Makefiles for ARTE-01

Contents

Introduction

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.

make
This is the command which does the job. As we are using GNU make, this is oft called as gmake not to confuse it with the hardware vendors make, which is often called as make by default.
Makefile
For the purpose of this document, we can assume the makefiles to be a kind of scripts, in which variables are used and compilers, linkers etc. are invoked.
target
This is the word given in the make command line which defines what of the possible actions described in the makefile should be taken.
Traditionally, this is the name of the file to be created by the make call, hence the name target. However, make itself does not know which files it is creating. Therefore a fictional name as e.g. run can be given to trigger a program execution that does not create any file or none whose name is related to that of the target. Still the term target is used. Calling make with no target as a command line argument means just using the default target, which is the first one listed in the makefile.
dependency
The power of make is to execute only those commands which are actually needed to update some file that depends on others. A typical example is that the linking of object files to an executable is only necessary, if at least one of the object files changed since this was done the last time. On the other hand, recompiling a source file is necessary not only if itself has been changed but also if any of the used include files has been changed. Those files a target depends on are called dependency. Of course this can be chained: the object files, which are dependencies of the executable, are targets themselves that depend on their respective source files and their include files.
rule
A rule combines a target and its dependencies with the commands to be run when this target has to be "remade". (Using this term as applicable in case the target is a filename). As targets for which rules exist can be templates, the same rule can be triggered by different target names.

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.

Concept

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.

Installing ARTE & module development

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.

Setting up the environment

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).

Installing ARTE

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)

Thus, to "play it save" you should use the commands

Module Development

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.

Using ARTE

Basic Terms

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:

options
These are the typicall UNIX options starting with a '-' and steering how "make" should behave in general. The only option a "black box user" might want to use is most propably '-s' meaning 'silent' which cuts the output of progress information to the screen down to a minimum. These options are defined by the authors of GNU make and not subject to this documentation.
targets
This is the most important argument. It tells make which part(s) of the Makefile to execute. There is allways a default if none target is given.
variable settings
This allows the user on invocation of "make" to override some default settings of variables used by make. Command line arguments containing a '=' are recognized as variable settings. An example within the context of ARTE is the variabel "debug" which steers wether the object files are optimized or contain debugger information. The default is to create optimized compiler output, if you want to have debugging information, you might want to say "debug=g" on the make commandline. (The alternative is to set this in the makefile, see below)

Configuring your makefile

There are a few places where you should edit the template Makefile you find in the ARTE distribution:

HBVERS=
Please insert here the ARTE version, you want to use, e.g. ARTE-08-01
kumac=
Please specify here the name of your .kumac file (without the .kumac suffix!)
debug=
If you want to have debugging information in your object files by default, set this to 'g'. The default is 'n', which means to have optimized object files.
artedebug=
(Not in the template makefile)
Use this, if you want (or don't want) to use ARTE libraries with debugging information differently from what you set for your object files. It defaults to the value of debug.
Main use for this is propably setting it to 'n', if debug is set to 'g', but ARTE libraries with debugging information are not available.

Running make

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:

run
Update everything and run the executable


    
runonly
Just run the existing executable, don't compile and link it.


    
runonly_<kumacname>
run executable with kumac script <kumacname>.kumac


    
executable
Create the executable (Does not update the dependencies!)


    
run_<kumacname>
Create the executable (Does not update the dependencies!) and run it with kumac script <kumacname>.kumac


    
lib<name>.a
Create a library in the library directory (given by makevariable libdir) from all source files in the source directories.


   
clean
removes all objectfiles from your objectdirectory which can be remade from existing sources. Optional the executable is removed as well. Note however, that libraries created by you will not be removed.


   
empty
like clean, but prompts you additionally for object files, for which no sources seem to exist.
 (new in ARTE-01-09)
Apart from giving a target, you can set makefile variables in the command line. E.g. if you want to run make just once to produce an executable containing debugging information, you do not need to edit your makefile, but you can type:
make executable debug=g
Please note, that in this case, typing just "make runonly" will most propable run your optimized (i.e. non-debugging) executable, you have to start it also with "debug=g".

The Users Makefile

"Preface"

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.

Changing the defaults

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.hb
by
include $(HB)/$(HBVERS)/makefiles/Makefile.setup
include $(HB)/$(HBVERS)/makefiles/Makefile.rules
if 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.a
If 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.

Usable variables

The variables that you most likely need to change (if any) are

incdirs
List of include file directories. Please note, that this variable has to be changed before any of the compiler options!
libdir
Directory to create in and to search for your own libraries.
ccopt
Options to the C compiler
cxxopt
Options to the C++ compiler
f77opt
Options to the Fortran77 compiler
linkopt
Options to the linker

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, <weyers@ifh.de>)

Changing default targets

There should in principel no need to change the default targets. However, if you run into trouble with makedepend because 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
    

Further Configuration

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>'.

Examples

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 variables like libdir set here)
# 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.rules

   
This 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.

Hints

When new directories are created ...

When the ARTE makefiles create a new directory, they use a script 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 noquestion in it.

If you don't want to see all the output ...

The GNU make which has to be used for the ARTE makefiles has an option '-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.


Peter J. Weyers
Last modified: Fri Aug 27 1998