This is a description of the makefiles which are provided with ARTE, the HERA-B Software environment, to compile and install as well the libraries as to compile and run the individual users program. To give general information about (GNU) make and makefiles is beyond the scope of this document. Please refer to the info files which should be part of any installation of GNU make.
Please note that the use of GNU make, often known as gmake, is mandatory. The native make provided by commercial UNIX systems will not work with the ARTE makefiles!
GNU make versions prior to 3.75 have been reported to cause trouble as well. To find out which version of make is installed on your system, type [g]make -v. If you get an error, you're not running GNU make. Otherwise it will show the version number.
To make the understanding of the following more easy to the reader, I will give a few explanations of words often used in the context of make and makefiles. I am sorry for not being too short, but I think some knowledge is needed here.
To be technically exact, the dependencies of a rule may be targets of other rules which -as discussed above- need not correspond to files. In this case, the dependency is considered to be younger than the target, if it was "remade".
The aim of this following section is to give you an rough idea of the purposes of the different makefiles used in ARTE and their relations. If you just want to use the makefiles as a black box, there should be no need for you to read that section.
One base of the ARTE makefile concept are the settings of environment variables. Two of them already define the location of the makefiles: $HB should contain the full-path name of the directory containing the ARTE stuff on your system and $HBVERS refers to the ARTE version used, which is also the name of the corresponding subdirectory of your common ARTE directory. The use of the latter for the location of makefiles may be dropped in the future, when/if makefiles which do not depend on the ARTE version seem doable.
To glue the various makefiles together, the GNU make syntax is used which allows makefiles to be included into others like the C-Preprocessor does by the #include "filename" statement. The splitting into several makefiles is used to separate general defaults for all platforms like the names of the ARTE libraries, from the machine dependent ones like e.g. some compiler options and from the individual users choices. The following names and places are used:
Thus to use default settings, the user has just to use the inclusion of one ARTE makefile into the makefile in his working directory. In case he wants to override the defaults, the user has to go one step deeper and include Makefile.setup and Makefile.rules directly, to have the possibility to change the variables after setting the default values and before applying them. For usage information on this see below.
As for the modules, this is a bit more complicated, as the make command to create a library out of the sources is in general not given by a human directly but in the top-level makefile, which allows to say "make install" in the top level directory of the ARTE source code distribution and everything will be done to install the respective ARTE version. The information given for the users makefile is still valid, but some more non-default settings, (i.e. differing from those in Makefile.setup), which are common to all module makefiles are given by command line arguments to make to save the work to edit each makefile of all modules in case of the necessity to change them. To avoid accidently invoking make in a module directory without having those variables set, the default target in the module directory is a dummy one, reminding the user that this is not what this makefile was made for. Of course it is possible to copy the way the top-level makefile invokes make in the module directories.
If you want to install ARTE, you first of all have to get the sources and put them in an appropriate place. This is hopefully explained somewhere else.
Before doing anything else, some (shell) environment variables have to define some directories which are not the same on all machines: The most prominent one is $HB, whichs value is the directory containing all ARTE versions you currently have installed. For the whole set of variable refer to the file hbprofile.template, which is intended to be a template for a file (by convention called hbprofile) that each user on your system should source (i.e. run in his shell using the "." as command and the file hbprofile as argument).
Then cd into the directory whichs name is that of the ARTE version to be installed. In case you just want to install a released ARTE version, giving the command "[g]make install" should be enough.
Please note, that the major feature of the target "install" is not to create/update the dependencies!
In case you are not sure whether source files have been changed since the last running of make (this should happen only to developers), you better run just "[g]make" without any arguments. This will remake the list of dependencies each time the command is run.
In case you really know what you are doing, you can run "make depend" once to update the dependencies and then run only "make install" to save the time it needs to update the dependencies. Please do this only if you are really understand what is written here!
If you want to apply one of these steps to just one module you can
use rules which are triggered by the respective targets:
(Replace <module> by the modules name)
This previous takes us to the usage of the provided makefiles for developing ARTE modules. In principle, as mentioned above, the modules directory already contain a Makefile that is suitable to rebuild the respective module. This should also be valid if the whole stuff is copied to the developers home directory. He/She has just to set the variables defining the places of object files and the resulting library. My recommendation is to use a Makefile of his/her own, that is used to build the executable the module is tested with, and have a rule there which invokes make recursively in the module directory. The whole setup is shown in the Users Makefile Section.
Special care must be taken to the place and access to the include files. As we are using the modules name as part of the path in the include statement itself, the include files of the development version must be seen inside such a directory also when developing them. Thus a directory (a symlink will do) with the modules name has to be created inside a directory that comes first in the order of include directories for the module and the test program as well.
It seems, that it would have been more sensible to omit this part of the path in the include statement for the include files which belong to the module itself. However, you as a module developer are able to do this, I expect it to work without problems. If you do this, I would be glad to hear of your experience.
If you are going to use the ARTE makefiles as a black box, all you should know about "make" is, that it uses the file "Makefile" for instructions what to do and that it has three types of arguments:
There are a few places where you should edit the template Makefile you find in the ARTE distribution:
The default target (i.e. if you don't specify one on the command line) of the makefiles of the ARTE distribution is to update the dependencies and to create the executable. The following targets are also defined:
(new in ARTE-01-09)
Please note, that in this case, typing just "
make executable debug=g
make runonly" will most propable run your optimized (i.e. non-debugging) executable, you have to start it also with "
Please note that the formerly used variables copt,lopt etc. not only have become obsolete, but will NOT work on makefiles of ARTE-01-08-r2 or later! The decision to abandon these has mainly two reasons: It seemed, that there would be more and more variables that need to be user extendable, thus the Makefiles would become more and more complex by adding new (user) variables and the users in need of such extensibility had to wait for the next makefile version until their requests are fulfilled. On the other hand, such additional user variables would never allow the user neither to choose the order of his additions with respect to the predefined ones, nor to not use a default options without having his/her own version of the "common" Makefile.hb. The solution was to divide this Makefile.hb into one part that sets the default values and one part that applies the values, thus giving the user the possibility to change the default values in between.
I assume, you need to change the defaults defined by the standard Makefile. Otherwise you need not read this section. Also I assume, that you are using one of the default users makefiles to start with.
First off all, you have to use two include statements for the general Makefiles instead of one. Replace
include $(HB)/$(HBVERS)/makefiles/Makefile.setup include $(HB)/$(HBVERS)/makefiles/Makefile.rulesif you haven't done so yet. Now you can change the values set by Makefile.setup before the values are used in Makefile.rules. The variables corresponding to copt, fopt and lopt are ccopt, f77opt and linkopt respectively. You should not set from scratch any of the variables that are described here! The idea is to alter the values, thus allways taking into account possible future changes in their default values defined by Makefiles.setup. This means e.g. to use
linkopt := /my/path/libmylib.a $(linkopt)instead of
lopt := /my/path/libmylib.aIf you don't want to extend the options, but to change an option, you can use one of the substitution features of the GNU make syntax. As example, replace the optimization level of the C compiler from the default -O2 to -O4 by
ccopt := $(patsubst -O%,-O4,$(ccopt))This will give you all default options defined in Makefile.setup but the optimiztion level which will be set to -O4 regardless of its default.
The variables that you most likely need to change (if any) are
If you look into the distributed makefiles Makefile.setup and Makefile.rules you might find same more variables, but I recommend to use only those listed here, as the meaning and names of the undocumented variables may change without notice! If you feel that another variable should be fixed to allow users to change it whithout causing possible incompabilities with further versions of our distributed Makefiles, please contact me (PJW, <firstname.lastname@example.org>)
makedependbecause you have to many source-files, than the following, appended at the end of your makefile will help, althought is slows updating of the dependencies down:
depend: largedepend @exit 0 # prevent make from executing previously found commands @ # for this target
If you want to do more fancy stuff, e.g. have several connected projects updated with one Makefile, make the settings of variables host name dependend, ... or just learn more about GNU make, please look into the respective info pages, which are the official documentation of GNU make and can be read with Emacs by typing 'C-h i' or (if "make" is not listed there)'M-1 C-h i <path>/make.info<RETURN>'.
If you want to use a library 'libfoo.a' and corresponding include files that are not foreseen in the ARTE distribution, you could put them to directories $HOME/myarte/$HBBINTYPE/lib and $HOME/myarte/include respectivly. Now the respective part of your Makefile could look like this:
include $(HB)/$(HBVERS)/makefiles/Makefile.setup libdir := $(HOME)/myarte/$(HBBINTYPE)/lib # define libdir incdirs := $(HOME)/myarte/include $(incdirs) # extend incdirs linkopt := -lfoo $(linkopt) # extend linkopt include $(HB)/$(HBVERS)/makefiles/Makefile.rules
The most propable real-world example of a tailored Makefile beyond just changing some compiler/linker options I can imagine is that of a module developer having one source tree for his/her module and one for the test programm. Ofcourse it is conveniant to update everything up to the test executable after some changes of any source code. Therefor a developers Makefile could for instance look like this:
# Assume the modules name is "gean" mylib = $(libdir)/libgean.a # Tell make to update the executable if the library has changed $(bindir)/$(exename): $(mylib) # Tell make how to check and update the library if neccessary # Assume geandir to contain the directory name of the developers # module version # "lib" is the target name used in the modules directory of the # ARTE distribution, let's assume it's used here as well. # MAKE is the variable containing the name of the make program you are # using, i.e. "make", "gmake" or whatever. Of course it's sensible to # use the same here. $(mylib): $(MAKE) -C $(geandir) lib include $(HB)/$(HBVERS)/makefiles/Makefile.setup # prepend the list of include directories by the developers module # include directory to make sure that include files like # "geant/..." are found in that directory first. incdirs := $(myincdir) $(incdirs) # replace the default module with the developers version when linking linkopt := $(patsubst -lgean,$(mylib),$(linkopt)) include $(HB)/$(HBVERS)/makefiles/Makefile.rulesThis requires the directory given by $(geandir) to contain a makefile that updates the library itself if make is run in this directory. The makefiles used in the ARTE source distribution to build the module libraries can be used for that purpose.
When the ARTE makefiles create a new directory, they use a
hbmkdir to create it recursively. Not to annoy
you with unwanted directories, it stops and asks you whether to
create this directory. Of course you will run into trouble, when
answering "no" at most points . But you might want to stop the
whole procedure by <ctrl-c> to change your settings and
restart it. However, if you don't want to be asked at all, you
should create a file
.hbmkdirrc in your home
directory and put a line with the word
The GNU make which has to be used for the ARTE makefiles has an
-s' which makes it run "silent". This means
not to produce informational output, only errors are shown. The
scripts used by the ARTE makefiles, e.g. to create directories
hbmkdir) or to print additional information
hbecho), recognise this and are "silent" themselves.