The Jam build-tool provides a versatile, unified build process across many platforms including cross-compilation, build-configuration, automated unit-tests, and concurrent execution of build steps. This is a a step-by-step introduction to the Jam-based build system, demonstrating the usage of jam on a Windows NT build host, on POSIX-based systems such as UNIX, Linux, Mac OS-X or QNX and show how to cross-compile.
If jam is run without any arguments, default build options are attempted to be deduced from the environment. This will work well from a unix shell or the 'build command shell' provided by Microsoft visual studio installations.
To start a build with default build options simply change to the project root directory and execute the jam binary (-q means stop on first error). The command below builds the project on Windows when executed in the 'build command shell':
jam.exe -q
Accordingly, on POSIX systems, a script named jam.sh can be used to build the jam executable first and then the project in one simple step. The script builds the jam binary the first time it is executed and passes on any command-line arguments. The following command builds a project on POSIX hosts:
./jam.sh -q
NOTE:
After a checkout the jam-script may needs to be made executable with the chmod command:
chmod +x ./jam.sh
jam.sh program.bin
Some important pseudo-targets are named all, lib or exe. The target 'all' will build all targets in the dependency tree. 'lib' will build only libraries and 'exe' only exectuables, respectively. When jam is called without specifying any targets the pseudo-target 'all' is assumed. This is the same as explicitly calling jam to build the target 'all'. To build all libraries and their dependencies in a project, invoke jam like so:
jam.sh lib
jam.exe -a
A specific target can be rebuild by combining -a and a target name. The target program.bin will be completely rebuild with the following command:
jam.exe -a program.bin
jam.sh clean
jam.sh -q test
One important jam variable is named CONFIG and can be set to 'debug' or 'release' to build either a debug or release version of a project. To build a release version of a project, use the following command:
jam.sh -sCONFIG=release
Most variables have default values or are deduced from environment variables. The default for CONFIG is 'debug'. The following table gives an overview which jam variables are used to enable certain build options:
Target Operating System (TARGET_OS): nt, linux, qnxnto, wince, macox, solarix, aix
Target Platform (TARGET_OSPLAT): x86, ppc, arm, mips, sh4, sparc
Configuration (CONFIG): debug, release
Compiler/Toolchain (TOOLSET): vc7, vc8, vc9, gcc, icpp, qcc, xlc, sunpro, mingw
More than one variable can be set when jam is invoked. The following command builds a release version with the gnu compiler toolset on a POSIX host:
./jam.sh -sCONFIG=release -sTOOLSET=gcc
./jam.sh -sCONFIG=release
The default TOOLSET on a Unix host may not be gcc, but the compiler/linker of the respective vendor. For example, the default TOOLSET on AIX is the XLC compiler and the default TOOSET on Solaris is the Sun Workshop compiler. The Gnu compiler can be used on these systems by setting the TOOLSET to gcc explicitly.
jam.exe -sVISUALC="C:\Programme\Microsoft Visual Studio 2005" -sTOOLSET=vc8
If the special 'build command shell' is used, VISUALC is determined from other environment variables and does not have to be specified. Also, the TOOLSET is deduced from the environment and does not have to be specified. If the express version of Visual Studio 2005 is used, the path to the Platform SDK must be specified with -sPLATFORMSDK=path_to_PlatformSDK. To build with VisualC++ 2003, set the TOOLSET to vc7. It is not possible to build vc7 targets from the 'build command shell' provided by a Microsoft visual studio 8 installation or vice versa.
jam.exe -sVISUALC="C:\Programme\Microsoft Visual Studio 8"
-sTOOLSET=vc8 -sTARGET_OS=wince -sTARGET_OSPLAT=arm
./jam.sh
Cross compiling can be done on either a QNX host for another CPU or on a Windows NT/XP host. For cross compiling the TARGET_OS and TARGET_OSPLAT variables need to be set. The following command will build a project on a Windows NT/XP host for QNX systems with X86 processors.
jam.exe -sTARGET_OS=qnxnto -sTARGET_OSPLAT=x86
To cross compile for QNX on a QNX host the TARGET_OSPLAT needs to be set:
./jam.sh -sTARGET_OSPLAT=ppc
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 recursively builds target files from source files, using dependency information and updating actions expressed in the Jambase file, which is written in jam's own interpreted language. The default Jambase is compiled into jam and provides a boilerplate for common use, relying on a user-provide file "Jamfile" to enumerate actual targets and sources.
The Jambase is described in the Jambase
Reference and the document Using
Jamfiles and 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 c
| Turn on display option c and off the default
display (summary info and actions):
|
-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. |
Jam has four phases of operation: start-up, parsing, binding, and updating.
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.
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 last action of the Jambase is to read (via the "include" rule) a user-provided file called "Jamfile".
Collectively, the purpose of the Jambase and the Jamfile is to
name built target 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 Jamfile uses these to specify the actual relationship
among the target and source files. See the Jambase Reference and the document Using Jamfiles and 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 -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.
Language Features
Jam treats its input files as whitespace-separated tokens, with two exceptions: double quotes (") can enclose whitespace to embed it into a token, and everything between the matching curly braces ({}) in the definition of a updating actions is treated as a single string. A backslash (\) can escape a double quote, or any single whitespace character.
Jam requires whitespace (blanks, tabs, or newlines) to surround all tokens, including the colon (:) and semicolon (;) tokens.
Jam keywords (as mentioned in this document) are reserved and generally must be quoted with double quotes (") to be used as arbitrary tokens, such as variable or target names.
Jam's only data type is a one-dimensional list of arbitrary strings. They arise as literal (whitespace-separated) tokens in the Jambase or included files, as the result of variable expansion of those tokens, or as the return value from a rule invocation.
The basic jam language entity is called a rule. A rule is simply a procedure definition, with a body of jam statements to be run when the rule is invoked. The syntax of rule invocation make it possible to write Jamfiles that look a bit like Makefiles.
Rules take up to 9 arguments ($(1) through $(9), each a list) and can have a return value (a single list). A rule's return value can be expanded in a list by enclosing the rule invocation with [ and ].
A rule may have updating actions associated with it, in which case arguments $(1) and $(2) are treated as built targets and sources, respectively. Updating actions are the OS shell commands to execute when updating the built targets of the rule.
When an rule with updating actions is invoked, those actions are added to those associated with its built targets ($(1)) before the rule's procedure is run. Later, to build the targets in the updating phase, the actions are passed to the OS command shell, with $(1) and $(2) replaced by bound versions of the target names. See Binding above.
Jam's langauge has the following statements:
|
Jam variables are lists of zero or more elements, with each element being a string value. An undefined variable is indistinguishable from a variable with an empty list, however, a defined variable may have one more elements which are null strings. All variables are referenced as $(variable).
Variables are either global or target-specific. In the latter case, the variable takes on the given value only during the target's binding, header file scanning, and updating; and during the "on target statement" statement.
A variable is defined with:
|
The first three forms set variable globally. The last three forms set a target-specific variable. The = operator replaces any previous elements of variable with elements; the += operation adds elements to variable's list of elements; the ?= operator sets variable only if it was previously unset. The last form "variable on targets ?= elements" checks to see if the target-specific, not the global, variable is set. (The ?= operator also has an old form "default =".)
Variables referenced in updating commands will be replaced with their values; target-specific values take precedence over global values. Variables passed as arguments ($(1) and $(2)) to actions are replaced with their bound values; the "bind" modifier can be used on actions to cause other variables to be replaced with bound values. See Action Modifiers above.
Jam variables are not re-exported to the environment of
the shell that executes the updating actions, but the updating
actions can reference jam variables with $(variable).
Variable Expansion
During parsing, jam performs variable expansion on each token that is not a keyword or rule name. Such tokens with embedded variable references are replaced with zero or more tokens. Variable references are of the form $(v) or $(vm), where v is the variable name, and m are optional modifiers.
Variable expansion in a rule's actions is similar to variable expansion in statements, except that the action string is tokenized at whitespace regardless of quoting.
The result of a token after variable expansion is the product of the components of the token, where each component is a literal substring or a list substituting a variable reference. For example:
|
The variable name and modifiers can themselves contain a variable reference, and this partakes of the product as well:
|
Because of this product expansion, if any variable reference in a token is undefined, the result of the expansion is an empty list. If any variable element is a null string, the result propagates the non-null elements:
|
A variable element's string value can be parsed into grist and filename-related components. Modifiers to a variable are used to select elements, select components, and replace components. The modifiers are:
[n]
| Select element number n (starting at 1). If the variable contains fewer than n elements, the result is a zero-element list. |
[n-m]
| Select elements number n through m. |
[n-]
| Select elements number n through the last. |
:B
| Select filename base. |
:S
| Select (last) filename suffix. |
:M
| Select archive member name. |
:D
| Select directory path. |
:P
| Select parent directory. |
:G
| Select grist. |
:U
| Replace lowercase characters with uppercase. |
:L
| Replace uppercase characters with lowercase. |
:chars
| Select the components listed in chars. |
:G=grist
| Replace grist with grist. |
:D=path
| Replace directory with path. |
:B=base
| Replace the base part of file name with base. |
:S=suf
| Replace the suffix of file name with suf. |
:M=mem
| Replace the archive member name with mem. |
:R=root
| Prepend root to the whole file name, if not already rooted. |
:E=value
| Use value instead if the variable is unset. |
:J=joinval
| Concatentate list elements into single element, separated by joinval. |
On VMS, $(var:P) is the parent directory of $(var:D); on Unix and NT, $(var:P) and $(var:D) are the same.
Jam has twelve built-in rules, all of which are pure procedure rules without updating actions. They are in three groups: the first builds the dependency graph; the second modifies it; and the third are just utility rules.
|
The six rules ALWAYS, LEAVES, NOCARE, NOTFILE, NOUPDATE, and TEMPORARY modify the dependency graph so that jam treats the targets differently during its target binding phase. See Binding above. Normally, jam updates a target if it is missing, if its filesystem modification time is older than any of its dependencies (recursively), or if any of its dependencies are being updated. This basic behavior can be changed by invoking the following rules:
|
|
This section discusses variables that have special meaning to
jam.
SEARCH and LOCATE Variables
These two variables control the binding of file target names to locations in the file system. Generally, $(SEARCH) is used to find existing sources while $(LOCATE) is used to fix the location for built targets.
Rooted (absolute path) file targets are bound as is. Unrooted file target names are also normally bound as is, and thus relative to the current directory, but the settings of $(LOCATE) and $(SEARCH) alter this:
Both $(SEARCH) and $(LOCATE) should be set target-specific and
not globally. If they were set globally, jam would use
the same paths for all file binding, which is not likely to
produce sane results. When writing your own rules, especially
ones not built upon those in Jambase, you may need to set
$(SEARCH) or $(LOCATE) directly. Almost all of the rules defined
in Jambase set $(SEARCH) and $(LOCATE) to sensible values for
sources they are looking for and targets they create, respectively.
HDRSCAN and HDRRULE Variables
These two variable control header file scanning. $(HDRSCAN) is an egrep(1) pattern, with ()'s surrounding the file name, used to find file inclusion statements in source files. Jambase uses $(HDRPATTERN) as the pattern for $(HDRSCAN). $(HDRRULE) is the name of a rule to invoke with the results of the scan: the scanned file is the target, the found files are the sources. $(HDRRULE) is run under the influence of the scanned file's target-specific variables.
Both $(HDRSCAN) and $(HDRRULE) must be set for header file scanning to take place, and they should be set target-specific and not globally. If they were set globally, all files, including executables and libraries, would be scanned for header file include statements.
The scanning for header file inclusions is not exact, but it is at least dynamic, so there is no need to run something like makedepend(GNU) to create a static dependency file. The scanning mechanism errs on the side of inclusion (i.e., it is more likely to return filenames that are not actually used by the compiler than to miss include files) because it can't tell if #include lines are inside #ifdefs or other conditional logic. In Jambase, HdrRule applies the NOCARE rule to each header file found during scanning so that if the file isn't present yet doesn't cause the compilation to fail, jam won't care.
Also, scanning for regular expressions only works where the included file name is literally in the source file. It can't handle languages that allow including files using variable names (as the Jam language itself does).
A number of Jam built-in variables can be used to identify runtime platform:
| OS | OS identifier string |
| OSPLAT | Underlying architecture, when applicable |
| MAC | true on MAC platform |
| NT | true on NT platform |
| OS2 | true on OS2 platform |
| UNIX | true on Unix platforms |
| VMS | true on VMS platform |
| JAMDATE | Time and date at jam start-up. |
| JAMUNAME | Ouput of uname(1) command (Unix only) |
| JAMVERSION | jam version, as reported by jam -v. |
When jam executes a rule's action block, it forks and execs a shell, passing the action block as an argument to the shell. The invocation of the shell can be controlled by $(JAMSHELL). The default on Unix is, for example:
JAMSHELL = /bin/sh -c % ;
The % is replaced with the text of the action block.
Jam does not directly support building in parallel across multiple hosts, since that is heavily dependent on the local environment. To build in parallel across multiple hosts, you need to write your own shell that provides access to the multiple hosts. You then reset $(JAMSHELL) to reference it.
Just as jam expands a % to be the text of the rule's action block, it expands a ! to be the multi-process slot number. The slot number varies between 1 and the number of concurrent jobs permitted by the -j flag given on the command line. Armed with this, it is possible to write a multiple host shell. For example:
|
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.
Author
Jam's author is Christopher Seiwald (seiwald@perforce.com). Documentation is provided by Perforce Software, Inc.
jam, the Jam executable program, recursively builds target files from source files using dependency and build specifications defined in Jam rules files. jam parses the rules files to identify targets and sources, examines the filesystem to determine which targets need updating, and issues OS commands to update targets. Jam requires a few files and one directory to be present to compile a project.
A base rules file called "Jambase" is provided with the Jam distribution and is normally located in the project root. The Jambase file defines rules and variables which support standard software build operations, like compiling, linking, etc. When jam is invoked, the Jambase will be loaded, if none is present the project root, a builtin Jambase is used. The external Jambase references further scripts from a 'jam' subdirectory, which must be located in the project root as well.
When the Jambase rules are used, jam reads Jambase, then reads a file called "Jamfile" in the current directory. The Jamfile describes what to do with the source files in its directory. It may also cause Jamfiles in other directories to be read.
Under certain circumstances, the first Jamfile read also causes a site-specific "Jamrules" file to be read. The Jamrules file is an optional set of rule and variable definitions used to define site-specific processing.
Jamfiles 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.
A Jamfile can be as simple as this:
Main myprog : main.c util.c ;
This specifies that there is a main.c and util.c file in the same
directory as the Jamfile, 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
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.
Consider this Jamfile:
Main myprog : main.c util.c ;
LinkLibraries myprog : libtree ;
Library libtree : 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 libtree will be linked into myprog as well. The Library rule specifies which source files will be compiled and archived into the libtree library.
The Jamfile above refers to targets like "myprog" and "libtree". However, depending on the platform you're building on, the actual filenames of those targets could be "myprog.exe" and "libtree.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. Unless you are using the SubDir rules (described later), the default identifier for a file target is its filename. In the above example, the target identifiers are the filenames: myprog.exe, libtree.lib, main.obj, etc.
While all 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.
You can use any buildable target on the jam command line to build a subset of defined targets. For example:
jam libtree.a
on Unix builds the libtree library and all the compiled objects
that go in it.
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 "lib", which is dependent on file targets created by the Library rule. So the command:
jam lib
used with the above example would cause the libtree library to be built.
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 which specify dependencies, like the Main, Library, and LinkLibrary rules, can be invoked in any order. jam figures out the order in which targets are built from their dependencies.
Some rules, however, 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.
This document describes how to use various Jambase rules from a functional point of view. You can see the summary of available Jambase rules in the Jambase Reference. The detailed specifications for any Jambase rule can be found by reading the rule definition itself in the Jambase file.
Handling Directory Trees
The SubDir* rules are used to
define source code directory hierarchies.
With SubDir and SubInclude, you can use jam
to build software from source files and Jamfiles spread
across many directories, as is typical for large projects.
The SubDir* rules unify an entire
source code tree so that jam can read in
all the Jamfiles in one pass and
compute dependencies across the entire project.
To use the SubDir* rules, you must:
The SubDir rule must be invoked before any rules that refer to the contents of the directory - it is best to put it at the top of each Jamfile. For example:
# Jamfile in $(TOP)/src/util directory.
SubDir TOP src util ;
Main myprog : main.c util.c ;
LinkLibraries myprog : libtree ;
Library libtree : treemake.c treetrav.c ;
This compiles four files in $(TOP)/src/util, archives
two of the objects into libtree, and links the whole
thing into myprog.
Outputs are placed in the $(TOP)/src/util
directory.
This doesn't appear to be any different from the previous example that didn't have a SubDir rule, but two things are happening behind the scenes:
The Jamrules file can contain variable definitions and rule definitions specific to your codeline. It allows you to completely customize your build environment without having to rewrite Jambase. Jamrules is only read in once, at the first SubDir invocation.
When you have set a root variable, e.g., $(TOP), SubDir constructs path names rooted with $(TOP), e.g., $(TOP)/src/util. Otherwise, SubDir constructs relative pathnames to the root directory, computed from the number of arguments to the first SubDir rule, e.g., ../../src/util. In either case, the SubDir rule constructs the path names that locate source files. You'll see how this is useful later.
The SubDir rule takes as its first argument the root variable's name and takes as subsequent arguments the directory names leading from the root to the directory of the current Jamfile. Note that the name of the subdirectory is given as individual elements: the SubDir rule does not use system-specific directory name syntax.
The recommended practice is only to include one level of subdirectories at a time, and let the Jamfile in each subdirectory include its own subdirectories. This allows a user to sit in any arbitrary directory of the source tree and build that subtree. For example:
# This is $(TOP)/Jamfile, top level Jamfile for mondo project.
SubInclude TOP src ;
SubInclude TOP man ;
SubInclude TOP misc ;
SubInclude TOP util ;
If a directory has both subdirectories of its own as well
as files that need building, the SubIncludes should be
either before the SubDir rule or be at the end of the Jamfile
- not between the SubDir and other rule invocations.
For example:
# This is $(TOP)/src/Jamfile:
SubDir TOP src ;
Main mondo : mondo.c ;
LinkLibraries mondo : libmisc libutil ;
SubInclude TOP src misc ;
SubInclude TOP src util ;
(jam processes all the Jamfiles it reads as if it were reading one single, large Jamfile. Build rules like Main and LinkLibraries rely on the preceding SubDir rule to set up source file and output file locations, and SubIncludes rules read in Jamfiles that contain SubDir rules. So if you put a SubIncludes rule between a SubDir and a Main rule, jam will try to find the source files for the Main rule in the wrong directory.)
| SEARCH_SOURCE | The SubDir targets (e.g., "TOP src util") are used to construct a pathname (e.g., $(TOP)/src/util), and that pathname is assigned to $(SEARCH_SOURCE). Rules like Main and Library use $(SEARCH_SOURCE) to set search paths on source files. | |
| LOCATE_SOURCE | Initialized by the SubDir rule to the same value as $(SEARCH_SOURCE), unless ALL_LOCATE_TARGET is set. $(LOCATE_SOURCE) is used by rules that build generated source files (e.g., Yacc and Lex) to set location of output files. Thus the default location of built source files is the directory of the Jamfile that defines them. | |
| LOCATE_TARGET | Initalized by the SubDir rule to the same value as $(SEARCH_SOURCE), unless ALL_LOCATE_TARGET is set. $(LOCATE_TARGET) is used by rules that build binary objects (e.g., Main and Library) to set location of output files. Thus the default location of built binaray files is the directory of the Jamfile that defines them. | |
| ALL_LOCATE_TARGET | If $(ALL_LOCATE_TARGET) is set, LOCATE_SOURCE and and LOCATE_TARGET are set to $(ALL_LOCATE_TARGET) instead of to $(SEARCH_SOURCE). This can be used to direct built files to be written to a location outside of the source tree, and enables building from read-only source trees. | |
| SOURCE_GRIST | The SubDir targets are formed into a string like "src!util" and that string is assigned to SOURCE_GRIST. Rules that define file targets use $(SOURCE_GRIST) to set the "grist" attribute on targets. This is used to assure uniqueness of target identifiers where filenames themselves are not unique. For example, the target identifiers of $(TOP)/src/client/main.c and $(TOP)/src/server/main.c would be <src!client>main.c and <src!server>main.c. |
The $(LOCATE_TARGET) and $(SEARCH_SOURCE) variables are used extensively by rules in Jambase: most rules that generate targets (like Main, Object, etc.) set $(LOCATE) to $(LOCATE_TARGET) for the targets they generate, and rules that use sources (most all of them) set $(SEARCH) to be $(SEARCH_SOURCE) for the sources they use.
$(LOCATE) and $(SEARCH) are better explained in The Jam Executable Program but in brief they tell jam where to create new targets and where to find existing ones, respectively.
Note that you can reset these variables after SubDir sets them. For example, this Jamfile builds a program called gensrc, then runs it to create a source file called new.c:
SubDir TOP src util ;
Main gensrc : gensrc.c ;
LOCATE_SOURCE = $(NEWSRC) ;
GenFile new.c : gensrc ;
By default, new.c would be written into the
$(TOP)/src/util directory, but resetting LOCATE_SOURCE causes
it to be written to the $(NEWSRC) directory. ($(NEWSRC) is assumed
to have been set elsewhere, e.g., in Jamrules.)
TOP = USR_DISK:[JONES.SRC] ;
SubInclude TOP util ;
The variable must have a value that looks like a directory
or device. If you choose, you can use a concealed logical.
For example:
TOP = TOP: ;
SubInclude TOP util ;
The : at the end of TOP makes the value of $(TOP) look
like a device name, which jam respects as a directory name
and will use when trying to access files. TOP must then
be defined from DCL:
$ define/job/translation=concealed TOP DK100:[USERS.JONES.SRC.]
Note three things: the concealed translation allows the
logical to be used as a device name; the device name in
the logical (here DK100) cannot itself be concealed logical
(VMS rules, man); and the directory component of the
definition must end in a period (more VMS rules).
Building Executables and Libraries
The rules that build executables and libraries are: Main, Library, and LinkLibraries.
Main myprog : main.c util.c ;
This compiles main.c and util.c and links main.o and
util.o into myprog. The object files and resulting
executable are named appropriately for the platform.
Main can also be used to build shared libraries and/or dynamic link libraries, since those are also linked objects. Though, this feature is deprecated and the rule SharedLibrary should be used instead.
Main driver$(SUFSHR) : driver.c ;
Normally, Main uses $(SUFEXE) to determine the suffix on
the filename of the built target. To override it,
you can supply a suffix explicity.
In this case,
$(SUFSHR) is assumed to be the OS-specific shared library
suffix, defined in Jamrules with something
like:
if $(UNIX) { SUFSHR = .so ; }
else if $(NT) { SUFSHR = .dll ; }
Main uses the Objects rule to compile source targets.
Library libstring : strcmp.c strcpy.c strlen.c ;
Library libtree : treemake.c treetrav.c ;
This compiles five source files, archives three of the
object files into libstring and the other two into libtree.
Actual library filenames are formed with the $(SUFLIB) suffix.
Once the objects are safely in the libraries, the
objects are deleted.
Library uses the Objects rule to compile source files.
SharedLibrary example : example.c util.c ;
This compiles example.c and util.c and links example.o and
util.o into example. The object files and resulting
executable are named appropriately for the platform.
Main uses the Objects rule to compile source targets.
Normally, SharedLibrary uses $(SUFLIB) and $(SUFDLL) to determine the prefix/suffix on the filename of the built target. Under windows the resulting library will be called example.dll and a import library called example.lib will be created. Under unix, one shared library called libexample.so will be created. To override it, you can supply a prefix/suffix explicity.
Main myprog : main.c util.c ;
LinkLibraries myprog : libstring libtree ;
SharedLibrary mydll : dll.c stuff.c ;
LinkLibraries mydll : libstring libtree ;
The LinkLibraries rule does two things: it makes the
libraries dependencies of the executable, so that they get
built first; and it makes the libraries show up on the
command line that links the executable. The ordering of
the lines above is important, because the preceeding Main
or SharedLibrary Rule type its target.
You can put multiple libraries on a single invocation of the LinkLibraries rule, or you can provide them in multiple invocations. In both cases, the libraries appear on the link command line in the order in which they were encountered. You can also provide multiple executables to the LinkLibraries rule, if they need the same libraries, e.g.:
LinkLibraries prog1 prog2 prog3 : libstring libtree ;
The LinkLibraries rule accepts a third optional parameter to add linker flags to the command line that links the target. The rule does so by settimg the LINKLIBS variable on the targets specified in the first argument. The following example uses the linker flags conatined in FLAGS when myprog is linked:
Main myprog : main.c util.c ;
LinkLibraries myprog : libstring libtree : $(FLAGS) ;
Main myprog : main.c util.c ;
LinkSharedLibraries myprog : example ;
SharedLibrary mydll : dll.c stuff.c ;
LinkSharedLibraries mydll : example ;
The LinkSharedLibraries rule does two things: it makes the
libraries dependencies of the executable, so that they get
built first; and it makes the libraries show up on the
command line that links the executable. The ordering of
the lines above is important, because the preceeding Main
or SharedLibrary Rules type its target.
You can put multiple libraries on a single invocation of the LinkSharedLibraries rule, or you can provide them in multiple invocations. In both cases, the libraries appear on the link command line in the order in which they were encountered. E. g.:
LinkSharedLibraries myprog : example1 example2 ;
The LinkSharedLibraries rule accepts a third optional parameter to add linker flags to the command line that links the executable or shared library. The following example assumes that a variable FLAGS contains additional linker flags:
Main myprog : main.c util.c ;
LinkSharedLibraries myprog : libstring libtree : $(FLAGS) ;
The LinkSharedLibraries rule accepts a third optional parameter to add linker flags to the command line that links the target. The rule does so by settimg the LINKLIBS variable on the targets specified in the first argument. The following example uses the linker flags conatined in FLAGS when myprog is linked:
Main myprog : main.c util.c ;
LinkSharedLibraries myprog : libstring libtree : $(FLAGS) ;
Main myprog : main.c util.c ;
LinkFlags myprog : $(FLAGS) ;
SharedLibrary mydll : dll.c stuff.c ;
LinkFlags mydll : $(FLAGS) ;
This adds the linker flags contained in $(FLAGS) to the
to the command line that links the targets myprog or mydll.
It is possible to link against external libraries by adding
the actual link command flag.
| AR | Archive command, used for Library targets. | |
| SUFEXE | * | Suffix on filenames of executables referenced by Main and LinkLibraries. |
| SUFDLL | * | Suffix on filenames of shared libraries referenced by SharedLibrary and LinkSharedLibraries. |
| LINK | Link command, used for Main targets. | |
| LINKFLAGS | Linker flags. | |
| LINKLIBS | Link libraries that aren't dependencies. (See note below.) | |
| EXEMODE | * | File permissions on Main targets. |
| MODE | Target-specific file permissions on Main targets (set from $(EXEMODE)) | |
| RANLIB | Name of ranlib program, if any. |
Variables above marked with "*" are used by the Main, Library, and LinkLibraries rules. Their values at the time the rules are invoked are used to set target-specific variables.
All other variables listed above are globally defined, and are used in actions that update Main and Library targets. This means that the global values of those variables are used, uness target-specific values have been set. (For instance, a target-specific MODE value is set by the Main rule.) The target-specific values always override global values.
Note that there are several ways to specify link libraries for executables:
For example:
#In Jamrules:
if $(UNIX) { X11LINKLIBS = -lXext -lX11 ; }
if $(NT) { X11LINKLIBS = libext.lib libX11.lib ; }
#In Jamfile:
Main xprog : xprog.c ;
LinkFlags xprog : $(X11LINKLIBS) ;
# Or: LINKLIBS on xprog$(SUFEXE) = $(X11LINKLIBS) ;
LinkLibraries xprog : libxutil ;
# Or: LinkLibraries xprog : libxutil : $(X11LINKLIBS) ;
Library libxutil : xtop.c xbottom.c xutil.c ;
This example uses the Jam syntax "variable on target" to
set a target-specific variable. In this way, only xprog
will be linked with this special $(X11LINKLIBS),
even if other executables were going to be built
by the same Jamfile. Note that when you set a variable
on a target, you have to specify the target identifer
exactly, which in this case is the suffixed filename of
the executable.
The actual link command line on Unix, for example, would
look something like this:
cc -o xprog xprog.o libxutil.a -lXext -lX11
Target identifiers created by the Objects rule have grist set to $(SOURCE_GRIST). So given this Jamfile:
SubDir TOP src lock ;
Main locker : lock.c ;
the object file created is lock.o (or lock.obj) and
its target identifier is <src!lock>lock.o
(or <src!lock>lock.obj).
You can also call Objects directly. For example:
Objects a.c b.c c.c ;
This compiles a.c into a.o, b.c into b.o, etc. The object
file suffix is supplied by the Objects rule.
Object foo.o : foo.c ;
However, the Object rule does not provide suffixes, and
it does not provide the grist needed to construct target
identifiers if you are using the SubDir* rules.
A portable and robust Jamfile would need to invoke Object thus:
Object <src!util>foo$(SUFOBJ) : <src!util>foo.c ;
which is inelegant and clearly shows why using Objects
is better than using Object.
If there's any advantage to the Object rule, it's that it doesn't require that the object name bear any relationship to the source. It is thus possible to compile the same file into different objects. For example:
Object a.o : foo.c ;
Object b.o : foo.c ;
Object c.o : foo.c ;
This compiles foo.c (three times) into a.o, b.o, and c.o.
Later examples show how this is useful.
The Object rule looks at the suffix of the source file and calls the appropriate rules to do the actual preprocessing (if any) and compiling needed to produce the output object file. The Object rule is capable of the generating of an object file from any type of source. For example:
Object grammar$(SUFOBJ) : grammar.y ;
Object scanner$(SUFOBJ) : scanner.l ;
Object fastf$(SUFOBJ) : fastf.f ;
Object util$(SUFOBJ) : util.c ;
An even more elegant way to get the same result is to let the
Objects rule call Object:
Objects grammar.y scanner.l fastf.f util.c ;
In addition to calling the compile rules, Object sets up a bunch of variables specific to the source and target files. (See Variables Used in Compiling, below.)
The Object rule calls compile rules specific to the suffix of the source file. (You can see which suffixes are supported by looking at the Object rule definition in Jambase.) Because the extra work done by the Object rule, it is not always useful to call the compile rules directly. But the adventurous user might attempt it. For example:
Yacc grammar.c : grammar.y ;
Lex scan.c : scan.l ;
Cc prog.o : prog.c ;
These examples individually run yacc(1), lex(1), and the C
compiler on their sources.
#In Jamrules:
rule UserObject
{
switch $(>)
{
case *.rc : ResourceCompiler $(<) : $(>) ;
case * : ECHO "unknown suffix on" $(>) ;
}
}
rule ResourceCompiler
{
DEPENDS $(<) : $(>) ;
Clean clean : $(<) ;
}
actions ResourceCompiler
{
rc /fo $(<) $(RCFLAGS) $(>)
}
#In Jamfile:
Library liblock : lockmgr.c ;
if $(NT) { Library liblock : lock.rc ; }
In this example, the UserObject definition in Jamrules allows *.rc files to be handle as regular Main and Library sources. The lock.rc file is compiled into lock.obj by the "rc" command, and lock.obj is archived into a library with other compiled objects.
LibraryFromObjects libfoo.a : max.o min.o ;
Object max.o : maxmin.c ;
Object min.o : maxmin.c ;
ObjectCcFlags max.o : -DUSEMAX ;
ObjectCcFlags min.o : -DUSEMIN ;
This Unix-specific example compiles the same source file into
two different
objects, with different compile flags, and archives them.
(The ObjectCcFlags rule is described shortly.)
Unfortunately, the portable and robust implementation of the
above example is not as pleasant to read:
SubDir TOP foo bar ;
LibraryFromObjects libfoo$(SUFLIB) : <foo!bar>max$(SUFOBJ)
<foo!bar>min$(SUFOBJ) ;
Object <foo!bar>min$(SUFOBJ) : <foo!bar>maxmin.c ;
Object <foo!bar>max$(SUFOBJ) : <foo!bar>maxmin.c ;
ObjectCcFlags <foo!bar>min$(SUFOBJ) : -DUSEMIN ;
ObjectCcFlags <foo!bar>max$(SUFOBJ) : -DUSEMAX ;
Note that, among other things, you must supply the library
file suffix when using the LibraryFromObjects rule.
MainFromObjects testprog ;
LinkLibraries testprog : libprog ;
Library libprog : main.c util.c ;
On Unix, say, this generates a link command that looks like:
cc -o testprog libprog.a
Linking purely from libraries is something that doesn't
work everywhere: it depends on the symbol "main" being
undefined when the linker encounters the library that contains
the definition of "main".
| C++ | The C++ compiler command | |
| CC | The C compiler command | |
|
C++FLAGS
CCFLAGS | Compile flags, used to create or update compiled objects | |
|
SUBDIRC++FLAGS
SUBDIRCCFLAGS | Additonal compile flags for source files in this directory. | |
| OPTIM | Compiler optimization flag. The Cc and C++ actions use this as well as C++FLAGS or CCFLAGS. | |
| HDRS | Non-standard header directories; i.e., the directories the compiler will not look in by default and which therefore must be supplied to the compile command. These directories are also used by jam to scan for include files. | |
| STDHDRS | Standard header directories, i.e., the directories the compiler searches automatically. These are not passed to the compiler, but they are used by jam to scan for include files. | |
| SUBDIRHDRS | Additional paths to add to HDRS for source files in this directory. | |
| LEX | The lex(1) command | |
| YACC | The yacc(1) command |
The Cc rule sets a target-specific $(CCFLAGS) to the current value of $(CCFLAGS) and $(SUBDIRCCFLAGS). Similarly for the C++ rule. The Object rule sets a target-specific $(HDRS) to the current value of $(HDRS) and $(SUBDDIRHDRS).
$(CC), $(C++), $(CCFLAGS), $(C++FLAGS), $(OPTIM), and $(HDRS) all affect the compiling of C and C++ files. $(OPTIM) is separate from $(CCFLAGS) and $(C++FLAGS) so they can be set independently.
$(HDRS) lists the directories to search for header files, and it is used in two ways: first, it is passed to the C compiler (with the flag -I prepended); second, it is used by HdrRule to locate the header files whose names were found when scanning source files. $(STDHDRS) lists the header directories that the C compiler already knows about. It does not need passing to the C compiler, but is used by HdrRule.
Note that these variables, if set as target-specific variables, must be set on the target, not the source file. The target file in this case is the object file to be generated. For example:
Library libximage : xtiff.c xjpeg.c xgif.c ;
HDRS on xjpeg$(SUFOBJ) = /usr/local/src/jpeg ;
CCFLAGS on xtiff$(SUFOBJ) = -DHAVE_TIFF ;
This can be done more easily with the rules that follow.
#In Jamrules:
if $(NT) { CCFLAGS_X = /DXVERSION ;
HDRS_X = \\\\SPARKY\\X11\\INCLUDE\\X11 ;
}
#In Jamfile:
Main xviewer : viewer.c ;
ObjectCcFlags viewer.c : $(CCFLAGS_X) ;
ObjectHdrs viewer.c : $(HDRS_X) ;
The ObjectCcFlags and ObjectHdrs rules take .c files
as targets, but actually set $(CCFLAGS) and $(HDRS) values
on the .obj (or .o) files. As a result, the action
that updates the target .obj file uses the target-specific
values of $(CCFLAGS) and $(HDRS).
#In Jamrules:
GZHDRS = $(TOP)/src/gz/include ;
GZFLAG = -DGZ ;
OBJS = $(TOP)/objs
#In Jamfile:
SubDir TOP src gz utils ;
SubDirHdrs $(GZHDRS) ;
SubDirCcFlags $(GZFLAG) ;
SubDirObjects $(OBJS) ;
Library libgz : gizmo.c ;
Main gizmo : main.c ;
LinkLibraries gizmo : libgz ;
All .c files in this directory will be compiled with
$(GZFLAG) as well as the default $(CCFLAG), and the include
paths used on the compile command will be $(GZHDRS) as well
as the default $(HDRS). All objects will be generated in
$(TOP)/objs.
$(HDRRULE) source-file : included-files ;
This rule is supposed to set up the dependencies between
the source file and the included files. The Object rule
uses HdrRule to do the job. HdrRule itself expects
another variable, $(HDRSEARCH), to be set to the list of
directories where the included files can be found. Object
does this as well, setting $(HDRSEARCH) to $(HDRS) and
$(STDHDRS).
The header file scanning occurs during the "file binding" phase of jam, which means that the target-specific variables (for the source file) are in effect. To accomodate nested includes, one of the HdrRule's jobs is to pass the target-specific values of $(HDRRULE), $(HDRSCAN), and $(HDRSEARCH) onto the included files, so that they will be scanned as well.
If there are special dependencies that need to be set, and which are not set by HdrRule itself, you can define another rule and let it invoke HdrRule. For example:
#In Jamrules:
rule BuiltHeaders
{
DEPENDS $(>) : mkhdr$(SUFEXE) ;
HdrRule $(<) : $(>) ;
}
#In Jamfile:
Main mkhdr : mkhdr.c ;
Main ugly : ugly.c ;
HDRRULE on ugly.c = BuiltHeaders ;
This example just says that the files included by "ugly.c"
are generated by the program "mkhdr", which can be built
from "mkhdr.c". During the binding phase, jam will
scan ugly.c, and if it finds an include file, ughdr.h,
for example, it will automatically invoke the rule:
BuiltHeaders ugly.c : ughdr.h ;
By calling HdrRule at the end of BuiltHeaders,
all the gadgetry of HdrRule takes effect and it
doesn't need to be duplicated.
| HDRPATTERN | Default scan pattern for "include" lines. | |
| HDRSCAN | Scan pattern to use. This is a special variable: during binding, if both HDRSCAN and HDRRULE are set, scanning is activated on the target being bound. The HdrRule and Object rules sets this to $(HDRPATTERN) on their source targets. | |
| HDRRULE | Name of rule to invoked on files found in header scan. The HdrRule and Object rules set this to "HdrRule" on their source targets. This is also a special variable; it's the only jam variable that can hold the name of a rule to be invoked. | |
| HDRSEARCH | Search paths for files found during header scanning. This is set from $(HDRS) and $(STDHDRS), which are described in the Compiling section. jam will search $(HDRSEARCH) directories for the files found by header scans. |
The Object rule sets HDRRULE and HDRSCAN specifically for the source files to be scanned, rather than globally. If they were set globally, jam would attempt to scan all files, even library archives and executables, for header file inclusions. That would be slow and probably not yield desirable results.
switch $(OS)
{
case NT* : File config.h : confignt.h ;
case * : File config.h : configunix.h ;
}
LOCATE on config.h = $(LOCATE_SOURCE) ;
This creates a config.h file from either confignt.h or
configunix.h, depending on the current build platform.
The File rule does not use the LOCATE_SOURCE variable set by the SubDir rule (although it does use SEARCH_SOURCE), which means you have to set the copied file's output directory yourself. That's done by setting the special LOCATE variable on the target, as shown above, or with the MakeLocate rule described below.
#In Jamrules:
DISTRIB_GROB = d:\\distrib\\grob ;
#In Jamfile:
Bulk $(DISTRIB_GROB) : grobvals.txt grobvars.txt ;
This causes gobvals.txt and grobvars.txt to be copied
into the $(DISTRIB_GROB) directory.
HardLink config.h : configunix.h ;
Shell /usr/local/bin/add : add.sh ;
You can also use $(SHELLHEADER) to dictate what the first line of the copied file will be. For example:
Shell /usr/local/bin/add : add.awk ;
SHELLHEADER on /usr/local/bin/add = "#!/bin/awk -f" ;
This installs an awk(1) script.
| FILEMODE | Default file permissions for copied files | |
| SHELLMODE | Default file permissions for Shell rule targets | |
| MODE | File permissions set on files copied by File, Bulk, and Shell rules. File and Shell sets a target-specific MODE to the current value of $(FILEMODE) or $(SHELLMODE), respectively. | |
| SHELLHEADER | String to write in first line of Shell targets (default is #!/bin/sh). |
Installing Files
Jambase provides a set of Install* rules to copy files
into an destination directory and set permissions on them.
On Unix, the install(1) program is used.
If the destination directory does not exist, jam
creates it first.
All files copied with the Install* rules are dependencies of the install pseudotarget, which means that the command "jam install" will cause the installed copies to be updated. Also, "jam uninstall" will cause the installed copies to be removed.
The Install* rules are:
| InstallBin | Copies file and sets its permission to $(EXEMODE).
You must specify the suffixed executable name. E.g.:
InstallBin $(BINDIR) : thing$(SUFEXE) ;
|
| InstallFile | Copies file and sets its permission to $(FILEMODE). E.g.:
InstallFile $(DESTDIR) : readme.txt ;
|
| InstallLib | Copies file and sets its permission to $(FILEMODE).
You must specify the suffixed library name. E.g.:
InstallLib $(LIBDIR) : libzoo$(SUFLIB) ;
|
| InstallMan | Copies file into the mann
subdirectory of the target directory
and sets its permission to $(FILEMODE). E.g.,
this copies foo.5 into the $(DESTDIR)/man5 directory:
InstallMan $(DESTDIR) : foo.5 ;
|
| InstallShell | Copies file and sets its permission to $(SHELLMODE). E.g.:
InstallShell $(DESTDIR) : startup ;
|
| INSTALL | The install program (Unix only) | |
| FILEMODE | Default file permissions on readable files. | |
| EXEMODE | Default file permission executable files. | |
| SHELLMODE | Default file permission on shell script files. | |
| MODE | Target-specific file permissions |
The Install rules set a target-specific MODE to the current value of $(FILEMODE), $(EXEMODE), or $(SHELLMODE), depending on which Install rule was invoked.
The directory variables are just defined for convenience: they must be passed as the target to the appropriate Install rule. The $(INSTALL) and mode variables must be set (globally) before calling the Install rules in order to take effect.
The Clean rule defines files to be removed when you run "jam clean". Any site-specific build rules defined in your Jamrules should invoke Clean so that outputs can be removed. E.g.,
rule ResourceCompiler
{
DEPENDS $(<) : $(>) ;
Clean clean : $(<) ;
}
Most Jambase rules invoke the Clean rule on their built targets, so "jam clean" will remove all compiled objects, libraries, executables, etc.
GenFile data.tbl : hxtract data.h ;
MakeLocate data.tbl : $(TABLEDIR) ;
In this example, the File rule creates data.tbl from data.h.
The MakeLocate causes data.tbl to be written into the $(TABLEDIR)
directory; and if the directory doesn't exist, it is created first.
The MakeLocate rule can be used to build targets introduced by Main, Library or SharedLibrary at a specific location.
Main myprog : main.c ;
MakeLocate myprog : $(OUTPUT) ;
In the example above the program 'myprog' is built at the location
specified by the variable OUTPUT.
The MakeLocate rule invokes another Jambase rule, MkDir, to (recursively) create directories. MkDir uses the $(MKDIR) variable to determine the platform-specific command that creates directories.
RmTemps must be:
SubDir TOP src big ;
GenFile big.y : joinfiles part1.y part2.y part3.y ;
Main bigworld : main.c big.y ;
RmTemps bigworld$(SUFEXE) : <src!big>big.y ;
This causes big.y to be deleted after it has been used to create
the bigworld executable.
The exact target identifier of big.y is <src!big>big.y
(the GenFile and Main rules tack on the grist automatically);
the exact target identifier of the bigworld executable
is bigworld$(SUFEXE).
Jambase is a base set of Jam rules which provide roughly make-like functionality for jam, the Jam executable program. This document is a reference guide to the rules, pseudotargets, and variables defined in Jambase for use in Jamfiles.
As obj.o : source.s ;
Assemble the file source.s. Called by the Object rule.Bulk directory : sources ;
Copies sources into directory.Cc object : source ;
Compile the file source into object, using the C compiler $(CC), its flags $(CCFLAGS) and $(OPTIM), and the header file directories $(HDRS). Called by the Object rule.C++ obj.o : source.cc ;
Compile the C++ source file source.cc. Called by the Object rule.Chmod target ;
(Unix and VMS only.) Change file permissions on target to target-specific $(MODE) value set by Link, File, Install*, and Shell rules.Clean clean : targets ;
Removes existing targets when clean is built. clean is not a dependency of all, and must be built explicitly for targets to be removed.FDefines defines ;
Expands a list of definitions into a list of compiler (or preprocessor) switches (such as -Dsymbol=val on Unix) to pass the definitions.File target : source ;
Copies source into target.FIncludes dirs ;
Expands a list of directories into a list of compiler (or preprocessor) switches (such as -Idir on Unix) to add the directories to the header inclusion search path.Fortran obj.o : source.f ;
Compile the Fortran source file source.f. Called by the Object rule.FQuote files ;
Returns each of files suitably quoted so as to hide shell metacharacters (such as whitespace and filename matching wildcards) from the shell.
GenFile target : image sources ;
Runs the command "image target sources" to create target from sources and image. (where image is an executable built by the Main rule.)HardLink target : source ;
Makes target a hard link to source, if it isn't one already. (Unix only.)HdrRule source : headers ;
Arranges the proper dependencies when the file source includes the files headers through the "#include" C preprocessor directive.InstallBin dir : sources ;This rule is not intended to be called explicitly. It is called automatically during header scanning on sources handled by the Object rule (e.g., sources in Main or Library rules).
Copy sources into dir with mode $(EXEMODE).InstallLib dir : sources ;
Copy sources into dir with mode $(FILEMODE).InstallMan dir : sources ;
Copy sources into the appropriate subdirectory of dir with mode $(FILEMODE). The subdirectory is mans, where s is the suffix of each of sources.InstallShell dir : sources ;
Copy sources into dir with mode $(SHELLMODE).Lex source.c : source.l ;
Process the lex(1) source file source.l and rename the lex.yy.c to source.c. Called by the Object rule.Library library : sources ;
Compiles sources and archives them into library. The intermediate objects are deleted. Calls Objects and LibraryFromObjects.LibraryFromObjects library : objects ;If Library is invoked with no suffix on library, the $(SUFLIB) suffix is used.
Archives objects into library. The objects are then deleted.Link image : objects ;If library has no suffix, the $(SUFLIB) suffix is used.
Links image from objects and sets permissions on image to $(EXEMODE). Image must be actual filename; suffix is not supplied. Called by Main.LinkLibraries image : libraries : flags ;
Makes image depend on libraries and includes them during the linking. The flags are added to the link command line. The libraries must be static libraries built in this project.LinkSharedLibraries image : libraries ;Image may be referenced without a suffix in this rule invocation; LinkLibraries supplies the suffix. Must follow a Main, Library or SharedLibrary rule for the same target
Makes image depend on libraries and includes them during the linking. libraries must be shared libraries built in this projectMain image : sources ;Image may be referenced without a suffix in this rule invocation; LinkSharedLibraries supplies the suffix. Mustfollow a Main, Library or SharedLibrary rule for the same target
Compiles sources and links them into image. Calls Objects and MainFromObjects.MainFromObjects image : objects ;Image may be referenced without a suffix in this rule invocation; Main supplies the suffix.
Links objects into image. Dependency of exe. MainFromObjects supplies the suffix on image filename.MakeLocate target : dir ;
Creates dir and causes target to be built into dir.MkDir dir ;
Creates dir and its parent directories.Object object : source ;
Compiles a single source file source into object. The Main and Library rules use this rule to compile source files.ObjectC++Flags source : flags ;Causes source to be scanned for "#include" directives and calls HdrRule to make all included files dependedencies of object.
Calls one of the following rules to do the actual compiling, depending on the suffix of source:
*.c: Cc *.cc: C++ *.cpp: C++ *.C: C++ *.l: Lex *.y: Yacc *.*: UserObject
Add flags to the source-specific value of $(CCFLAGS) or $(C++FLAGS) when compiling source. Any file suffix on source is ignored.ObjectDefines object : defines ;
Adds preprocessor symbol definitions to the (gristed) target-specific $(CCDEFS) for the object.ObjectHdrs source : dirs ;
Add dirs to the source-specific value of $(HDRS) when scanning and compiling source. Any file suffix on source is ignored.Objects sources ;
For each source file in sources, calls Object to compile the source file into a similarly named object file.RmTemps targets : sources ;
Marks sources as temporary with the TEMPORARY rule, and deletes sources once targets are built. Must be the last rule invoked on targets. Used internally by LibraryFromObjects rule.Setuid images ;
Sets the setuid bit on each of images after linking. (Unix only.) SharedLibrary library : sources : flags ;SoftLink target : source ;Compiles sources and links them into library. The flags are added to the link command line. Calls Objects and SharedLibraryFromObjects.If SharedLibrary is invoked with no suffix on library, the $(SUFDLL) suffix is used.
Makes target a symbolic link to source, if it isn't one already. (Unix only.)SubDir TOP d1 ... dn ;
Sets up housekeeping for the source files located inSubDirC++Flags flags ;$(TOP)/d1/.../dn:
- Reads in rules file associated with TOP, if it hasn't already been read.
- Initializes variables for search paths, output directories, compiler flags, and grist, using d1 ... dn tokens.
TOP is the name of a variable; d1 thru dn are elements of a directory path.
Adds flags to the compiler flags for source files in SubDir's directory.SubDirHdrs d1 ... dn ;
Adds the path d1/.../dn/ to the header search paths for source files in SubDir's directory. d1 through dn are elements of a directory path.SubInclude VAR d1 ... dn ;
Reads the Jamfile in $(VAR)/d1/.../dn/.
Shell image : source ; Copies source into the executable sh(1) script image. Ensures that the first line of the script is $(SHELLHEADER) (default #!/bin/sh).Undefines images : symbols ;
Adds flags to mark symbols as undefined on link command for images. Images may be referenced unsuffixed; the Undefines rule supplies the suffix.UserObject object : source ;
This rule is called by Object for source files with unknown suffixes, and should be defined in Jamrules with a user-provided rule to handle the source file types not handled by the Object rule. The Jambase UserObject rule merely issues a complaint when it encounters source with files suffixes it does not recognize.Yacc source.c : source.y ;
Process the yacc(1) file source.y and renamed the resulting y.tab.c and y.tab.h to source.c. Produces a y.tab.h and renames it to source.h. Called by the Object rule.
There are two kinds of Jam targets: file targets and pseudotargets. File targets are objects that can be found in the filesystem. Pseudotargets are symbolic, and usually represent other targets. Most Jambase rules that define file targets also define pseudotargets which are dependent on types of file targets. The Jambase pseudotargets are:
| exe | Executables linked by the Main or MainFromObjects rules |
| lib | Libraries created by the Library or LibraryFromObjects rules |
| obj | Compiled objects used to create Main or Library targets |
| dirs | Directories where target files are written |
| file | Files copied by File and Bulk rules |
| shell | Files copied by Shell rule |
| clean | Removal of built targets (except files copied by Install* rules) |
| install | Files copied by Install* rules |
| uninstall | Removal of targets copied by Install* rules |
In addition, Jambase makes the jam default target "all" depend on "exe", "lib", "obj", "files", and "shell".
Most of the following variables have default values for each platform; refer to the Jambase file to see what those defaults are.
ALL_LOCATE_TARGET
Alternative location of built targets. By default, Jambase rules locate built targets in the source tree. By setting $(ALL_LOCATE_TARGET) in Jamrules, you can cause jam to write built targets to a location outside the source tree.ALL_LOCATE_OBJECTS
Alternative location of built objects. By default, Jambase rules locate built targets in the source tree. By setting $(ALL_LOCATE_OBJECTS) in Jamrules, you can cause jam to write built objects to a location outside the source tree.AR
The archive command used to update Library and LibraryFromObjects targets.AS
The assembler for As rule targets.ASFLAGS
Flags handed to the assembler for As.AWK
The name of awk interpreter, used when copying a shell script for the Shell rule.BCCROOT
Selects Borland compile and link actions on NT.BINDIR
Not longer used. (I.e., used only for backward compatibility with the obsolete INSTALLBIN rule.)CC
C compiler used for Cc rule targets.CCFLAGS
Compile flags for Cc rule targets. The Cc rule sets target-specific $(CCFLAGS) values on its targets.C++
C++ compiler used for C++ rule targets.C++FLAGS
Compile flags for C++ rule targets. The C++ rule sets target-specific $(C++FLAGS) values on its targets.CHMOD
Program (usually chmod(1)) used to set file permissions for Chmod rule.CP
The file copy program, used by File and Install* rules.CRELIB
If set, causes the Library rule to invoke the CreLib rule on the target library before attempting to archive any members, so that the library can be created if needed.CW
On Macintosh, the root of the Code Warrior Pro 5 directory.DEFINES
Preprocessor symbol definitions for Cc and C++ rule targets. The Cc and C++ rules set target-specific $(CCDEFS) values on their targets, based on $(DEFINES). (The "indirection" here is required to support compilers, like VMS, with baroque command line syntax for setting symbols).DOT
The operating system-specific name for the current directory.DOTDOT
The operating system-specific name for the parent directory.EXEMODE
Permissions for executables linked with Link, Main, and MainFromObjects, on platforms with a Chmod action.FILEMODE
Permissions for files copied by File or Bulk, on platforms with a Chmod action.FORTRAN
The Fortran compiler used by Fortran rule.FORTRANFLAGS
Fortran compiler flags for Fortran rule targets.GROUP
(Unix only.) The group owner for Install* rule targets.HDRGRIST
If set, used by the HdrRule to distinguish header files with the same name in diffrent directories.HDRPATTERN
A regular expression pattern that matches C preprocessor "#include" directives in source files and returns the name of the included file.HDRRULE
Name of the rule to invoke with the results of header file scanning. Default is "HdrRule".HDRSThis is a jam-special variable. If both HDRRULE and HDRSCAN are set on a target, that target will be scanned for lines matching $(HDRSCAN), and $(HDDRULE) will be invoked on included files found in the matching $(HDRSCAN) lines.
Directories to be searched for header files. This is used by the Object rule to:HDRSCAN(See STDHDRS.)
- set up search paths for finding files returned by header scans
- add -I flags on compile commands
Regular expression pattern to use for header file scanning. The Object rule sets this to $(HDRPATTERN). This is a jam-special variable; see HDRRULE.HDRSEARCH
Used by the HdrRule to fix the list of directories where header files can be found for a given source file.INSTALLGRIST
Used by the Install* rules to grist paths to installed files; defaults to "installed".JAMFILE
Default is "Jamfile"; the name of the user-written rules file found in each source directory.JAMRULES
Default is "Jamrules"; the name of a rule definition file to be read in at the first SubDir rule invocation.KEEPOBJS
If set, tells the LibraryFromObjects rule not to delete object files once they are archived.LEX
The lex(1) command and flags.LIBDIR
Not longer used. (I.e., used only for backward compatibility with the obsolete INSTALLLIB rule.)LINK
The linker. Defaults to $(CC).LINKFLAGS
Flags handed to the linker. Defaults to $(CCFLAGS).LINKLIBS
List of external libraries to link with. The target image does not depend on these libraries.LN
The hard link command for HardLink rule.LOCATE_SOURCE
Used to set the location of generated source files. The Yacc, Lex, and GenFile rules set LOCATE on their targets to $(LOCATE_SOURCE). $(LOCATE_SOURCE) is initialized by the SubDir rule to the source directory itself. (Also, see ALL_LOCATE_TARGET.)LOCATE_TARGET
Used to set the location of built binary targets. The Object rule, and hence the Main and Library rules, set LOCATE on their targets to $(LOCATE_TARGET). $(LOCATE_TARGET) is initialized by the SubDir rule to the source directory itself. (See ALL_LOCATE_TARGET.)MANDIR
Not longer used. (I.e., used only for backward compatibility with the obsolete INSTALLMAN rule.)MKDIR
The 'create directory' command used for the MkDir rule.MODE
The target-specific file mode (permissions) for targets of the Shell, Setuid, Link, and Install* rules. Used by the Chmod action; hence relevant to NT and VMS only.MSVC
Selects Microsoft Visual C 16-bit compile & link actions on NT.MSVCNT
Selects Microsoft Visual C NT 5.0 and earlier compile & link actions on NT.MSVCDIR
Selects Microsoft Visual C NT 6.0 and later compile & link actions on NT. These are identical to versions 5.0 and earlier -- it just seems Microsoft changed the name of the variable.MV
The file rename command and options.NEEDLIBS
The list of libraries used when linking an executable. Used by the Link rule.NOARSCAN
If set, indicates that library members' timestamps can't be found, and prevents the individual objects from being deleted, so that their timestamps can be used instead.NOARUPDATE
If set, indicates that libraries can't be updated, but only created whole.OPTIM
The C compiler flag for optimization, used by Cc and C++ rules.OSFULL
The concatenation of $(OS)$(OSVER)$(OSPLAT), used when jam builds itself to determine the target binary directory. $(OS) and $(OSPLAT) are determined by jam at its compile time (in jam.h). $(OSVER) can optionally be set by the user.OWNER
The owner of installed files. Used by Install* rules.RANLIB
The name of the ranlib command. If set, causes the Ranlib action to be applied after the Archive action to targets of the Library rule.RELOCATE
If set, tells the Cc rule to move the output object file to its target directory because the cc command has a broken -o option.RM
The command and options to remove a file.SEARCH_SOURCE
The directory to find sources listed with Main, Library, Object, Bulk, File, Shell, InstallBin, InstallLib, and InstallMan rules. This works by setting the jam-special variable SEARCH to the value of $(SEARCH_SOURCE) for each of the rules' sources. The SubDir rule initializes SEARCH_SOURCE for each directory.SHELLHEADER
A string inserted to the first line of every file created by the Shell rule.SHELLMODE
Permissions for files installed by Shell rule.SOURCE_GRIST
Set by the SubDir to a value derived from the directory name, and used by Objects and related rules as 'grist' to perturb file names.STDHDRS
Directories where headers can be found without resorting to using the flag to the C compiler. The $(STDHDRS) directories are used to find headers during scanning, but are not passed to the compiler commands as -I paths.SUBDIR
The path from the current directory to the directory last named by the SubDir rule.TOP
The path from the current directory to the directory that has the Jamrules file. Used by the SubDir rule.SUFEXE
The suffix for executable files, if none provided. Used by the Main rule.SUFLIB
The suffix for libraries. Used by the Library and related rules.SUFOBJ
The suffix for object files. Used by the Objects and related rules.UNDEFFLAG
The flag prefixed to each symbol for the Undefines rule (i.e., the compiler flag for undefined symbols).WATCOM
Selects Watcom compile and link actions on OS2.YACC
The yacc(1) command.YACCFILES
The base filename generated by yacc(1).YACCFLAGS
The yacc(1) command flags.YACCGEN
The suffix used on generated yacc(1) output.
Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
Copyright 2006-2008 Marc Boris Duerner
Comments to info@perforce.com
Last updated: Nov 5, 2008