jam [ -a ] [ -g ] [ -n ] [ -q ] [ -v ] [ -d debug ] [ -f jambase ] [ -j jobs ] [ -o actionsfile ] [ -s var=value ] [ -t target ] [ target ... ]
Jam is a program construction tool, like make(1).
jam, the Jam executable program, recursively builds targets from source files using dependency and build specifications defined in Jam build scripts, written in jam's own interpreted language. jam parses the build scripts to identify targets and sources, examines the filesystem to determine which targets need updating, and issues OS commands to update targets. The build scripts consist of the Jambase which is distributed with jam and provides a boilerplate dependency information and updating actions for common use. It relies on the user-provided files named "Jamconfigure" and "Jamfile", to define the build configuration and to enumerate actual targets and sources. The build process is arranged in a several steps, normally consisting of a build configuration step, followed by a build step and finally a deployment or installation step.
The Jambase is described in the Jambase Reference and the document Using the Jambase.
If target is provided on the command line, jam builds target; otherwise jam builds the target 'all'.
Jam may be invoked with the following options:
-a
| Build all targets anyway, even if they are up-to-date. |
-d n
| Enable cummulative debugging levels from 1 to n.
Interesting values are:
|
-d +n
| Enable debugging level n. |
-d 0
| Turn off all debugging levels. Only errors are emitted. |
-f jambase
| Read jambase instead of using the built-in Jambase. Multiple -f flags are permitted. |
-g
| Build targets with the newest sources first, rather than in the order of appearance in the Jambase/Jamfiles. |
-j n
| Run up to n shell commands concurrently (UNIX and NT only). The default is 1. |
-n
| Don't actually execute the updating actions, but do everything else. This changes the debug level to -dax. |
-o file
| Write the updating actions to the specified file instead of running them (or outputting them, as on the Mac). |
-q
| Quit quickly (as if an interrupt was received) as soon as any target build fails. |
-s var=value
| Set the variable var to value, overriding both internal variables and variables imported from the environment. |
-t target
| Rebuild target and everything that depends on it, even if it is up-to-date. |
-v
| Print the version of jam and exit. |
The Jambase defines rules and variables which support standard software build operations, like compiling, linking, etc. When jam is invoked, a file named Jambase will be looked for in the project root directory, that is the entry point to the Jambase. The actual Jambase resides in a directory named "jam", also located in the project root directory.
When the Jambase is loaded, jam reads up to three other user-defined files from the project root, the Jamconfigure script, the Jamfile and the Jamrules. All three are written in the jam script language. The file Jamconfigure is mandatory and describes the build configuration. The Jamfile describes what to do with the source files in its directory. It may also cause Jamfiles in other directories to be read. The Jamrules file is generated when the Jamconfigure script is executed in the configure step and contains a set of project-specific rule and variable definitions. The first Jamfile normally causes the Jamrules file to be read, when it calls the SubDir rule.
Two scripts come with the jam distribution that simplify boostrapping the build process. One script named jam.sh runs on posix compatible build hosts, the other one named jam.bat runs on windows based build hosts. These scripts bootstrap and run the jam executable, so that jam executables do not have to be included for all possible build hosts, but rather built on demand. A precompiled version for windows hosts is distributed with the scripts named jam.exe.
The build process usually consists of several steps, such as:
The build must be configured before any other build steps can be performed. Build configuration is started when jam is executed for the target named "configure" and a log is written to a file named Jamrules.log. The result of the configuration is the Jamrules file, which in turn is loaded at the begin of the build step. Before the user-defined tests are executed, the built-in tests are always run to detect some basic capabilities of the build host platform for example how to delete files or create directories. The Jambase will then read in a file named Jamconfigure, which describes the project-specific configuration i.e. wich tests are run to determine if all required dependencies, such as system headers and libraries are present.
After sucessful build configuration, the actual build can be started. For this, the Jamfile is read, which describes which targets are built from the source files etc. The Jamrules file is read by the first Jamfile when the SubDir rue is called for the first time, which is usually as the first statement in a Jamfile. The build step is initiated when jam is executed for a build target (no target implies the target "all", which updates all build targets).
The build can be cleaned up, i.e. all built targets can be removed by the clean step. Running jam for the "clean" target will work without error even if the build has failed or not all build targets are present for other reasons. The Jamfile provides information what files can be cleaned up.
When targets have been built sucessfully, they can be installed. This is done by running jam for the target 'install'. The Jamfile also has to provide information what files are to be installed. The target named "uninstall" will remove any previously installed targets.
The Jam program has four phases of operation: start-up, parsing, binding, and updating. These phases are performed whenever the jam program is executed to perform a build step. Do not confuse the four phases of operation with the steps of the build process.
Upon start-up, jam imports environment variable settings into jam variables. Environment variables are split at blanks with each word becoming an element in the variable's list of values. Environment variables whose names end in PATH are split at $(SPLITPATH) characters (e.g., ":" for Unix).
To set a variable's value on the command line, overriding the variable's environment value, use the -s option. To see variable assignments made during jam's execution, use the -d+7 option.
All command line options are also passed to the jam build scripts in a global variable named ARGS.
In the parsing phase, jam reads and executes the Jambase file, by default the built-in one. It is written in the jam language. See Language below. The Jambase reads (via the "include" rule) the a user-provided files called "Jamconfigure" and "Jamfile".
Collectively, the purpose of the Jambase, Jamconfigure and the
Jamfile is to name built targets and source files, construct the
dependency graph among them, and associate build actions with targets.
The Jambase defines boilerplate rules and variable assignments,
and the Jamconfigure and Jamfile uses these to specify the actual
relationship among the target and source files. See the Jambase Reference and the document Using the Jambase for information.
Binding
A file target's identifier is generally the file's name, which can be absolutely rooted, relative to the directory of jam's invocation, or simply local (no directory). Most often it is the last case, and the actual file path is bound using the $(SEARCH) and $(LOCATE) special variables. See SEARCH and LOCATE Variables below. A local filename is optionally qualified with "grist," a string value used to assure uniqueness. A file target with an identifier of the form file(member) is a library member (usually an ar(1) archive on UNIX).
The use of $(SEARCH) and $(LOCATE) allows jam to separate the the location of files from their names, so that Jamfiles can refer to files locally (i.e. relative to the Jamfile's directory), yet still be usable when jam is invoked from a distant directory. The use of grist allows files with the same name to be identified uniquely, so that jam can read a whole directory tree of Jamfiles and not mix up same-named targets.
After binding, jam again recursively descends the dependency graph, this time executing the update actions for each target marked for update during the binding phase. If a target's updating actions fail, then all other targets which depend on that target are skipped. The updating phase is not important for the configure build step, where no dependency graph is set up.
The -j flag instructs jam to build more than one target
at a time. If there are multiple actions on a single target,
they are run sequentially. The -g flag reorders builds so that
targets with newest sources are built first. Normally, they are
built in the order of appearance in the Jamfiles.
Jam Build Scripts
Jam build scripts contain rule invocations, which usually look like:
RuleName targets : targets ;The target(s) to the left of the colon usually indicate what gets built, and the target(s) to the right of the colon usually indicate what it is built from.
Elements in jam scripts are delimited by whitespace (blanks, tabs, or newlines). Elements to be delimited include rule names, targets, colons, and semicolons. A common mistake users make is to forget the whitespace, e.g.,
Main myprog: main.c util.c ; #WRONG!Jam doesn't distinguish between a typo and a target called "myprog:", so if you get strange results, the first thing you should check for in your Jamfile is missing whitespace.
A Jamconfigure script can be very simple:
ConfigureCc ; ConfigureC++ ;This specifies that the C and C++ compiler should be configured. The rules named ConfigureCc and ConfigureC++ do not require any arguments, therefore the statement consists just of the rulename followed by a semicolon. The build can then be configured by executing:
jam configure
A Jamfile can be as simple as this:
SubDir ; Main myprog : main.c util.c ;The first statement in a Jamfile is usally the first call of the SubDir rule. This causes the previously generated Jamrules to be read and it sets the directory context of all following build rules, e.g. in where the sources can be found. This Main rule specifies that there is a main.c and util.c file in the same directory as specified by the SubDir rule, and that those source files should be compiled and linked into an executable called myprog. If you cd to the directory where this Jamfile lives, you can see the exactly how jam would build myprog with:
jam -nOr, you can actually build myprog with the command:
jam
Consider this Jamfile:
SubDir ; Main myprog : main.c util.c ; LinkLibraries myprog : tree ; Library tree : treemake.c treetrav.c ;
The Main rule specifies that an executable called myprog will be built. The compiled main.c and util.c objects will be linked to produce myprog. The LinkLibraries rule specifies that tree will be linked into myprog as well. The Library rule specifies which source files will be compiled and archived into the tree library.
The Jamfile above refers to targets like "myprog" and "tree". However, depending on the platform you're building on, the actual filenames of those targets could be "myprog.exe" and "tree.lib". Most Jambase rules supply the actual filenames of targets, so that Jamfiles themselves need not make any platform-specific filename references.
The jam program builds up a list of unique target identifiers. The default identifier for a file target is its filename prefixed with the path specified by the SubDir rule. In the above example, the target identifiers are simply the filenames: myprog.exe, tree.lib, main.obj, etc.
You can use any buildable target on the jam command line to build a subset of defined targets. In our example:
jam libtree.aon Unix builds the libtree library and all the compiled objects that go in it.
While most Jambase rules refer to "targets", not all targets are buildable. There are two kinds of buildable targets: file targets and pseudotargets. File targets are objects that can be found in the filesystem. Pseudotargets are symbolic, and represent other targets. Examples for preudotargets are "configure" or "install", which start the configure step and the install step, respectively.
Most Jambase rules that define file targets also define pseudotargets which are dependent on types of file targets. For example, Jambase defines a pseudotarget called "clean", which is dependent on all targets created in the build step. So the command:
jam cleanused with the above example would cause the program myprog, the tree library, and all object files to be removed and thus clean the build. Also, there is one pseudotarget built into jam itself, called "all". Jambase sets "all" dependent on (almost) all other targets.
In the unfortunate case where you have a buildable target whose name is the same as one of the Jambase pseudotargets, you'll have problems with the conflicting target name. Your workaround choices are:
File lib : libfoo.a ;try
File <dir>lib : libfoo.a ;
Jambase rules set dependencies on targets, so that if you update a source file, all the file targets that depend on that source file, and only the ones that depend on that source file, will be updated (rebuilt) the next time you run jam.
Here are some of the dependencies that get set when jam runs on NT using the example Jamfile above:
Target | Depends on | |
myprog.exe | main.obj, util.obj, libtree.lib | |
libtree.lib | treemake.obj, treetrav.obj | |
treetrav.obj | treetrav.c |
Furthermore, the Main and Library rules set up recursive header scanning on their source targets. So after jam has finished parsing the Jamfile and setting the rule-driven dependencies, it scans the source files for "#include" lines. All #include files found during this scan become dependencies of the compiled object. E.g., all header files used to compile treetrav.c would be made dependencies of treetrav.obj.
As a result, when you run jam, it will rebuild targets if either the source files change or the header files change. You can't tell by looking at a Jamfile which header files are dependencies, but you can easily display those dependencies with:
jam -nd+3
Rules that define a target, like the Main, Library and SharedLibrary rule must be invoked before any other rule using the same target is invoked. For example, the LinkLibraries rule for the target myprog must be called after the Main rule defined the target myprog. However, do not expect the actions to be executed later in the order the rules were invoked, as the rules only specify dependencies and jam figures out the order in which targets are built from their dependencies.
Some rules, set variables which are used by subsequent rule invocations, and their ordering is important. For example, the SubDir* rules (discussed later) must be invoked in a particular order.
In addition to generic error messages, jam may emit one of the following:
|
The -j flag can cause jam to get confused when single actions update more than one target at a time. jam may proceed as if the targets were built even though they are still under construction.
For parallel building to be successful, the dependencies among files must be properly spelled out, as targets tend to get built in a quickest-first ordering. Also, beware of un-parallelizable commands that drop fixed-named files into the current directory, like yacc(1) does.
With the -j flag, errors from failed commands can get staggeringly mixed up.
A poorly set $(JAMSHELL) is likely to result in silent failure.