Basic Jam Usage

Usage

jam [ -a ] [ -g ] [ -n ] [ -q ] [ -v ]
    [ -d debug ] 
    [ -f jambase ] 
    [ -j jobs ] 
    [ -o actionsfile ] 
    [ -s var=value ] 
    [ -t target ] 
    [ target ... ]

Description

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.

Command Line Options

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:
1
Show actions and summary info (the default)
2
Show "quiet" actions and display all action text, as they are executed
3
Show dependency analysis, and target/source timestamps/paths
4
Show arguments and timming of shell invocations
5
Show rule invocations and variable expansions
6
Show directory/header file/archive scans, and attempts at binding to targets
7
Show variable settings
8
Show variable fetches, variable expansions, and evaluation of '"if"' expressions
9
Show variable manipulation, scanner tokens, and memory usage
10
Show profile information for rules, both timing and memory
11
Show parsing progress of Jamfiles
12
Show graph of target dependencies
13
Show change target status (fate)
-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.

Required Files

The Jambase

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.

Project Specific Jam Scripts

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.

Jam Executable Wrappers

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.

Build Process Layout

The build process usually consists of several steps, such as:

  • Build configuration
  • Building the targets
  • Cleaning the build
  • Installing targets
  • Uninstalling targets
The build steps are triggered by the targets configure, clean, all, install and uninstall.

Build Configuration

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.

Building Targets

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

Clean Up

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.

Installation and Deployment

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.

Program Execution

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.

Start-up

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.

Parsing

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

Binding
After parsing, jam recursively descends the dependency graph and binds every file target with a location in the filesystem. The binding phase is not important for the configure step, where no dependency graph is set up.

Targets
Any string value in jam can represent a target, and it does so if the DEPENDS or INCLUDES rules make it part of the dependency graph. Build targets are files to be updated. Source targets are the files used in updating build targets. Build targets and source targets are collectively referred to as file targets, and frequently build targets are source targets for other build targets. Pseudotargets are symbols which represent dependencies on other targets, but which are not themselves associated with any real file.

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.

Update Determination
After binding each target, jam determines whether the target needs updating, and if so marks the target for the updating phase. A target is normally so marked if it is missing, it is older than any of its sources, or any of its sources are marked for updating. This behavior can be modified by the application of special built-in rules. See Modifying Binding below.

Header File Scanning
During the binding phase, jam also performs header file scanning, where it looks inside source files for the implicit dependencies on other files caused by C's #include syntax. This is controlled by the special variables $(HDRSCAN) and $(HDRRULE). The result of the scan is formed into a rule invocation, with the scanned file as the target and the found included file names as the sources. Note that this is the only case where rules are invoked outside the parsing phase. See HDRSCAN and HDRRULE Variables below.

Updating

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.

Jamconfigure

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

Jamfile

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 -n
Or, you can actually build myprog with the command:
    jam

Filenames, Target Identifiers, and Buildable Targets

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.a 
on Unix builds the libtree library and all the compiled objects that go in it.

Pseudotargets

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 clean
used 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:

  1. Change the name of your buildable file or directory that conflicts.

  2. Modify your Jambase and change the name of the conflicting pseudotarget. (Pseudotargets are defined in Jambase using the NOTFILE rule.)

  3. Use grist on the conflicting target name in your Jamfile. E.g., instead of
            File lib : libfoo.a ;
        
    try
            File <dir>lib : libfoo.a ;
        

Dependencies

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.exemain.obj, util.obj, libtree.lib
libtree.libtreemake.obj, treetrav.obj
treetrav.objtreetrav.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

Rule Ordering

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.

Diagnostics

In addition to generic error messages, jam may emit one of the following:

warning: unknown rule X
A rule was invoked that has not been defined with an "actions" or "rule" statement.

using N temp target(s)
Targets marked as being temporary (but nonetheless present) have been found.

updating N target(s)
Targets are out-of-date and will be updated.

can't find N target(s)
Source files can't be found and there are no actions to create them.

can't make N target(s)
Due to sources not being found, other targets cannot be made.

warning: X depends on itself
A target depends on itself either directly or through its sources.

don't know how to make X
A target is not present and no actions have been defined to create it.

X skipped for lack of Y
A source failed to build, and thus a target cannot be built.

warning: using independent target X
A target that is not a dependency of any other target is being referenced with $(<) or $(>).

X removed
Jam removed a partially built target after being interrupted.

Bugs, Limitations

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.