Webmaster  |  Imprint 
Platinum
Platinum C++ Framework
Main  |  License  |  Documentation  |  Download  |  Support 

Building

The jam build-tool

Jam is a make-like program that provides a versatile, unified build process across many platforms including cross-compilation, build-configuration, automated unit-tests, and concurrent execution of build steps. This document intends to be a step-by-step introduction to the jam-based build system. The examples demonstrate 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.

Starting the build process

The jam tool must be invoked in the project root, where a 'jam' subdirectory and the files named 'Jambase', 'Jamrule' and 'Jamfile' are located. A precompiled binary of the jam program is provided for Windows platforms and a POSIX shell script for all other platforms, which builds the jam executable the first time it is excuted. 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. Th following is the equivalent to executing jam.exe on Windows:

./jam.sh -q

NOTE:
After a checkout the jam-script may needs to be made executable with the chmod command:

chmod +x ./jam.sh

Building specific targets

All artefacts that are created during the build process are refered to as 'targets'. A target can be a binary file, such as a executable or a so-called pseudo-target, which usually references other targets. All targets build a dependency tree and if jam is invoked to build a target, all dependencies will be resolved automatically and be built first. To build a specific target of the project simply invoke jam with a target name. The following command will build the target program.exe and all its dependencies:

jam.exe program.exe

Some important pseudo-targets are 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.exe lib

Rebuilding targets

To completely rebuild a target and its dependencies, the command line parameter -a can be passed to jam. The option -a can be used with or without a specific target. Thus the following command will rebuild the whole project:

jam.exe -a

A specific target can be rebuild by combining -a and a target name. The target program.exe will be completely rebuild with the following command:

jam.exe -a program.exe

Cleaning the project

The pseudo-target 'clean' plays a special role in the jam build system. All artefacts that are created during the build process are dependents of the 'clean' peseudo-target. When jam is invoked with the target clean, all artefacts will be deleted if they exist. Therefore the following command will remove all artefacts that were created by a build with default options:

jam.exe clean

Command line options

Several command line arguments can be passed to jam:

-a Build target(s), even if they are current.
-dx Set the debug level to x
-jx Run up to x shell command concurrently
-n Don't actually execute, but show the updating actions.
-q Quit quickly as soon as a target fails.
-sx=y Set variable x=y, overriding environment.

Build options

Various build options can be set to control how jam builds the targets, for example if a release or debug version should be built. Build options are set by special jam variables before or when jam is executed. A jam variable can be set with the command line option -s followed by a variable/value pair separated by the equal sign (-sVARIABLE=VALUE) or by setting a environment variable with the same name. When jam is invoked, all environment variables will be available as jam variables in the build scripts.

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.exe -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, 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

Compiling for Linux/Unix/Mac OS-X

Compiling for Linux or Mac OS-X with the GNU compiler is done from a normal shell. The default value for the TOOLSET is gcc already, so it doesn't have to be set explicitly. The following command builds a release version on a Linux system:

./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 compiler. The Gnu compiler can be used on these systems by setting the TOOLSET to gcc explicitly.

Compiling for Windows NT/XP with Visual Studio 7/8

The Microsoft visual studio installation contains a special 'build command shell'. It differs from a regular command shell in that more environment variables are set. If the build command shell is not used, the VISUALC variable has to be set either as environment variable or with -s when jam is invoked. If the path to the visual studio installation contains whitespace the path has to be put in quotes. The following command demonstrates how a build can be started from a regular console on windows to build with VisualC++ 2005 (vc8):

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=C:⁄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.

Compiling Windows CE targets

Windows CE targets need to be cross compiled under Windows NT/XP. Therefore the TARGET_OS and TARGET_OSPLAT variables need to be set when jam is invoked. No build command shell for embedded targets is provided by Microsoft, so the path to the Visual studio installation has to be set and a regular command shell has to be used. The following command builds for ARM CPU's:

jam.exe -sVISUALC="C:\Programme\Microsoft Visual Studio 8" 
        -sTOOLSET=vc8 -sTARGET_OS=wince -sTARGET_OSPLAT=arm

Compiling QNX targets

Building with jam on a QNX host is not different from building on unix systems. To build on a QNX system simply execute the shell script:

./jam.sh

QNX targets can be cross compiled or directly compiled on a QNX host. 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

Setting up a new Project

Jam requires a few files and one directory to be present to be able to compile a project:

Rules and Variable Syntax

A Jam variable is global and can be assigned with the equal sign. To get the value in a variable the $-sign has to be used:

VAR = 5 ;
Echo "The value is:" $(VAR) ;

The so called Jambase in the jam subdirectory and the rules taken from the file Jamrules can be used in the Jamfiles of the project to build targets. Rules can take multiple parameters which are separated by a colon. For Example the rule File, which copies files, can takes two parameters, the first is the target file, the second the source file:

 File target.txt : source.txt ;

Note that the jam syntax requires all tokens to be whitespace-separated including the semicolon at the end of each line.

Handling Directory Trees

Jam defines a special variable called TOP. This variable contains the path to the project root directory. Path names can be constructed rooted with TOP. The SubDir and SubInclude rules used to build the project tree take paths rooted with TOP.

The SubDir rule must be the first rule invoked in a Jamfile. It specifies the path to the current directory and initializes a set of variables that are used by other rules to uniquely identify the source files and assign locations. The SubDir rule takes as its first argument the root variable's name and takes as subsequent parameters the directory names leading from the root to the directory of the current Jamfile. The following means that the Jamfile which contains the SubDir statement is in the the directory /src/util:

SubDir $(TOP) src util

The Jamfile in the project root directory therefore simply sets its directory to with the SubDir rule.

The SubInclude rule is used in a Jamfile to include another Jamfile and to build up the project directory tree this way. Its arguments are in the same format as SubDir's. The recommended practice is to include only one level of subdirectories at a time and let the Jamfile in each subdirectory include its own subdirectories. The following Jamfile includes four other Jamfiles:

SubInclude $(TOP) src
SubInclude $(TOP) man
SubInclude $(TOP) util
SubInclude $(TOP) misc

The SubInclude statements must be the last statements in a Jamfile, because it is affected by the SubDir rule of the included Jamfiles. All paths are relative to the root directory.

Setting Include Paths

The rule 'SubDirHdrs' sets include paths for all source files in a directory. The following jam statement will add the path /include to the header search paths:

SubDirHdrs $(TOP)/include ;

Building Executables

The rule 'Main' can be used to build executables from a list of source files. The following example assumes that besides the mandatory jam files a file called main.cpp resides in the project tree that contains program code. To build a program called 'program', the Main rule must be applied in the Jamfile:

Main program : main.cpp ;

The first parameter passed to the rule is the target name, the second is the list of source files. All system specific target name decorations will be added by jam auomatically. So under windows the resulting binary will be called program.exe. Under unix it will simply be called 'program'.

Building static libraries

The rule 'Library' can be used to build a static library from a list of source files. The following example assumes that besides the mandatory jam file a file called example.cpp resides in the project tree that contains the library code. To build a static library called 'example' the Library rule must be used in the corresponding Jamfile:

Library example : example.cpp ;

The first parameter passed to the rule is the target name, the second is the list of source files. All system specific target name decorations will be added by jam auomatically. So under windows the resulting library will be called example.lib. Under unix it will be called libexample.a.

Building shared libraries

The rule 'SharedLibrary' can be used to build a shared library from a list of source files. The following example assumes that besides the mandatory jam files, a file called example.cpp resides in the project tree that contains the library code. To build a shared library called 'example' the SharedLibrary rule must be used in the corresponding Jamfile:

SharedLibrary example : example.cpp ;

The first parameter passed to the rule is the target name, the second is the list of source files. All system specific target name decorations will be added by jam auomatically. So 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.

Linking Executables

Separate rules exist to link shared or static libraries to an executable. The rule Main_LinkLibraries can be used to link a number of static libraries to an executable. This example assumes that a library called example is build from a source file example.cpp and linked to a program called 'program', which is to be built from a source file called main.cpp. The Jamfile in this case looks like this:

Library example : example.cpp ;

Main program : main.cpp ;
Main_LinkLibraries program : example ;

The first parameter passed to the rule 'Main_LinkLibraries' is the name of the target the static libraries should be linked to, the second is the list of static libraries to link.

The rule Main_LinkSharedLibraries can be used to link a number of shared libraries to an executable. This example assumes that a library called example is build from a source file example.cpp and linked to a program called 'program', which is to be built from a source file called main.cpp. The Jamfile in this case looks like this:

SharedLibrary example : example.cpp ;

Main program : main.cpp ;
Main_LinkLibraries program : example ;

The first parameter passed to the rule 'Main_LinkSharedLibraries' is the name of the target the shared libraries should be linked to, the second is the list of shared libraries to link.

Linking Shared Libraries

Separate rules exist to link shared or static libraries to a shared library. The rule SharedLibrary_LinkLibraries can be used to link a number of static libraries to a shared library. This example assumes that a library called tire is build from a source file tire.cpp and linked to a shared library called 'car', which is to be built from a source file called car.cpp. The Jamfile in this case looks like this:

Library tire : tire.cpp ;

SharedLibrary car : car.cpp ;
SharedLibrary_LinkLibraries car : tire ;

The first parameter passed to the rule 'SharedLibrary_LinkLibraries' is the name of the shared library target the static libraries should be linked to, the second is the list of static libraries to link.

The rule SharedLibrary_LinkSharedLibraries can be used to link a number of shared libraries to another shared library. This example assumes that a shared library called tire is build from a source file tire.cpp and linked to a shared library called 'car', which is to be built from a source file called car.cpp. The Jamfile in this case looks like this:

SharedLibrary tire : tire.cpp ;

SharedLibrary car : car.cpp ;
SharedLibrary_LinkSharedLibraries car : tire ;

The first parameter passed to the rule 'SharedLibrary_LinkSharedLibraries' is the name of the target the shared libraries should be linked to, the second is the list of shared libraries to link.

Copyright © 2003-2007 The Pt Development Team
Pt 1.0