SLAC PEP-II
BABAR
SLAC<->RAL
Babar logo
Workbook HEPIC Databases PDG HEP preprints
Organization Detector Computing Physics Documentation
Personnel Glossary Sitemap Search Hypernews
Unwrap page!
Wkbk. Search
Wkbk. Sitemap
Introduction
Non SLAC
HOWTO's
Introduction
Logging In
QuickTour
Detector
Info Resources
Software Infrastructure
CM2 Introduction
Unix
OO
SRT
Objectivity
Event Store
Framework
Beta
Modifying Code
Writing and Editing
Compiling
Debugging
Analysis
Framework II
Analysis
Find Data
Batch Processing
PAW
PAW II
ROOT I
ROOT II
ROOT III
Advanced Infrastructure
New Releases
Workdir
Main Packages
Event Displays
Gen/Sim/Reco
Contributing Software
SRT and CVS
Coding
Advanced Topics
Make CM2 Ntuples
New Packages
New Packages 2
Persistent Classes
Java
Site Installation
Check this page for HTML 4.01 Transitional compliance with the
W3C Validator
(More checks...)

Workbook for BaBar Offline Users - Compile, Link and Run

Note: To follow this WorkBook page, you will need to have completed the Workbook section on Editing to create the PExample files needed. It is worth working through both of these sections carefully as they provide an excellent introduction to BaBar analysis code.

Also, before running, remember to do (from the release directory, ana30):

srtpath <enter> <enter>
cond18boot

Writing code in a unix environment involves the use of several tools. The two main tools are the compiler and linker. To see the results of the minor changes you have made will involve first compiling your new code, linking it, and then running the new executable.

A very important part of compiling and linking is patience - you must check the output from each stage to make sure there are no errors or other messages that hint at problems and often have to go back several times, clean up, recompile, relink, make sure you're on the correct machine, start again....


Introduction to gmake

An executable is built from the code defined in multiple files. When changes are made in one or more of these files the code in the modified files and all dependent files will need to be re-compiled and re-linked. Compile and link commands often involve many options, such as directory search paths for included files, names for compiled files, warning messages, debugging information and so forth. Compile and link commands quickly become quite lengthy, and in large software projects the dependencies amongst files is usually rather involved. A utility called gmake, is used to manage the complicated and tedious nature of this process.

GNUmakefiles

The gmake utility uses a programmer written file, called the GNUmakefile to define a set of instructions for how to compile and assemble the code segments into the executable. The file also defines many variables such as search paths, which compiler to use, etc. The instructions specify the dependencies of the code segments so that the gmake utility can recognize only those components that need to be reprocessed. A well written makefile can reduce unnecessary compilation and save much time.

The gmake facility looks in the current directory for a file named GNUmakefile, makefile, or Makefile (in that order). The first one of these files found is used to define the dependency/build rules for the given target.

Targets, Dependencies, and Build Rules

The general structure of an instruction in the GNUmakefile consists of a target, a dependency, and a rule. The target is in the name for that particular instruction. You execute the rules associated with a particular target by issuing the command:
   > gmake <target_name> 
This is referred to as "making" the target. Associated with each target is a set of dependent files. When any of the dependent files have been modified or if the target file does not exist, the target will be rebuilt (or built) in accordance with the rule. For example, a line in a GNUmakefile might be:
   foo.o : foo.cc foo.hh bar.hh
   	g++ -c foo.cc 
The target is foo.o, the dependent files are foo.cc, foo.hh, and bar.hh, and the rule is "g++ -c foo.cc". If any of foo.cc, foo.hh or bar.hh have been modified, or if the foo.o does not yet exist, issuing gmake foo.o will result in the recompilation of foo.cc in accordance with the rule. The default target is the first target listed in the GNUmakefile. It is the rule that will be executed when gmake is invoked without an argument.

Sometimes targets are used to perform tasks not related to compiling and linking code. If you define a target for which there is no file of the same name, and the rule commands do not create the target file, then a file of the target name will not exist in the directory. Because the target does not have a corresponding file it is always considered out of date; the rules will be executed every time the target is made. These targets are referred to as phony targets. Phony targets do not usually have dependent files.

A GNUmakefile is part of any release, including the test release you created. GNUmakefiles are also included in any package that you check out. The GNUmakefile of the release is the master makefile. This is why you issue gmake commands from the release directory. Commands issued from a subdirectory of a release will only have access to targets defined in the subdirectory's GNUmakefile (assuming there is one). The master makefile defines the target all that you made in the Quicktour analysis.

For general use of BaBar software, you will use gmake commands often, but you will probably not need to write or modify a GNUmakefile. Even users writing new analysis modules rarely need to make significant modifications to a GNUmakefile.

Related documents:

  • HOWTO-GNUmakefile - specific information about the BaBar GNUmakefile from the SoftRelTools package
  • GNU make manual - describes gmake and all of its subtleties in detail.
  • If you are interested you can browse the GNUmakefile that came with your test release.

Time stamps

gmake relies on time stamps to determine what needs to be redone. The Makefile (or GNUmakefile) for a given package knows about the dependences between all the files. If a given file is being compiled with a gmake command, any files that it depends upon and that are newer than it will also be compiled. Therefore, if file X is newer than file Y, but Y depends on X, recompiling Y will force a recompilation of X, and any other files that might have been edited since Y was last touched.

As such, to force a file to be recompiled, you may need to manually "touch" one of the relevant files. An example of such a command is:

  touch BetaMiniUser/AppUserBuildBase.cc
which will force AppUserBuildBase.cc to be recompiled. In this case, this will cause almost the entire package to recompile as almost all the other files in the package depend on AppUserBuildBase.cc.

Link files

In BaBar software each package includes a link_PACKAGE.mk file in addition to the GNUmakefile. The link file is used by the GNUmakefile. The use of this file is mainly for overriding previous definitions of linking rules defined by the test release's GNUmakefile. This overriding mostly serves to append the new package directory to the linking list. More information on this can be found in the HOWTO package in HOWTO-dependency.

The all target

In the Quicktour, you used the command "gmake all" to compile and link your code. The all target is a "smart" target that makes all of the targets you need (and some that you may not need) in the correct order. The targets made by gmake all are:
  • installdirs - Creates the required architecture-specific directories (for example, lib/$BFARCH and bin/$BFARCH).
  • database.import - A database command. Creates a local copy of a database and its bootfile. (But it will not work unless you have made your .bbobjy file.)
  • schema - A database command. Sets up class definitions for a database.
  • include - Makes any needed include files.
  • lib - Compiles the code.
  • bin - Links the code.
  • javalinks - Support for java.
  • python - Support for python.
Some of these targets are needed for a sucessful compile and link. "gmake include" takes care of dependencies. "gmake lib" compiles the code, and "gmake bin" links it. And the first command, "gmake installdirs", creates the $BFARCH directories needed to store the files created by the include, lib and bin targets.

On the other hand, as mentioned in the Quicktour, many of these targets are not needed for your simple BetaMiniUser job. For example, the database commands are needed only if you are planning to set up your own federated database, which is unlikely unless you are an advanced user running simulation software. Also, the javalinks and python targets are not really needed here. They are included in gmake all to ensure that the targets are made in the right order for users who do need them.

The installdirs target

Different machine architectures have different compiled formats. To keep object files of different architecture formats separate the lib and bin directories have a subdirectory for each architecture that you compile code on.

The command that makes these subdirectories is gmake installdirs. A new test release comes with lib, bin, tmp and test directories, but they are all empty. The command gmake installdirs creates a subdirectory called $BFARCH in each one of these subdirectories. Here $BFARCH is the architecture that you chose when you entered the srtpath command; for example, Linux24SL3_i386_gcc323.

The include target

The include target creates any include files needed.

The lib target

The command to compile your code is gmake lib.

When you compile your C++ code a preprocessor is run first. As discussed in editing code, the preprocessor does such things as prepend header files and execute macro definitions. In addition, the dependencies among the files are recorded in files with the same root as the source file and a '.d' suffix. In BaBar software these files are stored in the tmp directory of your release.

After precompilation regular compilation takes place. This converts the file into a re-locatable, architecture-dependent version of the source code. The result of this step is called an object. The object files also have the same root name as the source file with a '.o' suffix. Object files are also stored in the tmp directory of your test release.

These object files are swept into archive libraries. Libraries are stored in the lib directory of your release and have a '.a' suffix.

Like the lib and bin directories, the tmp directory has a subdirectory for each architecture that you compile code on.

The bin Target

This command makes all of the bin targets in all of the packages in your test release. The new executables are located in your bin/$BFARCH directory.

Once object modules have been created they need to be linked together to build the executable. The command to link your code is gmake bin. This command makes all of the bin targets in all of the packages in your test release. The new executables are located in your bin/$BFARCH directory. If you list this directory, you will see a '*' after the names of most of the files, indicating that they are executables.

For the BetaMiniUser package the executable is named BetaMiniApp. This is the only one that you actually need.

Starting clean: the clean target

In a moment you will use the gmake all command to recompile and relink your code to incorporate your new PExample. But first, you will enter the gmake clean command.

When issued from your test release directory, gmake clean will delete the files in the directories: bin, lib, tmp, test, and results for all architectures. This removes all object files, libraries, and the executable from your release so that you may restart the compilation and building process of the executable from a "clean" state.

If do a "gmake clean", then you will have to reenter all of your gmake commands before your code will work again. In this case, this means that you will have to reenter your gmake all command, as you will see below.

(On the other hand, gmake clean usually does not undo your gmake workdir.setup command, unless you accidentally issue gmake clean from workdir. If so, just go to your test release directory and reenter "gmake workdir.setup", and that should fix it.)

Another related useful target is cleanarch. The command gmake cleanarch command removes only library, binary and temporary files saved under the current architecture (i.e. the architecture set when you most recently issued an srtpath command in the current session). But it leaves the libraries and/or binaries for built with other architectures intact.

Example: Compile and link your new code

Now it is time to recompile and relink the code to incorporate the new PExample module and modification to AppUserBuildBase.cc into the executable. From your test release issue

  
ana30> gmake clean
ana30> rm all.log
ana30> bsub -q bldrecoq -o all.log gmake all ROPT=-noOptimize-Debug
Note: you should use the bldrecoq queue only for building libraries and executables, not for running analysis jobs.

You can see the output in all.log. Check your own output to make sure there are no error messages which must be fixed. When you look at your log file, note that the arrows "->" indicate which gmake command it is working on. So if your job crashes, you know which gmake command was running when it failed.

You may have noticed that the above command is a little different from the one you used in the Quicktour. In the Quicktour you typed:

ana30> bsub -q bldrecoq -o all.log gmake all 
without the "ROPT=-noOptimize-Debug". The default settings for the compiler and linker for this release are to retain symbols for debugging but also to optimize the code for fastest execution. In the next part of the Workbook, you will be using the debugger for your own code. This is most easily done if our code is not optimized, so that all variables are available in the debug session. The rest of the code in the release (ie, the packages that you did not check out) has already been compiled optimized, but presumably you will not be debugging the production code.

It is important to issue this command from the test release directory because that's where the GNUmakefile that defines the lib target resides. Check the output to verify that your code has compiled before going to the next step (linking).

Problems During Compile and Link

You may not have a successful compilation the first time. There are many common error messages that you will inevitably need to become familiar with.

Typical compile errors:

  • Errors with incorrect use of gmake.
  • Failure to find header file during precompilation,
  • Errors caused by lack of forward declaration/include statement in header/implementation file.
  • Reading between the lines: the line that the compiler says contains the error is often not the line where the actual mistake is.
  • Declarations of variables: multiple and lack of.
  • Loops within loops within loops. How to check those close brackets - e.g. smart editors like emacs.
  • Cascading errors: often, later errors are caused by earlier ones. Don't try to 'correct' everything before recompiling.

Typical linking problems:

  • The linker message "No rule to make target libPACKAGE.a"

  • Failure due to undefined/unresolved symbols

  • Got enough disk space for your executable?!

Often an error is due to a typo, or missing closed brace etc. Any errors will need to be interpreted, fixed in the source file, and then re-compiled. This is an iterative process until the compilation is successful.

A Shortcut: Compiling or linking only one package

So far, you have always used the command "gmake all" to compile and link your code. But if all you want to do is make the BetaMiniApp executable, then you need only some of the gmake commands invoked by "gmake all":

gmake lib
gmake BetaMiniUser.bin

Or you could put them together to make a single command:

bsub -q bldrecoq -o mylog.log gmake lib BetaMiniUser.bin
You will notice that the link command, gmake BetaMiniUser.bin, is a bit different from the gmake bin command that you used before. In general, commands of the form "gmake package.target" perform the task "gmake target" on the files in "package" only. The command "gmake BetaMiniUser.bin" to links only the code in BetaMiniUser. This is useful if you have a lot of packages checked out, because instead of making BetaMiniApp plus executables you don't need from the other packages, you make only BetaMiniApp.

Let's look at another example. Assume that you have checked out:

BetaMiniUser
KanEvent
RecoDataK
and have made substantial changes to files in BetaMiniUser and a few in at least one of the other two packages. Assume also, that there are two binaries (i.e. executable files) that can possibly be built in the BetaMiniUser package, FirstApp and SecondApp, and that it takes a long time to compile the binaries. In the case that you care only about the SecondApp executable, a common series of commands would be:
gmake clean     //remove pre-editing libraries and other temporary files
gmake lib       //rebuild the libraries for all the packages
gmake BetaMiniUser.SecondApp  //build only the SecondApp executable
The gmake clean command removes the library and binary files and other auxilliary and machine-generated files that existed before the package was edited to avoid possible conflicts. The gmake lib command need remakes all the needed library files. Then gmake BetaMiniUser.SecondApp builds the SecondApp executable.

Using only the gmake commands that you need can save you some compile time, and avoids the creation of lots of unnecessary files. A word of caution, however: if you are going to skip parts of gmake all, make sure that you know what you are doing. If your job keeps crashing, try gmake all instead.

gmake options

The gmake command comes with a number of useful options. The command "gmake -n TARGET" doesn't actually run commands, it just prints them. For example, if you enter the command "gmake -n lib" from your ana30 directory, then you will get the following output:
GNU Make version 3.79.1,
Build OPTIONS = Linux24SL3_i386_gcc323-Debug-native-Objy-Optimize-Fastbuild-
Ldlink2-SkipSlaclog-Static-Lstatic
Linux yakut02 2.4.21-37.0.1.ELsmp #1 SMP Thu Jan 19 17:17:30 CST 2006 i686 
athlon i386 GNU/Linux  [uname -a]
echo "-> lib";
for package in xx BetaMiniUser KanModules database workdir; do if [ "$package" 
!= "xx" -a "$package" != "BASE" ]; then gmake  $package.lib NOPKG=yes; fi; done
If you can understand it, this message gives you an idea of what the gmake lib command would do if you entered it without the "-n" switch. However, if you check in your lib directory:
   ana30> ls -l lib/$BFARCH
you will not find any new lib files; only old lib files (if you have compiled before) or none at all.

Another useful gmake command is "gmake -k TARGET". This command tells gmake to keep going even when some targets can't be made.

To see a full list of options and a description of each one, enter "gmake --help" at the command line.


Running Your New Code

The PExample module code is compiled because it is located in the BetaMiniUser directory. It is linked into the executable because the AppUserBuildBase.cc file loads it into the framework. The final step is to include your newly-created module in your analysis application.

As discussed in the Beta section, the BetaMiniApp executable needs to be run from the workdir directory. Depending on the input data source, a tcl script is passed to the executable as an argument. The job is passed from tcl file to tcl file (via the "sourceFoundFile" command) until it is finished.

In the Quicktour, the snippet.tcl script was passed to BetaMiniApp as an argument. The snippet file performed some initiial setup, and then passed the job to MyMiniAnalysis.tcl, which did some more setup and added some modules to the framework's path ("Everything"). Then MyMiniAnalysis.tcl passed the job to btaMini.tcl, the main tcl file used to access the Mini database.

Now that you have created a new module class and compiled and linked the code, you will need to include the PExample module in your analysis path.

In the Quicktour analysis the file snippet.tcl is passed to the analysis executable. This file sources (or rather, "sourceFoundFile"s) a secondary tcl file called MyMiniAnalysis.tcl. It is in MyMiniAnalysis.tcl that your user-specific analysis path is defined. This is the file that should be modified to append PExample to the path instead of NTrkExample. This is a very simple edit, and because it is a tcl file and not C++ code, it is independent of compiling and linking your code.

A working example of a MyMiniAnalysis.tcl script that places the PExample module in the execution path is in the WorkBook's NewExamples/PExample directory.
The command

   ana30/workdir>  BetaMiniApp snippet.tcl
will run the executable BetaMiniApp. Now you will need to input collection(s) to KanEventInput, and start the job, as in the Quicktour:
    > mod talk KanEventInput
    KanEventInput> input add /store/SP/R18/001237/200309/18.6.0b/SP_001237_013238
    KanEventInput> exit
    > ev beg -nev 40
    > exit
When your job is done, go into ROOT and load the .root file as before. You should now see a directory for your new module:
TFile**         myHistogram.root        Created for you by RooTupleManager
 TFile*         myHistogram.root        Created for you by RooTupleManager
  KEY: TH1F     h1d1;1  MC reco abs mtm difference
  KEY: TH1F     h1d2;1  Reco track momentum
  KEY: TH1F     h1d3;1  Tracks per Event
  KEY: TH1F     h1d4;1  Momentum
  KEY: TH1F     h1d5;1  TagInspector Status
In addition to the histogram for tracks/event there is now a momentum histogram. Go ahead and plot it with the commands:
   root[] h1d4->Draw():
It should look like this:

root histogram

You might wonder whether or not the axes are ideal. In our example code the histogram axes are hard-coded. To change them would involve editing the code, recompiling, relinking, re-running, and re-analyzing. Basically you would need to do everything over. That is very time-consuming. Fortunately there is code available to make some parameters more dynamic and flexible than this. Instead of redoing everything we will discuss how to modify the PExample class to make certain parameters (of the histogram for example) changeable during the analysis process in the Framework Continued chapter.

Runtime gotchas:

Just because your code compiled and linked doesn't mean that everything will work as planned. For example, memory misuse errors may allow your code to compile and link sucessfully, but will cause problems at runtime.
  • Segmentation violations - accessing a null pointer?

  • Bus Errors - has the size of an object changed?

  • Something strange to do with memory allocation(especially on Sun) - remake from cold.

  • Further investigation/understanding of the problem - see the chapter on Debugging Code

Non-existent binaries

Missing binaries can catch you out in two ways:
  1. if your gmake bin command fails due to some compile-time error, the binary won't be made
  2. if you put your release in your scratch area (as in the Quicktour), and you haven't used your binary for some time (approximately a week), it will be deleted, as the scratch disk cleans out unused files
There are two ways in which a missing binary will manifest itself:
  1. The binary will simply not be found when you try to execute it
  2. A binary in the BaBar compiled code (in workdir/PARENT) will run, and none of your changes will be in it
In the second case, what happens is that the system searches for an executable in your bin/$BFARCH/ directory, and when it doesn't find one, it looks in the original analysis-30 release, finds the central, pre-compiled binary, and uses that one instead. This problem can be very difficult to spot - the code appears to run just fine, but none of your changes are in the output files!

In either case, the way to check things is to look at output from the compile and link stages and, particularly if it is just the case that you haven't tried to run your binary for some time, check the directories:

ls -l ana30/lib/$BFARCH/
ls -l ana30/bin/$BFARCH/
(There is also a link, "bin", in your workdir to ana30/bin.) If this directory does not contain the binary you wanted to run, then the binary hasn't been built, or has got old and been deleted.

Notes on Platform Variations

Mainly just to make the user aware of the fact that compiler and runtime behaviour is platform-dependent. Important example: incremental linking on Sun. Also, note that the same code that compiles or links on one platform may not do so on another.
General Related Documents:

Back to Workbook Front Page

Author: Tracey Marsh
Contributors: James Weatherall, Joseph Perl, Leon Rochester, Jenny Williams,

Last modification: 3 March 2006
Last significant update: 14 September 2005