Want to learn about B2 features? Start with the
tutorial and continue with the overview.
When you’re ready to try B2 in practice, go to the
installation.
If there’s anything you find unclear in this documentation, report the
problem directly in the issue
tracker. For more general questions, please post them to our discussion
forums (https://github.com/bfgroup/b2/discussions).
Copyright 2018-2021 René Ferdinand Rivera Morell;
Copyright 2006, 2014 Vladimir Prus.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE.txt or copy at https://www.bfgroup.xyz/b2/LICENSE.txt)
2. Installation
To install B2 from an official release, as available on
GitHub,
follow these steps:
Unpack the release. On the command line, go to the root of the
unpacked tree.
Run either .\bootstrap.bat (on Windows), or ./bootstrap.sh (on
other operating systems).
Run
$ ./b2 install --prefix=PREFIX
where PREFIX is a directory where you want B2 to be installed.
Optionally, add PREFIX/bin to your PATH environment variable.
$ PREFIX/bin/b2
A simple executable should be built.
ℹ
A C++11 capable compiler is needed to build the b2 engine. But using
the b2 engine and build system does not require C++11.
3. Tutorial
This section will guide you though the most basic features of
B2. We will start with the “Hello, world” example, learn how to
use libraries, and finish with testing and installing features.
3.1. Hello, world
The simplest project that B2 can construct is stored in
example/hello/ directory. The project is described by a file called
Jamfile that contains:
exe hello : hello.cpp ;
Even with this simple setup, you can do some interesting things. First
of all, just invoking b2 will build the hello executable by compiling
and linking hello.cpp. By default, the debug variant is built. Now, to
build the release variant of hello, invoke
b2 release
Note that the debug and release variants are created in different
directories, so you can switch between variants or even build multiple
variants at once, without any unnecessary recompilation. Let us extend
the example by adding another line to our project’s Jamfile:
exe hello2 : hello.cpp ;
Now let us build both the debug and release variants of our project
again:
b2 debug release
Note that two variants of hello2 are linked. Since we have already
built both variants of hello, hello.cpp will not be recompiled;
instead the existing object files will just be linked into the
corresponding variants of hello2. Now let us remove all the built
products:
b2 --clean debug release
It is also possible to build or clean specific targets. The following
two commands, respectively, build or clean only the debug version of
hello2.
b2 hello2
b2 --clean hello2
3.2. Properties
To represent aspects of target configuration such as debug and release
variants, or single- and multi-threaded builds portably, B2
uses features with associated values. For example, the debug-symbols
feature can have a value of on or off. A property is just a
(feature, value) pair. When a user initiates a build, B2
automatically translates the requested properties into appropriate
command-line flags for invoking toolset components like compilers and
linkers.
There are many built-in features that can be combined to produce
arbitrary build configurations. The following command builds the
project’s release variant with inlining disabled and debug symbols
enabled:
b2 release inlining=off debug-symbols=on
Properties on the command-line are specified with the syntax:
feature-name=feature-value
The release and debug that we have seen in b2 invocations are just
a shorthand way to specify values of the variant feature. For example,
the command above could also have been written this way:
b2 variant=release inlining=off debug-symbols=on
variant is so commonly-used that it has been given special status as
an implicit feature—B2 will deduce its identity just from the
name of one of its values.
The set of properties specified on the command line constitutes a build
request—a description of the desired properties for building the
requested targets (or, if no targets were explicitly requested, the
project in the current directory). The actual properties used for
building targets are typically a combination of the build request and
properties derived from the project’s Jamfile (and its other Jamfiles,
as described in
the section called “Project Hierarchies”).
For example, the locations of `#include`d header files are normally not
specified on the command-line, but described in Jamfiles as target
requirements and automatically combined with the build request for those
targets. Multi-threaded compilation is another example of a typical
target requirement. The Jamfile fragment below illustrates how these
requirements might be specified.
exe hello
: hello.cpp
: boost multi
;
When hello is built, the two requirements specified above will always
be present. If the build request given on the b2 command-line
explicitly contradicts a target’s requirements, the target requirements
usually override (or, in the case of “free” features like
, [1]
augment) the build request.
☀
The value of the feature is relative to the location of
Jamfile where it is used.
3.2.2. Project Attributes
If we want the same requirements for our other target, hello2, we
could simply duplicate them. However, as projects grow, that approach
leads to a great deal of repeated boilerplate in Jamfiles. Fortunately,
there’s a better way. Each project can specify a set of attributes,
including requirements:
The effect would be as if we specified the same requirement for both
hello and hello2.
3.3. Project Hierarchies
So far we have only considered examples with one project, with one
user-written Jamfile file. A typical large codebase would
be composed of many projects organized into a tree. The top of the tree
is called the project root. Every subproject is defined by a file called
Jamfile in a descendant directory of the project root. The parent
project of a subproject is defined by the nearest Jamfile
file in an ancestor directory. For example, in the following directory
layout:
the project root is top/. The projects in top/app/ and
top/util/foo/ are immediate children of the root project.
ℹ
When we refer to a “Jamfile,” set in normal type, we mean a file called
either Jamfile or Jamroot. When we need to be more specific, the
filename will be set as “Jamfile” or “Jamroot.”
Projects inherit all attributes (such as requirements) from their
parents. Inherited requirements are combined with any requirements
specified by the subproject. For example, if top/Jamfile has
/home/ghost/local
in its requirements, then all of its sub-projects will have it in their
requirements, too. Of course, any project can add include paths to those
specified by its parents. [2] More
details can be found in the section called “Projects”.
Invoking b2 without explicitly specifying any targets on the command
line builds the project rooted in the current directory. Building a
project does not automatically cause its sub-projects to be built unless
the parent project’s Jamfile explicitly requests it. In our example,
top/Jamfile might contain:
build-project app ;
which would cause the project in top/app/ to be built whenever the
project in top/ is built. However, targets in top/util/foo/ will be
built only if they are needed by targets in top/ or top/app/.
3.4. Dependent Targets
When building a target X that depends on first building another target
Y (such as a library that must be linked with X), Y is called a
dependency of X and X is termed a dependent of Y.
To get a feeling of target dependencies, let’s continue the above
example and see how top/app/Jamfile can use libraries from
top/util/foo. If top/util/foo/Jamfile contains
lib bar : bar.cpp ;
then to use this library in top/app/Jamfile, we can write:
exe app : app.cpp ../util/foo//bar ;
While app.cpp refers to a regular source file, ../util/foo//bar is a
reference to another target: a library bar declared in the Jamfile at
../util/foo.
☀
Some other build system have special syntax for listing dependent
libraries, for example LIBS variable. In B2, you just add the
library to the list of sources.
Suppose we build app with:
b2 app optimization=full define=USE_ASM
Which properties will be used to build foo? The answer is that some
features are propagated — B2 attempts to use dependencies with
the same value of propagated features. The feature is
propagated, so both app and foo will be compiled with full
optimization. But is not propagated: its value will be added
as-is to the compiler flags for a.cpp, but won’t affect foo.
Let’s improve this project further. The library probably has some
headers that must be used when compiling app.cpp. We could manually
add the necessary #include paths to the app requirements as values of
the feature, but then this work will be repeated for all
programs that use foo. A better solution is to modify
util/foo/Jamfile in this way:
Usage requirements are applied not to the target being declared but to
its dependents. In this case, . will be applied to all
targets that directly depend on foo.
Another improvement is using symbolic identifiers to refer to the
library, as opposed to Jamfile location. In a large project, a library
can be used by many targets, and if they all use Jamfile location, a change
in directory organization entails much work.
The solution is to use project ids—symbolic names not tied to directory
layout. First, we need to assign a project id by adding this code to
Jamfile:
use-project /library-example/foo : util/foo ;
Second, we modify app/Jamfile to use the project id:
exe app : app.cpp /library-example/foo//bar ;
The /library-example/foo//bar syntax is used to refer to the target
bar in the project with id /library-example/foo. We’ve achieved our
goal—if the library is moved to a different directory, only top/Jamfile
must be modified. Note that project ids are global—two Jamfiles
are not allowed to assign the same project id to different directories.
☀
If you want all applications in some project to link to a certain
library, you can avoid having to specify directly the sources of every
target by using the property. For example, if
/boost/filesystem//fs should be linked to all applications in your
project, you can add /boost/filesystem//fs to the project’s
requirements, like this:
project
: requirements /boost/filesystem//fs
;
3.5. Static and shared libraries
Libraries can be either static, which means they are included in
executable files that use them, or shared (a.k.a. dynamic), which
are only referred to from executables, and must be available at run
time. B2 can create and use both kinds.
The kind of library produced from a lib target is determined by the
value of the link feature. Default value is shared, and to build a
static library, the value should be static. You can request a static
build either on the command line:
b2 link=static
or in the library’s requirements:
lib l : l.cpp : static ;
We can also use the property to express linking requirements on
a per-target basis. For example, if a particular executable can be
correctly built only with the static version of a library, we can
qualify the executable’s target
reference to the library as follows:
exe important : main.cpp helpers/static ;
No matter what arguments are specified on the b2 command line,
important will only be linked with the static version of helpers.
Specifying properties in target references is especially useful if you
use a library defined in some other project (one you can’t change) but
you still want static (or dynamic) linking to that library in all cases.
If that library is used by many targets, you could use target
references everywhere:
but that’s far from being convenient. A better approach is to introduce
a level of indirection. Create a local alias target that refers to the
static (or dynamic) version of foo:
This works no matter what kind of linking is used. When core is built as a
shared library, links utils directly into it. Static libraries can’t link
to other libraries, so when core is built as a static library, its
dependency on utils is passed along to core’s dependents, causing `app
to be linked with both core and utils.
ℹ
(Note for non-UNIX system). Typically, shared libraries must be
installed to a directory in the dynamic linker’s search path. Otherwise,
applications that use shared libraries can’t be started. On Windows, the
dynamic linker’s search path is given by the PATH environment variable.
This restriction is lifted when you use B2 testing
facilities—the PATH variable will be automatically adjusted before
running the executable.
3.6. Conditions and alternatives
Sometimes, particular relationships need to be maintained among a
target’s build properties. For example, you might want to set specific
#define when a library is built as shared, or when a target’s
release variant is built. This can be achieved using conditional
requirements.
In the example above, whenever network is built with shared,
NETWORK_LIB_SHARED will be in its properties, too. Also, whenever
its release variant is built, EXTRA_FAST will appear in its
properties.
Sometimes the ways a target is built are so different that describing
them using conditional requirements would be hard. For example, imagine
that a library actually uses different source files depending on the
toolset used to build it. We can express this situation using target
alternatives:
When building demangler, B2 will compare requirements for
each alternative with build properties to find the best match. For
example, when building with gcc alternative (2), will be
selected, and when building with msvc alternative (3) will be
selected. In all other cases, the most generic alternative (1) will be
built.
3.7. Prebuilt targets
To link to libraries whose build instructions aren’t given in a Jamfile,
you need to create lib targets with an appropriate file property.
Target alternatives can be used to associate multiple library files with
a single conceptual target. For example:
This example defines two alternatives for lib2, and for each one names
a prebuilt file. Naturally, there are no sources. Instead, the
feature is used to specify the file name.
Once a prebuilt target has been declared, it can be used just like any
other target:
exe app : app.cpp ../util/lib2//lib2 ;
As with any target, the alternative selected depends on the properties
propagated from lib2’s dependents. If we build the release and debug
versions of `app it will be linked with lib2_release.a and
lib2_debug.a, respectively.
System libraries — those that are automatically found by the toolset by
searching through some set of predetermined paths — should be declared
almost like regular ones:
lib pythonlib : : python22 ;
We again don’t specify any sources, but give a name that should be
passed to the compiler. If the gcc toolset were used to link an
executable target to pythonlib, -lpython22 would appear in the
command line (other compilers may use different options).
We can also specify where the toolset should look for the library:
lib pythonlib : : python22 /opt/lib ;
And, of course, target alternatives can be used in the usual way:
This section will provide the information necessary to create your own
projects using B2. The information provided here is relatively
high-level, and the Reference as well as the on-line
help system must be used to obtain low-level documentation (see
--help).
B2 has two parts — a build engine with its own interpreted
language, and B2 itself, implemented in that language. The
chain of events when you type b2 on the command line is as follows:
The B2 executable tries to find B2 modules and
loads the top-level module. The exact process is described in
the section called “Initialization”
The top-level module loads user-defined configuration files,
user-config.jam and site-config.jam, which define available
toolsets.
The Jamfile in the current directory is read. That in turn might
cause reading of further Jamfiles. As a result, a tree of projects is
created, with targets inside projects.
Finally, using the build request specified on the command line,
B2 decides which targets should be built and how. That
information is passed back to Boost.Jam, which takes care of actually
running the scheduled build action commands.
So, to be able to successfully use B2, you need to know only
four things:
B2 has a few unique concepts that are introduced in this
section. The best way to explain the concepts is by comparison with more
classical build tools.
When using any flavor of make, you directly specify targets and
commands that are used to create them from other target. The below
example creates a.o from a.c using a hardcoded compiler invocation
command.
a.o: a.c
g++ -o a.o -g a.c
This is a rather low-level description mechanism and it’s hard to adjust
commands, options, and sets of created targets depending on the compiler
and operating system used.
To improve portability, most modern build system provide a set of
higher-level functions that can be used in build description files.
Consider this example:
add_program ("a", "a.c")
This is a function call that creates the targets necessary to create an
executable file from the source file a.c. Depending on configured
properties, different command lines may be used. However, add_program
is higher-level, but rather thin level. All targets are created
immediately when the build description is parsed, which makes it
impossible to perform multi-variant builds. Often, change in any build
property requires a complete reconfiguration of the build tree.
In order to support true multi-variant builds, B2 introduces the
concept of a metatarget definition main target metatarget
metatarget — an object that is created when the build description is
parsed and can be called later with specific build properties to
generate actual targets.
Consider an example:
exe a : a.cpp ;
When this declaration is parsed, B2 creates a metatarget, but
does not yet decide what files must be created, or what commands must be
used. After all build files are parsed, B2 considers the
properties requested on the command line. Supposed you have invoked
B2 with:
b2 toolset=gcc toolset=msvc
In that case, the metatarget will be called twice, once with
toolset=gcc and once with toolset=msvc. Both invocations will
produce concrete targets, that will have different extensions and use
different command lines.
Another key concept is build property. A build
property is a variable that affects the build process. It can be
specified on the command line, and is passed when calling a metatarget.
While all build tools have a similar mechanism, B2 differs by
requiring that all build properties are declared in advance, and
providing a large set of properties with portable semantics.
The final concept is property propagation.
B2 does not require that every metatarget is called with the
same properties. Instead, the "top-level" metatargets are called with
the properties specified on the command line. Each metatarget can elect
to augment or override some properties (in particular, using the
requirements mechanism, see
the section called “Requirements”).
Then, the dependency metatargets are called with the modified properties and
produce concrete targets that are then used in the build process. Of
course, dependency metatargets maybe in turn modify build properties and
have dependencies of their own.
For a more in-depth treatment of the requirements and concepts, you may
refer to SYRCoSE 2009
B2 article.
4.2. Boost.Jam Language
This section will describe the basics of the Boost.Jam language—just
enough for writing Jamfiles. For more information, please see the
Boost.Jam documentation.
Boost.Jam has an interpreted, procedural language. On
the lowest level, a Boost.Jam program consists of
variables and rules (the Jam term for functions). They are grouped
into modules—there is one global module and a number of named modules.
Besides that, a Boost.Jam program contains classes and
class instances.
Syntactically, a Boost.Jam program consists of two kinds
of elements—keywords (which have a special meaning to
Boost.Jam) and literals. Consider this code:
a = b ;
which assigns the value b to the variable a. Here, = and ; are
keywords, while a and b are literals.
⚠
All syntax elements, even keywords, must be separated by spaces. For
example, omitting the space character before ; will lead to a syntax
error.
If you want to use a literal value that is the same as some keyword, the
value can be quoted:
a = "=" ;
All variables in Boost.Jam have the same type—list of
strings. To define a variable one assigns a value to it, like in the
previous example. An undefined variable is the same as a variable with
an empty value. Variables can be accessed using the $(variable)
syntax. For example:
a = $(b) $(c) ;
Rules are defined by specifying the rule name, the parameter names, and
the allowed value list size for each parameter.
rule example
(
parameter1 :
parameter2 ? :
parameter3 + :
parameter4 *
)
{
# rule body
}
When this rule is called, the list passed as the first argument must
have exactly one value. The list passed as the second argument can
either have one value of be empty. The two remaining arguments can be
arbitrarily long, but the third argument may not be empty.
The overview of Boost.Jam language statements is given
below:
helper 1 : 2 : 3 ;
x = [ helper 1 : 2 : 3 ] ;
This code calls the named rule with the specified arguments. When the
result of the call must be used inside some expression, you need to add
brackets around the call, like shown on the second line.
if cond { statements } [ else { statements } ]
This is a regular if-statement. The condition is composed of:
Literals (true if at least one string is not empty)
Comparisons: a operator b where operator is one of =, !=, <,
>, ⇐ or >=. The comparison is done pairwise between each string
in the left and the right arguments.
Logical operations: ! a, a && b, a || b
Grouping: ( cond )
for var in list { statements }
Executes statements for each element in list, setting the variable var
to the element value.
while cond { statements }
Repeatedly execute statements while cond remains true upon entry.
return values ;
This statement should be used only inside a rule and returns values to
the caller of the rule.
import module ;
import module : rule ;
The first form imports the specified module. All rules from that module
are made available using the qualified name: module.rule. The second form
imports the specified rules only, and they can be called using unqualified
names.
Sometimes, you need to specify the actual command lines to be used when
creating targets. In the jam language, you use named actions to do this.
For example:
This specifies a named action called create-file-from-another. The text
inside braces is the command to invoke. The $(<) variable will be expanded
to a list of generated files, and the $(>) variable will be expanded to a
list of source files.
To adjust the command line flexibly, you can define a rule with the same
name as the action and taking three parameters — targets, sources and
properties. For example:
In this example, the rule checks if a certain build property is
specified. If so, it sets the variable OPTIONS that is then used
inside the action. Note that the variables set "on a target" will be
visible only inside actions building that target, not globally. Were
they set globally, using variable named OPTIONS in two unrelated
actions would be impossible.
On startup, B2 searches and reads three configuration files:
site-config.jam, user-config.jam, and project-config.jam. The
first one is usually installed and maintained by a system administrator,
and the second is for the user to modify. You can edit the one in the
top-level directory of your B2 installation or create a copy in
your home directory and edit the copy. The third is used for project
specific configuration. The following table explains where the files are
searched.
You can use the --debug-configuration option to find which
configuration files are actually loaded.
Usually, user-config.jam just defines the available compilers and
other tools (see the section called “Targets
in site-config.jam” for more advanced usage). A tool is configured using
the following syntax:
using tool-name : ... ;
The using rule is given the name of tool, and will make that tool
available to B2. For example,
You can put using ; with no other argument in a Jamfile
that needs the tool, provided that the tool supports this usage.
In all other cases, the using rule should be in a configuration file.
The general principle is that descriptions in Jamfile should be
maintained as portable while configuration files are system specific.
All the supported tools are documented in
the section called “Builtin tools”, including the
specific options they take. Some general notes that apply to most C++
compilers are below.
For all the C++ compiler toolsets that B2 supports
out-of-the-box, the list of parameters to using is the same:
toolset-name, version, invocation-command, and options.
If you have a single compiler, and the compiler executable
has its “usual name” and is in the PATH, or
was installed in a standard “installation directory”, or
can be found using a global system like the Windows registry.
it can be configured by simply:
using tool-name ;
If the compiler is installed in a custom directory, you should provide
the command that invokes the compiler, for example:
using gcc : : g++-3.2 ;
using msvc : : "Z:/Programs/Microsoft Visual Studio/vc98/bin/cl" ;
Some B2 toolsets will use that path to take additional actions
required before invoking the compiler, such as calling vendor-supplied
scripts to set up its required environment variables. When the compiler
executables for C and C++ are different, the path to the C++ compiler
executable must be specified. The command can be any command allowed by
the operating system. For example:
using msvc : : echo Compiling && foo/bar/baz/cl ;
will work.
To configure several versions of a toolset, simply invoke the using
rule multiple times:
using gcc : 3.3 ;
using gcc : 3.4 : g++-3.4 ;
using gcc : 3.2 : g++-3.2 ;
using gcc : 5 ;
using clang : 3.9 ;
using msvc : 14.0 ;
Note that in the first call to using, the compiler found in the PATH
will be used, and there is no need to explicitly specify the command.
Many of toolsets have an options parameter to fine-tune the
configuration. All of B2’s standard compiler toolsets accept
four options cflags, cxxflags, compileflags and linkflags as
options specifying flags that will be always passed to the
corresponding tools. There must not be a space between the tag for the
option name and the value. Values of the cflags feature are passed
directly to the C compiler, values of the cxxflags feature are passed
directly to the C++ compiler, and values of the compileflags feature
are passed to both. For example, to configure a gcc toolset so that it
always generates 64-bit code you could write:
using gcc : 3.4 : : -m64 -m64 ;
If multiple of the same type of options are needed, they can be
concatenated with quotes or have multiple instances of the option tag.
using gcc : 5 : : "-std=c++14 -O2" ;
using clang : 3.9 : : -std=c++14 -O2 ;
Multiple variations of the same tool can be used for most tools. These
are delineated by the version passed in. Because the dash '-' cannot be
used here, the convention has become to use the tilde '~' to delineate
variations.
using gcc : 5 : g++-5 : ; # default is C++ 98
using gcc : 5~c++03 : g++-5 : -std=c++03 ; # C++ 03
using gcc : 5~gnu03 : g++-5 : -std=gnu++03 ; # C++ 03 with GNU
using gcc : 5~c++11 : g++-5 : -std=c++11 ; # C++ 11
using gcc : 5~c++14 : g++-5 : -std=c++14 ; # C++ 14
Although the syntax used to specify toolset options is very similar
to syntax used to specify requirements in Jamfiles, the toolset options are
not the same as features. Don’t try to specify a feature value in
toolset initialization.
4.4. Invocation
To invoke B2, type b2 on the command line. Three kinds of
command-line tokens are accepted, in any order:
options
Options start with either one or two dashes. The standard options are
listed below, and each project may add additional options
properties
Properties specify details of what you want to build (e.g. debug or
release variant). Syntactically, all command line tokens with an equal
sign in them are considered to specify properties. In the simplest
form, a property looks like feature=value
target
All tokens that are neither options nor properties specify what
targets to build. The available targets entirely depend on the project
you are building.
4.4.1. Examples
To build all targets defined in the Jamfile in the current directory
with the default properties, run:
b2
To build specific targets, specify them on the command line:
b2 lib1 subproject//lib2
To request a certain value for some property, add property=value to the
command line:
b2 toolset=gcc variant=debug optimization=space
4.4.2. Options
B2 recognizes the following command line options.
--help
Invokes the online help system. This prints general information on how
to use the help system with additional --help* options.
--clean
Cleans all targets in the current directory and in any sub-projects.
Note that unlike the clean target in make, you can use --clean
together with target names to clean specific targets.
--clean-all
Cleans all targets, no matter where they are defined. In particular,
it will clean targets in parent Jamfiles, and targets defined under
other project roots.
--build-dir
Changes the build directories for all project roots being built. When
this option is specified, all Jamroot files must declare a project
name. The build directory for the project root will be computed by
concatenating the value of the --build-dir option, the project name
specified in Jamroot, and the build dir specified in Jamroot (or
bin, if none is specified).
The option is primarily useful when building from read-only media,
when you can’t modify Jamroot.
--abbreviate-paths
Compresses target paths by abbreviating each component. This option is
useful to keep paths from becoming longer than the filesystem
supports. See also the
section called “Target Paths”.
--hash
Compresses target paths using an MD5 hash. This option is useful to
keep paths from becoming longer than the filesystem supports. This
option produces shorter paths than --abbreviate-paths does, but at the
cost of making them less understandable. See also
the section called “Target
Paths”.
--version
Prints information on the B2 and Boost.Jam versions.
-a
Causes all files to be rebuilt.
-n
Do not execute the commands, only print them.
-q
Stop at the first error, as opposed to continuing to build targets
that don’t depend on the failed ones.
-j N
Run up to N commands in parallel. Default number of jobs is the number
of detected available CPU threads. Note: There are circumstances when that
default can be larger than the allocated cpu resources, for instance in some
virtualized container installs.
Produces debug information about the loading of B2 and
toolset files.
--debug-building
Prints what targets are being built and with what properties.
--debug-generators
Produces debug output from the generator search process. Useful for
debugging custom generators.
-d0
Suppress all informational messages.
-d N
Enable cumulative debugging levels from 1 to n. Values are:
+
Show the actions taken for building targets, as they are executed
(the default).
Show "quiet" actions and display all action text, as they are
executed.
Show dependency analysis, and target/source timestamps/paths.
Show arguments and timing of shell invocations.
Show rule invocations and variable expansions.
Show directory/header file/archive scans, and attempts at binding
to targets.
Show variable settings.
Show variable fetches, variable expansions, and evaluation of
'"if"' expressions.
Show variable manipulation, scanner tokens, and memory usage.
Show profile information for rules, both timing and memory.
Show parsing progress of Jamfiles.
Show graph of target dependencies.
Show change target status (fate).
-d +N
Enable debugging level N.
-o file
Write the updating actions to the specified file instead of running
them.
-s var=value
Set the variable var to value in the global scope of the jam language
interpreter, overriding variables imported from the environment.
4.4.3. Properties
In the simplest case, the build is performed with a single set of
properties, that you specify on the command line with elements in the
form feature=value. The complete list of features can be found in
the section called “Builtin features”.
The most common features are summarized below.
Feature
Allowed values
Notes
variant
debug,release
link
shared,static
Determines if B2 creates shared or static libraries
threading
single,multi
Cause the produced binaries to be thread-safe. This requires proper support
in the source code itself.
address-model
32,64
Explicitly request either 32-bit or 64-bit code
generation. This typically requires that your compiler is appropriately
configured. Please refer to
the section called “C++ Compilers”
and your compiler documentation in case of problems.
Additional macro definitions for C and C++ compilers. The string should be
either SYMBOL or SYMBOL=VALUE
cxxflags
(Arbitrary string)
Custom options to pass to the C++ compiler.
cflags
(Arbitrary string)
Custom options to pass to the C compiler.
linkflags
(Arbitrary string)
Custom options to pass to the C++ linker.
runtime-link
shared,static
Determines if shared or static version of C and C++ runtimes should be used.
If you have more than one version of a given C++ toolset (e.g.
configured in user-config.jam, or autodetected, as happens with msvc),
you can request the specific version by passing toolset-version as the
value of the toolset feature, for example toolset=msvc-8.0.
If a feature has a fixed set of values it can be specified more than
once on the command line. In which case, everything will be built
several times — once for each specified value of a feature. For
example, if you use
Then a total of 4 builds will be performed. For convenience, instead of
specifying all requested values of a feature in separate command line
elements, you can separate the values with commas, for example:
b2 link=static,shared threading=single,multi
The comma has this special meaning only if the feature has a fixed set
of values, so
b2 include=static,shared
is not treated specially.
Multiple features may be grouped by using a forwards slash.
b2 gcc/link=shared msvc/link=static,shared
This will build 3 different variants, altogether.
4.4.4. Targets
All command line elements that are neither options nor properties are
the names of the targets to build. See the section
called “Target identifiers and references”. If no target is specified, the
project in the current directory is built.
4.5. Declaring Targets
A Main target is a user-defined named entity that can be built, for
example an executable file. Declaring a main target is usually done
using one of the main target rules described in
the section called “Builtin rules”. The user can
also declare custom main target rules as shown in
the section called “Main target rules”.
Most main target rules in B2 have the same common signature:
main-target-name is the name used to request the target on command
line and to use it from other main targets. A main target name may
contain alphanumeric characters, dashes (‘-’), and underscores
(‘_’).
sources is the list of source files and other main targets that must
be combined.
requirements is the list of properties that must always be present
when this main target is built.
default-build is the list of properties that will be used unless
some other value of the same feature is already specified, e.g. on the
command line or by propagation from a dependent target.
usage-requirements is the list of properties that will be propagated
to all main targets that use this one, i.e. to all its dependents.
Some main target rules have a different list of parameters as explicitly
stated in their documentation.
The actual requirements for a target are obtained by refining the
requirements of the project where the target is declared with the
explicitly specified requirements. The same is true for
usage-requirements. More details can be found in
the section called “Property refinement”.
4.5.1. Name
The name of main target has two purposes. First, it’s used to refer to
this target from other targets and from command line. Second, it’s used
to compute the names of the generated files. Typically, filenames are
obtained from main target name by appending system-dependent suffixes
and prefixes.
The name of a main target can contain alphanumeric characters, dashes,
underscores and dots. The entire name is significant when resolving
references from other targets. For determining filenames, only the part
before the first dot is taken. For example:
will generate two files named test.obj (in two different directories),
not two files named test.release.obj and test.debug.obj.
4.5.2. Sources
The list of sources specifies what should be processed to get the
resulting targets. Most of the time, it’s just a list of files.
Sometimes, you’ll want to automatically construct the list of source
files rather than having to spell it out manually, in which case you can
use the glob rule. Here are two
examples:
exe a : a.cpp ; (1)
exe b : [ glob *.cpp ] ; (2)
a.cpp is the only source file
all .cpp files in this directory are sources
Unless you specify a file with an absolute path, the name is considered
relative to the source directory — which is typically the directory
where the Jamfile is located, but can be changed as described in
the section called “Projects”.
The list of sources can also refer to other main targets. Targets in the
same project can be referred to by name, while targets in other projects
must be qualified with a directory or a symbolic project name. The
directory/project name is separated from the target name by a double
forward slash. There is no special syntax to distinguish the directory
name from the project name—the part before the double slash is first
looked up as project name, and then as directory name. For example:
lib helper : helper.cpp ;
exe a : a.cpp helper ;
exe b : b.cpp ..//utils ; (1)
exe c : c.cpp /boost/program_options//program_options ;
Since all project ids start with slash, “..” is a directory name.
The first exe uses the library defined in the same project. The second
one uses some target (most likely a library) defined by a Jamfile one
level higher. Finally, the third target uses a C++
Boost library, referring to it using its absolute symbolic name. More
information about target references can be found in
the section called “Dependent Targets” and
the section called “Target identifiers and references”.
4.5.3. Requirements
Requirements are the properties that should always be present when
building a target. Typically, they are includes and defines:
exe hello : hello.cpp : /opt/boost MY_DEBUG ;
There are a number of other features, listed in
the section called “Builtin features”.
For example if a library can only be built statically, or a file can’t be
compiled with optimization due to a compiler bug, one can use.
lib util : util.cpp : static ;
obj main : main.cpp : off ;
Sometimes, particular
relationships need to be
maintained among a target’s build properties. This can be achieved with
conditional requirements. For example, you might want to set specific
#defines when a library is built as shared, or when a target’s
release variant is built in release mode.
A more powerful variant of conditional requirements
is indirect conditional requirements. You can provide a rule that will
be called with the current build properties and can compute additional
properties to be added. For example:
lib network : network.cpp
: @my-rule
;
rule my-rule ( properties * )
{
local result ;
if gcc speed in $(properties)
{
result += USE_INLINE_ASSEMBLER ;
}
return $(result) ;
}
This example is equivalent to the previous one, but for complex cases,
indirect conditional requirements can be easier to write and understand.
Requirements explicitly specified for a target are usually combined with
the requirements specified for the containing project. You can cause a
target to completely ignore a specific project requirement using the
syntax by adding a minus sign before the property, for example:
exe main : main.cpp : -UNNECESSARY_DEFINE ;
This syntax is the only way to ignore free properties, such as defines,
from a parent. It can be also useful for ordinary properties. Consider
this example:
project test : requirements multi ;
exe test1 : test1.cpp ;
exe test2 : test2.cpp : single ;
exe test3 : test3.cpp : -multi ;
Here, test1 inherits the project requirements and will always be built
in multi-threaded mode. The test2 target overrides the project’s
requirements and will always be built in single-threaded mode. In
contrast, the test3 target removes a property from the project
requirements and will be built either in single-threaded or
multi-threaded mode depending on which variant is requested by the user.
Note that the removal of requirements is completely textual: you need to
specify exactly the same property to remove it.
4.5.4. Default Build
The default-build parameter is a set of properties to be used if the
build request does not otherwise specify a value for features in the
set. For example:
exe hello : hello.cpp : : multi ;
would build a multi-threaded target unless the user explicitly requests
a single-threaded version. The difference between the requirements and
the default-build is that the requirements cannot be overridden in any
way.
4.5.5. Additional Information
The ways a target is built can be so different that describing them
using conditional requirements would be hard. For example, imagine that
a library actually uses different source files depending on the toolset
used to build it. We can express this situation using target alternatives:
lib demangler : dummy_demangler.cpp ; # alternative 1
lib demangler : demangler_gcc.cpp : gcc ; # alternative 2
lib demangler : demangler_msvc.cpp : msvc ; # alternative 3
In the example above, when built with gcc or msvc, demangler will
use a source file specific to the toolset. Otherwise, it will use a
generic source file, dummy_demangler.cpp.
It is possible to declare a target inline, i.e. the "sources" parameter
may include calls to other main rules. For example:
Will cause "helpers.cpp" to be always compiled without optimization.
When referring to an inline main target, its declared name must be
prefixed by its parent target’s name and two dots. In the example above,
to build only helpers, one should run b2 hello..helpers.
When no target is requested on the command line, all targets in the
current project will be built. If a target should be built only by
explicit request, this can be expressed by the
explicit rule:
explicit install_programs ;
4.6. Projects
As mentioned before, targets are grouped into projects, and each Jamfile
is a separate project. Projects are useful because they allow us to
group related targets together, define properties common to all those
targets, and assign a symbolic name to the project that can be used in
referring to its targets.
Projects are named using the project rule, which has the following
syntax:
project id : attributes ;
Here, attributes is a sequence of rule arguments, each of which begins
with an attribute-name and is followed by any number of build
properties. The list of attribute names along with its handling is also
shown in the table below. For example, it is possible to write:
project tennis
: requirements multi
: default-build release
;
The possible attributes are listed below.
Project id is a short way to denote a project, as opposed to the
Jamfile’s pathname. It is a hierarchical path, unrelated to filesystem,
such as "boost/thread". Target references make
use of project ids to specify a target.
Source location specifies the directory where sources for the project
are located.
Project requirements are requirements that apply to all the targets in
the projects as well as all sub-projects.
Default build is the build request that should be used when no build
request is specified explicitly.
The default values for those attributes are given in the table below.
Attribute
Name
Default value
Handling by the project rule
Project id
none
none
Assigned from the first parameter of the
'project' rule. It is assumed to denote absolute project id.
Source location
source-location
The location of jamfile for the
project
Sets to the passed value
Requirements
requirements
The parent’s requirements
The parent’s
requirements are refined with the passed requirement and the result is
used as the project requirements.
Default build
default-build
none
Sets to the passed value
Build directory
build-dir
Empty if the parent has no build
directory set. Otherwise, the parent’s build directory with the relative
path from parent to the current project appended to it.
Sets to the
passed value, interpreted as relative to the project’s location.
Besides defining projects and main targets, Jamfiles often invoke
various utility rules. For the full list of rules that can be directly
used in Jamfile see
the section called “Builtin rules”.
Each subproject inherits attributes, constants and rules from its parent
project, which is defined by the nearest Jamfile in an ancestor
directory above the subproject. The top-level project is declared in a
file called Jamroot, or Jamfile. When loading a project,
B2 looks for either Jamroot or Jamfile. They are handled
identically, except that if the file is called Jamroot, the search for
a parent project is not performed. A Jamfile without a parent project
is also considered the top-level project.
Even when building in a subproject directory, parent project files are
always loaded before those of their sub-projects, so that every
definition made in a parent project is always available to its children.
The loading order of any other projects is unspecified. Even if one
project refers to another via the use-project or a target reference,
no specific order should be assumed.
ℹ
Giving the root project the special name “Jamroot” ensures that
B2 won’t misinterpret a directory above it as the project root
just because the directory contains a Jamfile.
4.7. The Build Process
When you’ve described your targets, you want B2 to run the
right tools and create the needed targets. This section will describe
two things: how you specify what to build, and how the main targets are
actually constructed.
The most important thing to note is that in B2, unlike other
build tools, the targets you declare do not correspond to specific
files. What you declare in a Jamfile is more like a “metatarget.”
Depending on the properties you specify on the command line, each
metatarget will produce a set of real targets corresponding to the
requested properties. It is quite possible that the same metatarget is
built several times with different properties, producing different
files.
☀
This means that for B2, you cannot directly obtain a build
variant from a Jamfile. There could be several variants requested by the
user, and each target can be built with different properties.
4.7.1. Build Request
The command line specifies which targets to build and with which
properties. For example:
would build two targets, "app1" and "lib1//lib1" with the specified
properties. You can refer to any targets, using
target id and specify arbitrary properties.
Some of the properties are very common, and for them the name of the
property can be omitted. For example, the above can be written as:
When you request, directly or indirectly, a build of a main target with
specific requirements, the following steps are done. Some brief
explanation is provided, and more details are given in
the section called “Build process”.
Applying default build. If the default-build property of a target
specifies a value of a feature that is not present in the build request,
that value is added.
Selecting the main target alternative to use. For each alternative
we look how many properties are present both in alternative’s
requirements, and in build request. The alternative with largest number
of matching properties is selected.
Determining "common" properties. The build request is
refined with target’s
requirements. The conditional properties in requirements are handled as
well. Finally, default values of features are added.
Building targets referred by the sources list and dependency
properties. The list of sources and the properties can refer to other
target using target references. For each
reference, we take all
propagated
properties, refine them by explicit properties specified in the target
reference, and pass the resulting properties as build request to the
other target.
Adding the usage requirements produced when building dependencies to
the "common" properties. When dependencies are built in the previous
step, they return both the set of created "real" targets, and usage
requirements. The usage requirements are added to the common properties
and the resulting property set will be used for building the current
target.
Building the target using generators. To convert the sources to the
desired type, B2 uses "generators" — objects that correspond
to tools like compilers and linkers. Each generator declares what type
of targets it can produce and what type of sources it requires. Using
this information, B2 determines which generators must be run to
produce a specific target from specific sources. When generators are
run, they return the "real" targets.
Computing the usage requirements to be returned. The conditional
properties in usage requirements are expanded and the result is
returned.
4.7.3. Building a Project
Often, a user builds a complete project, not just one main target. In
fact, invoking b2 without arguments builds the project defined in the
current directory.
When a project is built, the build request is passed without
modification to all main targets in that project. It’s is possible to
prevent implicit building of a target in a project with the explicit
rule:
explicit hello_test ;
would cause the hello_test target to be built only if explicitly
requested by the user or by some other target.
The Jamfile for a project can include a number of build-project rule
calls that specify additional projects to be built.
5. Common tasks
This section describes main targets types that B2 supports
out-of-the-box. Unless otherwise noted, all mentioned main target rules
have the common signature, described in
the section called “Declaring Targets”.
5.1. Programs
Programs are created using the exe rule, which follows the
common syntax. For example:
exe hello
: hello.cpp some_library.lib /some_project//library
: multi
;
This will create an executable file from the sources—in this case,
one C++ file, one library file present in the same directory, and
another library that is created by B2. Generally, sources can
include C and C++ files, object files and libraries. B2 will
automatically try to convert targets of other types.
☀
On Windows, if an application uses shared libraries, and both the
application and the libraries are built using B2, it is not
possible to immediately run the application, because the PATH environment
variable should include the path to the libraries. It means you have to either
add the paths manually, or have the build place the application and the
libraries into the same directory. See
the section called “Installing”.
5.2. Libraries
Library targets are created using the lib rule, which follows the
common syntax. For example:
lib helpers : helpers.cpp ;
This will define a library target named helpers built from the
helpers.cpp source file. It can be either a static library or a shared
library, depending on the value of the
feature.
Library targets can represent:
Libraries that should be built from source, as in the example above.
Prebuilt libraries which already exist on the system. Such libraries
can be searched for by the tools using them (typically with the linker’s
-l option) or their paths can be known in advance by the build system.
The syntax for prebuilt libraries is given below:
lib z : : z /home/ghost ;
lib compress : : /opt/libs/compress.a ;
The name property specifies the name of the library without the
standard prefixes and suffixes. For example, depending on the system,
z could refer to a file called z.so, libz.a, or z.lib, etc. The
search feature specifies paths in which to search for the library in
addition to the default compiler paths. search can be specified
several times or it can be omitted, in which case only the default
compiler paths will be searched. The file property specifies the file
location.
The difference between using the file feature and using a combination
of the name and search features is that file is more precise.
⚠
The value of the search feature is just added to the linker search
path. When linking to multiple libraries, the paths specified by
search are combined without regard to which lib target each path
came from. Thus, given
lib a : : a /pool/release ;
lib b : : b /pool/debug ;
If /pool/release/a.so, /pool/release/b.so, /pool/debug/a.so, and
/pool/release/b.so all exist, the linker will probably take both a and
b from the same directory, instead of finding a in /pool/release and
b in /pool/debug. If you need to distinguish between multiple
libraries with the same name, it’s safer to use file.
For convenience, the following syntax is allowed:
lib z ;
lib gui db aux ;
which has exactly the same effect as:
lib z : : z ;
lib gui : : gui ;
lib db : : db ;
lib aux : : aux ;
When a library references another library you should put that other
library in its list of sources. This will do the right thing in all
cases. For portability, you should specify library dependencies even for
searched and prebuilt libraries, otherwise, static linking on Unix will
not work. For example:
lib z ;
lib png : z : png ;
ℹ
When a library has a shared library as a source, or a static library has
another static library as a source then any target linking to the first
library with automatically link to its source library as well.
On the other hand, when a shared library has a static library as a
source then the first library will be built so that it completely
includes the second one.
If you do not want a shared library to include all the libraries
specified in its sources (especially statically linked ones), you would
need to use the following:
lib b : a.cpp ;
lib a : a.cpp :
This specifies that library a uses library b, and causes all
executables that link to a to link to b also. In this case, even for
shared linking, the a library will not refer to b.
Usage requirements are often very useful
for defining library targets. For example, imagine that you want you
build a helpers library and its interface is described in its
helpers.hpp header file located in the same directory as the
helpers.cpp source file. Then you could add the following to the
Jamfile located in that same directory:
lib helpers : helpers.cpp : : : . ;
which would automatically add the directory where the target has been
defined (and where the library’s header file is located) to the
compiler’s include path for all targets using the helpers library.
This feature greatly simplifies Jamfiles.
5.3. Alias
The alias rule gives an alternative name to a group of targets. For
example, to give the name core to a group of three other targets with
the following code:
alias core : im reader writer ;
Using core on the command line, or in the source list of any other
target is the same as explicitly using im, reader, and writer.
Another use of the alias rule is to change build properties. For
example, if you want to link statically to the Boost Threads
library, you can write the following:
alias threads : /boost/thread//boost_thread : static ;
and use only the threads alias in your Jamfiles.
You can also specify usage requirements for the alias target. If you
write the following:
alias header_only_library : : : : /usr/include/header_only_library ;
then using header_only_library in sources will only add an include
path. Also note that when an alias has sources, their usage requirements
are propagated as well. For example:
will compile main.cpp with additional includes required for using the
specified static libraries.
5.4. Installing
This section describes various ways to install built targets and
arbitrary files.
5.4.1. Basic install
For installing a built target you should use the install rule, which
follows the common syntax. For
example:
install dist : hello helpers ;
will cause the targets hello and helpers to be moved to the dist
directory, relative to the Jamfile’s directory. The directory can be
changed using the location property:
install dist : hello helpers : /usr/bin ;
While you can achieve the same effect by changing the target name to
/usr/bin, using the location property is better as it allows you to
use a mnemonic target name.
The location property is especially handy when the location is not
fixed, but depends on the build variant or environment variables:
Specifying the names of all libraries to install can be boring. The
install allows you to specify only the top-level executable targets to
install, and automatically install all dependencies:
install dist : hello :
on EXE
LIB
;
will find all targets that hello depends on, and install all of those
which are either executables or libraries. More specifically, for each
target, other targets that were specified as sources or as dependency
properties, will be recursively found. One exception is that targets
referred with the use feature are not
considered, as that feature is typically used to refer to header-only
libraries. If the set of target types is specified, only targets of that
type will be installed, otherwise, all found target will be installed.
5.4.3. Preserving Directory Hierarchy
By default, the install rule will strip paths from its sources. So, if
sources include a/b/c.hpp, the a/b part will be ignored. To make the
install rule preserve the directory hierarchy you need to use the
feature to specify the root of the hierarchy you
are installing. Relative paths from that root will be preserved. For
example, if you write:
install headers
: a/b/c.h
: /tmp a
;
the a file named /tmp/b/c.h will be created.
The glob-tree rule can be used to find
all files below a given directory, making it easy to install an entire
directory tree.
5.4.4. Installing into Several Directories
The alias rule can be used when targets need
to be installed into several directories:
Because the install rule just copies targets, most free features
[3]
have no effect when used in requirements of the install rule. The only two
that matter are
dependency and, on Unix,
dll-path.
ℹ
(Unix specific) On Unix, executables built using B2 typically
contain the list of paths to all used shared libraries. For installing,
this is not desired, so B2 relinks the executable with an empty
list of paths. You can also specify additional paths for installed
executables using the dll-path feature.
5.5. Testing
B2 has convenient support for running unit tests. The simplest
way is the unit-test rule, which follows the
common syntax. For example:
The unit-test rule behaves like the exe
rule, but after the executable is created it is also run. If the
executable returns an error code, the build system will also return an
error and will try running the executable on the next invocation until
it runs successfully. This behavior ensures that you can not miss a
unit test failure.
There are few specialized testing rules, listed below:
They are given a list of sources and requirements. If the target name is
not provided, the name of the first source file is used instead. The
compile* tests try to compile the passed source. The link* rules try
to compile and link an application from all the passed sources. The
compile and link rules expect that compilation/linking succeeds. The
compile-fail and link-fail rules expect that the
compilation/linking fails.
There are two specialized rules for running executables, which are more
powerful than the unit-test rule. The run rule has the following
signature:
The rule builds application from the provided sources and runs it,
passing args and input-files as command-line arguments. The args
parameter is passed verbatim and the values of the input-files
parameter are treated as paths relative to containing Jamfile, and are
adjusted if b2 is invoked from a different directory. The run-fail
rule is identical to the run rule, except that it expects that the run
fails.
All rules described in this section, if executed successfully, create a
special manifest file to indicate that the test passed. For the
unit-test rule the files is named target-name.passed and for the other
rules it is called target-name.test. The run* rules also capture all
output from the program, and store it in a file named target-name.output.
If the preserve-test-targets feature has the
value off, then run and the run-fail rules will remove the
executable after running it. This somewhat decreases disk space
requirements for continuous testing environments. The default value of
preserve-test-targets feature is on.
It is possible to print the list of all test targets (except for
unit-test) declared in your project, by passing the --dump-tests
command-line option. The output will consist of lines of the form:
boost-test(test-type) path : sources
It is possible to process the list of tests, B2 output and the
presence/absence of the *.test files created when test passes into
human-readable status table of tests. Such processing utilities are not
included in B2.
The following features adjust behavior of the testing metatargets.
testing.arg
Defines an argument to be passed to the target when it is executed
before the list of input files.
Specifies a file to be passed to the executable on the command line
after the arguments. All files must be specified in alphabetical order
due to constraints in the current implementation.
testing.launcher
By default, the executable is run directly. Sometimes, it is desirable
to run the executable using some helper command. You should use this
property to specify the name of the helper command. For example, if
you write:
A description of the test. This is displayed as part of the
--dump-tests command-line option.
5.6. Custom commands
For most main target rules, B2 automatically figures out the
commands to run. When you want to use new file types or support new
tools, one approach is to extend B2 to support them smoothly,
as documented in Extender Manual. However, if the new
tool is only used in a single place, it might be easier just to specify the
commands to run explicitly.
Three main target rules can be used for that. The make rule allows you to
construct a single file from any number of source file, by running a command
you specify. The notfile rule allows you to run an arbitrary command,
without creating any files. And finally, the generate rule allows you to
describe a transformation using B2’s virtual targets. This is
higher-level than the file names that the make rule operates with and
allows you to create more than one target, create differently named targets
depending on properties, or use more than one tool.
The make rule is used when you want to create one file from a number
of sources using some specific command. The notfile is used to
unconditionally run a command.
Suppose you want to create the file file.out from the file file.in
by running the command in2out. Here is how you would do this in B2:
If you run b2 and file.out does not exist, B2 will run the
in2out command to create that file. For more details on specifying
actions, see
the section called “Boost.Jam Language”.
It could be that you just want to run some command unconditionally, and
that command does not create any specific files. For that you can use
the notfile rule. For example:
The only difference from the make rule is that the name of the target
is not considered a name of a file, so B2 will unconditionally
run the action.
The generate rule is used when you want to express transformations
using B2’s virtual targets, as opposed to just filenames. The
generate rule has the standard main target rule signature, but you are
required to specify the generating-rule property. The value of the
property should be in the form @rule-name, the named rule should have the
following signature:
and will be called with an instance of the project-target class, the
name of the main target, an instance of the property-set class
containing build properties, and the list of instances of the
virtual-target class corresponding to sources. The rule must return a
list of virtual-target instances. The interface of the
virtual-target class can be learned by looking at the
build/virtual-target.jam file. The generate example contained in the
B2 distribution illustrates how the generate rule can be
used.
5.7. Precompiled Headers
Precompiled headers is a mechanism to speed up compilation by creating a
partially processed version of some header files, and then using that
version during compilations rather then repeatedly parsing the original
headers. B2 supports precompiled headers with gcc and msvc
toolsets.
To use precompiled headers, follow the following steps:
Create a header that includes headers used by your project that you
want precompiled. It is better to include only headers that are
sufficiently stable — like headers from the compiler and external
libraries. B2 will include the header automatically and on-demand.
Declare a new B2 target for the precompiled header and add
that precompiled header to the sources of the target whose compilation
you want to speed up:
cpp-pch pch : pch.hpp ;
exe main : main.cpp pch ;
You can use the c-pch rule if you want to use the precompiled header
in C programs.
The pch example in B2 distribution can be used as reference.
Please note the following:
The build properties used to compile the source files and the
precompiled header must be the same. Consider using project requirements
to assure this.
Precompiled headers must be used purely as a way to improve
compilation time, not to save the number of #include statements. If a
source file needs to include some header, explicitly include it in the
source file, even if the same header is included from the precompiled
header. This makes sure that your project will build even if precompiled
headers are not supported.
Prior to version 4.2, the gcc compiler did not allow anonymous
namespaces in precompiled headers, which limits their utility. See the
bug report for
details.
Previosuly B2 had not been automatically inluding the header, a user
was required to include the header at the top of every source file
the precompiled header will be used with.
5.8. Generated headers
Usually, B2 handles implicit dependencies completely
automatically. For example, for C++ files, all #include statements are
found and handled. The only aspect where user help might be needed is
implicit dependency on generated files.
By default, B2 handles such dependencies within one main
target. For example, assume that main target "app" has two sources,
"app.cpp" and "parser.y". The latter source is converted into "parser.c"
and "parser.h". Then, if "app.cpp" includes "parser.h", B2 will
detect this dependency. Moreover, since "parser.h" will be generated
into a build directory, the path to that directory will automatically be
added to the include path.
Making this mechanism work across main target boundaries is possible,
but imposes certain overhead. For that reason, if there is implicit
dependency on files from other main targets, the
feature must be used, for example:
The above example tells the build system that when scanning all sources
of "app" for implicit-dependencies, it should consider targets from
"parser" as potential dependencies.
5.9. Cross-compilation
B2 supports cross compilation with the gcc and msvc toolsets.
After that, if the host and target os are the same, for example Linux,
you can just request that this compiler version be used:
b2 toolset=gcc-arm
If you want to target a different operating system from the host, you
need to additionally specify the value for the target-os feature, for
example:
# On windows box
b2 toolset=gcc-arm target-os=linux
# On Linux box
b2 toolset=gcc-mingw target-os=windows
For the complete list of allowed operating system names, please see the
documentation for target-os
feature.
When using the msvc compiler, it’s only possible to cross-compile to a
64-bit system on a 32-bit host. Please see
the section called “64-bit support”
for details.
5.10. Package Managers
B2 support automatic, or manual, loading of generated build files
from package managers. For example using the Conan package manager which
generates conanbuildinfo.jam files B2 will load that files automatically
when it loads the project at the same location. The included file can
define targets and other project declarations in the context of the
project it’s being loaded into. Control over what package manager file
is loaded can be controlled with (in order of priority):
With the use-packages rule.
Command line argument --use-package-manager=X.
Environment variable PACKAGE_MANAGER_BUILD_INFO.
Built-in detection of the file. Currently this includes: "conan".
use-packages rule:
rule use-packages ( name-or-glob-pattern ? )
The use-packages rule allows one to specify in the projects themselves kind
of package definitions to use either as the ones for a built-in package
manager support. For example:
use-packages conan ;
Or to specify a glob pattern to find the file with the definitions. For
instance:
use-packages "packages.jam" ;
--use-package-manager command line option:
The --use-package-manager=NAME command line option allows one to
non-intrusively specify per invocation which of the built-in package manager
types to use.
PACKAGE_MANAGER_BUILD_INFO variable:
The PACKAGE_MANAGER_BUILD_INFO variable, which is taken from the environment
or defined with the -sX=Y option, specifies a glob pattern to use to find
the package definitions.
Built-in detection:
There are a number of built-in glob patterns to support popular package
managers. Currently the supported ones are:
Conan (conan): currently supports the
b2 generator.
6. Reference
6.1. General information
6.1.1. Initialization
Immediately upon starting, the B2 engine (b2) loads the Jam
code that implements the build system. To do this, it searches for a
file called boost-build.jam, first in the invocation directory, then
in its parent and so forth up to the filesystem root, and finally in the
directories specified by the environment variable BOOST_BUILD_PATH. On
Unix BOOST_BUILD_PATH defaults to /usr/share/boost-build. When
found, the file is interpreted, and should specify the build system
location by calling the boost-build rule:
rule boost-build ( location ? )
If location is a relative path, it is treated as relative to the
directory of boost-build.jam. The directory specified by that location
and the directories in BOOST_BUILD_PATH are then searched for a file
called bootstrap.jam, which is expected to bootstrap the build system.
This arrangement allows the build system to work without any
command-line or environment variable settings. For example, if the build
system files were located in a directory "build-system/" at your project
root, you might place a boost-build.jam at the project root
containing:
boost-build build-system ;
In this case, running b2 anywhere in the project tree will
automatically find the build system.
The default bootstrap.jam, after loading some standard definitions,
loads both site-config.jam and user-config.jam.
6.2. Builtin rules
This section contains the list of all rules that can be used in
Jamfile — both rules that define new targets and auxiliary rules.
The check-target-builds allows you to conditionally use different
properties depending on whether some metatarget builds, or not. This
is similar to functionality of configure script in autotools projects.
The function signature is:
This function can only be used when passing requirements or usage
requirements to a metatarget rule. For example, to make an application
link to a library if it’s available, one has use the following:
For another example, the alias rule can be used to consolidate
configuration choices and make them available to other metatargets,
like so:
alias foobar : : : : [ check-target-builds has_foo "System has foo" : foo : bar ] ;
obj
Creates an object file. Useful when a single source file must be
compiled with special properties.
preprocessed
Creates an preprocessed source file. The arguments follow the
common syntax.
glob
The glob rule takes a list shell pattern and returns the list of
files in the project’s source directory that match the pattern. For
example:
lib tools : [ glob *.cpp ] ;
It is possible to also pass a second argument—the list of exclude
patterns. The result will then include the list of files matching any
of include patterns, and not matching any of the exclude patterns. For
example:
The glob-tree is similar to the glob except that it operates
recursively from the directory of the containing Jamfile. For example:
ECHO [ glob-tree *.cpp : .svn ] ;
will print the names of all C++ files in your project. The .svn
exclude pattern prevents the glob-tree rule from entering
administrative directories of the Subversion version control system.
Assigns a symbolic project ID to a project at a given path. This rule
must be better documented!
explicit
The explicit rule takes a single parameter—a list of target names.
The named targets will be marked explicit, and will be built only if
they are explicitly requested on the command line, or if their
dependents are built. Compare this to ordinary targets, that are built
implicitly when their containing project is built.
always
The always function takes a single parameter—a list of metatarget
names. The targets produced by the named metatargets will be
always considered out of date. Consider this example:
If a build of hello is requested, then it will always be recompiled. Note that
if a build of hello is not requested, for example you specify just
bye on the command line, hello will not be recompiled.
constant
Sets project-wide constant. Takes two parameters: variable name and a
value and makes the specified variable name accessible in this Jamfile
and any child Jamfiles. For example:
constant VERSION : 1.34.0 ;
path-constant
Same as constant except that the value is treated as path relative
to Jamfile location. For example, if b2 is invoked in the current
directory, and Jamfile in helper subdirectory has:
path-constant DATA : data/a.txt ;
then the variable DATA will be set to helper/data/a.txt, and if
b2 is invoked from the helper directory, then the variable DATA
will be set to data/a.txt.
build-project
Cause some other project to be built. This rule takes a single
parameter—a directory name relative to the containing Jamfile. When
the containing Jamfile is built, the project located at that directory
will be built as well. At the moment, the parameter to this rule
should be a directory name. Project ID or general target references
are not allowed.
test-suite
This rule is deprecated and equivalent to alias.
6.3. Builtin features
This section documents the features that are built-in into B2.
For features with a fixed set of values, that set is provided, with the
default value listed first.
address-model
Allowed values:32, 64.
Specifies if 32-bit or 64-bit code should be generated by the compiler. Whether
this feature works depends on the used compiler, its version, how the compiler
is configured, and the values of the architectureinstruction-set features.
Please see the section C++ Compilers for details.
address-sanitizer
Allowed values:on, norecover.
Enables address sanitizer. Value norecover disables recovery for the
sanitizer. The feature is optional, thus no sanitizer is enabled by default.
allow
This feature is used to allow specific generators to run. For example, Qt tools
can only be invoked when Qt library is used. In that case, qt will be
in usage requirement of the library.
Specifies the general processor family to generate code for.
archiveflags
The value of this feature is passed without modification to the archiver tool
when creating static libraries.
asmflags
The value of this feature is passed without modification to the assembler.
asynch-exceptions
Allowed values:off, on.
Selects whether there is support for asynchronous EH (e.g. catching SEGVs).
build
Allowed values:no
Used to conditionally disable build of a target. If no is in
properties when building a target, build of that target is skipped. Combined
with conditional requirements this allows you to skip building some target in
configurations where the build is known to fail.
cflags; cxxflags; linkflags
The value of these features is passed without modification to the corresponding
tools. For cflags that is both the C and C++ compilers, for cxxflags that
is the C++ compiler, and for linkflags that is the linker. The features are
handy when you are trying to do something special that cannot be achieved by a
higher-level feature in B2.
conditional
Used to introduce indirect conditional requirements. The value should have the
form:
@rulename
where rulename should be a name of a rule with the following signature:
rule rulename ( properties * )
The rule will be called for each target with its properties and should return
any additional properties. See also section Requirements for an example.
coverage
Allowed values:off, on.
Enables code instrumentation to generate coverage data during execution.
Specifies the version of the C++ Standard Language to build with. All the
official versions of the standard since "98" are included. It is also possible
to specify using the experimental, work in progress, latest version. Some
compilers specified intermediate versions for the experimental versions leading
up to the released standard version. Those are included following the GNU
nomenclature as 0x, 1y, 1z, and 2a. Depending on the compiler latest
would map to one of those.
ℹ
This is an optional feature. Hence when not specified the compiler
default behaviour is used.
ℹ
Please consult the toolset specific documentation for which cxxstd
is supported.
cxxstd-dialect
Subfeature ofcxxstd
Allowed values: iso, gnu, ms.
Indicates if a non-standard dialect should be used. These usually have
either/or extensions or platform specific functionality. Not specifying the
dialect will default to 'iso' which will attempt to use ISO C++ Standard
conformance to the best of the compiler’s ability.
c++abi
Selects a specific variant of C++ ABI if the compiler supports several.
c++-template-depth
Allowed values: Any positive integer.
Allows configuring a C++ compiler with the maximal template instantiation
depth parameter. Specific toolsets may or may not provide support for this
feature depending on whether their compilers provide a corresponding
command-line option.
ℹ
Due to some internal details in the current B2 implementation it
is not possible to have features whose valid values are all positive integer.
As a workaround a large set of allowed values has been defined for this feature
and, if a different one is needed, user can easily add it by calling the
feature.extend rule.
debug-symbols
Allowed values:on, off.
Specifies if produced object files, executables, and libraries should include
debug information. Typically, the value of this feature is implicitly set by
the variant feature, but it can be explicitly specified by the user. The most
common usage is to build release variant with debugging information.
define
Specifies a preprocessor symbol that should be defined on the command line.
You may either specify just the symbol, which will be defined without any
value, or both the symbol and the value, separated by equal sign.
def-file
Provides a means to specify def-file for windows DLLs.
dependency
Introduces a dependency on the target named by the value of this feature (so it
will be brought up-to-date whenever the target being declared is). The
dependency is not used in any other way.
This feature is specific to the msvc toolset (see Microsoft Visual C++),
and controls whether the manifest files should be embedded inside executables
and shared libraries, or placed alongside them. This feature corresponds to the
IDE option found in the project settings dialog, under Configuration Properties
→ Manifest Tool → Input and Output → Embed manifest.
embed-manifest-file
This feature is specific to the msvc toolset (see Microsoft Visual C++),
and controls which manifest files should be embedded inside executables and
shared libraries. This feature corresponds to the IDE option found in the
project settings dialog, under Configuration Properties → Manifest Tool →
Input and Output → Additional Manifest Files.
embed-manifest-via
This feature is specific to the msvc toolset (see Microsoft Visual C++),
and controls whether a manifest should be embedded via linker or manifest tool.
exception-handling
Allowed values:on, off.
Disables exceptions.
extern-c-nothrow
Allowed values:off, on.
Selects whether all extern "C" functions are considered nothrow by default.
fflags
The value of this feature is passed without modification to the tool when
compiling Fortran sources.
file
When used in requirements of a prebuilt library target this feature specifies
the path to the library file. See Prebuilt targets for examples.
find-shared-library
Adds a shared library to link to. Usually lib
targets should be preferred over using this feature.
find-static-library
Adds a static library to link to. Usually lib
targets should be preferred over using this feature.
flags
This feature is used for generic, i.e. non-language specific, flags for tools.
The value of this feature is passed without modification to the tool that will
build the target.
hardcode-dll-paths
Allowed values:true, false.
Controls automatic generation of dll-path properties.
This property is specific to Unix systems. If an executable is built with
true, the generated binary will contain the list of all
the paths to the used shared libraries. As the result, the executable can be
run without changing system paths to shared libraries or installing the
libraries to system paths. This is very convenient during development. Please
see the FAQ entry for details. Note that on Mac OSX,
the paths are unconditionally hardcoded by the linker, and it is not possible
to disable that behavior
implicit-dependency
Indicates that the target named by the value of this feature may produce files
that are included by the sources of the target being declared. See the section
Generated headers for more information.
force-include
Specifies an include path that has to be included in a way like if
#include "file" appeared as the first line of every target’s source file.
The include order is not guaranteed if used multiple times on a single target.
include
Specifies an additional include path that is to be passed to C and C++
compilers.
inlining
Allowed values:off, on, full.
Enables inlining.
install-package
Specifies the name of the package to which installed files belong. This is
used for default installation prefix on certain platforms.
install-
Specifies installation prefix for install targets.
These named installation prefixes are registered by default:
prefix: C:\ if windows is in the property set,
/usr/local otherwise
Specifies for which specific instruction set the code should be generated. The
code in general might not run on processors with older/different instruction
sets.
While B2 allows a large set of possible values for this features,
whether a given value works depends on which compiler you use. Please see
the section C++ Compilers for details.
library
This feature is almost equivalent to the
feature, except that it takes
effect only for linking. When you want to link all targets in a Jamfile to
certain library, the feature is preferred over X — the
latter will add the library to all targets, even those that have nothing to do
with libraries.
library-path
Adds to the list of directories which will be used by the linker to search for
libraries.
leak-sanitizer
Allowed values:on, norecover.
Enables leak sanitizer. Value norecover disables recovery for the
sanitizer. The feature is optional, thus no sanitizer is enabled by default.
link
Allowed values:shared, static
Controls how libraries are built.
linkflags
See .
local-visibility
Allowed values:global, protected, hidden.
This feature has the same effect as the
visibility feature but is intended
to be used by targets that require a particular symbol visibility. Unlike the
visibility feature, local-visibility is not inherited by the target
dependencies and only affects the target to which it is applied.
The local-visibility feature supports the same values with the same meaning
as the visibility feature. By default, if local-visibility is not specified
for a target, the value of the visibility feature is used.
location
Specifies the build directory for a target. The feature is used primarily with
rule.
location-prefix
Sets the build directory for a target as the project’s build directory prefixed
with the value of this feature. See section Target Paths for an example.
mflags
The value of this feature is passed without modification to the tool when
compiling Objective C sources.
mmflags
The value of this feature is passed without modification to the tool when
compiling Objective C++ sources.
name
When used in requirements of a prebuilt library target this feature specifies
the name of the library (the name of the library file without any
platform-specific suffixes or prefixes). See Prebuilt targets for examples.
When used in requirements of an target it specifies the name of the
target file.
optimization
Allowed values:off, speed, space.
Enables optimization. speed optimizes for faster code, space optimizes for
smaller binary.
profiling
Allowed values:off, on.
Enables generation of extra code to write profile information.
relevant
Allowed values: the name of any feature.
Indicates which other features are relevant for a given target. It is usually
not necessary to manage it explicitly, as B2 can deduce it in most
cases. Features which are not relevant will not affect target paths, and will
not cause conflicts.
A feature will be considered relevant if any of the following are true
It is referenced by toolset.flags or toolset.uses-features
It is used by the requirements of a generator
It is a sub-feature of a relevant feature
It has a sub-feature which is relevant
It is a composite feature, and any composed feature is relevant
It affects target alternative selection for a main target
It is a propagated feature and is relevant for any dependency
It is relevant for any dependency created by the same main target
It is used in the condition of a conditional property and the corresponding
value is relevant
It is explicitly named as relevant
Relevant features cannot be automatically deduced in the following cases:
Indirect conditionals. Solution: return properties of the form
result-feature:condition-feature
ℹ
This isn’t really a conditional, although for most purposes it functions
like one. In particular, it does not support multiple comma-separated elements
in the condition, and it does work correctly even in contexts where conditional
properties are not allowed
Action rules that read properties. Solution: add toolset.uses-features to
tell B2 that the feature is actually used.
Generators and targets that manipulate property-sets directly. Solution:
set manually.
rtti
Allowed values:on, off.
Disables run-time type information.
runtime-debugging
Allowed values:on, off.
Specifies whether produced object files, executables, and libraries should
include behavior useful only for debugging, such as asserts. Typically, the
value of this feature is implicitly set by the variant feature, but it can be
explicitly specified by the user. The most common usage is to build release
variant with debugging output.
runtime-link
Allowed values:shared, static
Controls if a static or shared C/C++ runtime should be used. There are some
restrictions how this feature can be used, for example on some compilers an
application using static runtime should not use shared libraries at all, and on
some compilers, mixing static and shared runtime requires extreme care. Check
your compiler documentation for more details.
search
When used in requirements of a prebuilt library target this feature adds to the
list of directories to search for the library file. See Prebuilt targets
for examples.
source
The X property has the same effect on building a target as putting X
in the list of sources. It is useful when you want to add the same source to
all targets in the project (you can put in requirements) or to
conditionally include a source (using conditional requirements, see
the section Conditions and alternatives. See also the
feature.
staging-prefix
Specifies staging prefix for install targets.
If present, it will be used instead of the path to named directory prefix.
Example:
project : requirements x/y/z ;
install a1 : a : (bindir) ; # installs into x/y/z/bin
install a2 : a : (bindir) q ; # installs into q/bin
The feature is useful when you cannot (or don’t want to) put build artfiacts
into their intented locations during the build (such as when cross-compiling),
but still need to communicate those intended locations to the build system,
e.g. to generate configuration files.
Specifies C++ standard library to link to and in some cases the library ABI to
use:
native
Use compiler’s default.
gnu
Use GNU Standard Library (a.k.a. libstdc++) with the old ABI.
gnu11
Use GNU Standard Library with the new ABI.
libc++
Use LLVM libc++.
sun-stlport
Use the STLport implementation of the standard library
provided with the Solaris Studio compiler.
apache
Use the Apache stdcxx version 4 C++ standard library provided with
the Solaris Studio compiler.
strip
Allowed values:off, on.
Controls whether the binary should be stripped — that is have everything not
necessary to running removed.
ℹ
This feature will show up in target paths of everything, not just
binaries.
suppress-import-lib
Suppresses creation of import library by the linker.
tag
Used to customize the name of the generated files. The value should have the
form:
@rulename
where rulename should be a name of a rule with the following signature:
rule tag ( name : type ? : property-set )
The rule will be called for each target with the default name computed by
B2, the type of the target, and property set. The rule can either
return a string that must be used as the name of the target, or an empty
string, in which case the default name will be used.
Most typical use of the tag feature is to encode build properties, or library
version in library target names. You should take care to return non-empty
string from the tag rule only for types you care about — otherwise, you might
end up modifying names of object files, generated header file and other targets
for which changing names does not make sense.
Specifies the operating system for which the code is to be generated. The
compiler you used should be the compiler for that operating system. This option
causes B2 to use naming conventions suitable for that operating
system, and adjust build process accordingly. For example, with gcc, it
controls if import libraries are produced for shared libraries or not.
Controls if the project should be built in multi-threaded mode. This feature
does not necessary change code generation in the compiler, but it causes the
compiler to link to additional or different runtime libraries, and define
additional preprocessor symbols (for example, _MT on Windows and _REENTRANT
on Linux). How those symbols affect the compiled code depends on the code
itself.
thread-sanitizer
Allowed values:on, norecover.
Enables thread sanitizer. Value norecover disables recovery for the
sanitizer. The feature is optional, thus no sanitizer is enabled by default.
toolset
Allowed values: any of the toolset modules.
Selects the toolset that will be used to build binary targets. The full list of
toolset modules is in the Builtin tools section.
undef
Specifies a preprocessor symbol to undefine.
undefined-sanitizer
Allowed values:on, norecover.
Enables undefined behavior sanitizer. Value norecover disables recovery for
the sanitizer. The feature is optional, thus no sanitizer is enabled by
default.
use
Introduces a dependency on the target named by the value of this feature (so it
will be brought up-to-date whenever the target being declared is), and adds its
usage requirements to the build properties of the target being declared. The
dependency is not used in any other way. The primary use case is when you want
the usage requirements (such as #include paths) of some library to be
applied, but do not want to link to it.
user-interface
Allowed values:console, gui, wince, native, auto.
Specifies the environment for the executable which affects the entry point
symbol (or entry point function) that the linker will select. This feature is
Windows-specific.
console
console application.
gui
application does not require a console (it is supposed to create its
own windows.
wince
application is intended to run on a device that has a version of the
Windows CE kernel.
native
application runs without a subsystem environment.
auto
application runs in the POSIX subsystem in Windows.
variant
Allowed values:debug, release, profile.
A feature combining several low-level features, making it easy to
request common build configurations.
The value debug expands to
off on off on
The value release expands to
speed off full off
The value profile expands to the same as release, plus:
on on
Users can define their own build variants using the variant rule
from the common module.
ℹ
Runtime debugging is on in debug builds to suit the expectations of
people used to various IDEs.
vectorize
Allowed values:off, on, full.
Enables vectorization.
version
This feature isn’t used by any of the builtin tools, but can be used, for
example, to adjust target’s name via
feature.
visibility
Allowed values:global, protected, hidden.
Specifies the default symbol visibility in compiled binaries. Not all values
are supported on all platforms and on some platforms (for example, Windows)
symbol visibility is not supported at all.
The supported values have the following meaning:
global
a.k.a. "default" in gcc documentation. Global symbols are
considered public, they are exported from shared libraries and can be
redefined by another shared library or executable.
protected
a.k.a. "symbolic". Protected symbols are exported from shared
ibraries but cannot be redefined by another shared library or executable.
This mode is not supported on some platforms, for example OS X.
hidden
Hidden symbols are not exported from shared libraries and cannot
be redefined by a different shared library or executable loaded in a process.
In this mode, public symbols have to be explicitly marked in the source code
to be exported from shared libraries. This is the recommended mode.
By default compiler default visibility mode is used (no compiler flags are
added).
ℹ
In Boost super-project Jamroot file this property is set to the default
value of hidden. This means that Boost libraries are built with hidden
visibility by default, unless the user overrides it with a different
visibility or a library sets a different local-visibility (see below).
warnings
Allowed values:on, all, extra, pedantic, off.
Controls the warning level of compilers.
on
enable default/"reasonable" warning level.
all
enable most warnings.
extra
enable extra, possibly conflicting, warnings.
pedantic
enable likely inconsequential, and conflicting, warnings.
off
disable all warnings.
Default value is all.
warnings-as-errors
Allowed values:off, on.
Makes it possible to treat warnings as errors and abort compilation on a
warning.
translate-path
Used to introduce custom path feature translation. The value should have the
form:
@rulename
where rulename should be a name of a rule with the following signature:
The rule is called for each target with the feature of a path property,
the path property value, target properties, the target project ID, and
the target project location. It should return the translated path value.
Or return nothing if it doesn’t do path translation. Leaving it do the
default path translation.
lto
Allowed values:on.
Enables link time optimizations (also known as interprocedural optimizations or
whole-program optimizations). Currently supported toolsets are GNU C++,
clang and Microsoft Visual C++. The feature is optional.
lto-mode
Subfeature oflto
Allowed values:full, thin, fat.
Specifies the type of LTO to use.
full
Use the monolithic LTO: on linking all input is merged into a single
module.
thin
Use clang’s ThinLTO: each compiled file contains a summary of the
module, these summaries are merged into a single index. This allows to avoid
merging all modules together, which greatly reduces linking time.
fat
Produce gcc’s fat LTO objects: compiled files contain both the
intermidiate language suitable for LTO and object code suitable for regular
linking.
response-file
Allowed values:auto, file, contents.
Controls whether a response file is used, or not, during the build of the
applicable target. For file a response file is created and the filename
replaced in the action. For contents the contents (:E=) is replaced
in the action and no response file is created. For auto either a response
file is created, or the contents replaced, based on the length of the
contents such that if the contents fits within the limits of the command
execution line length limits the contents is replaced. Otherwise a
response file is created and the filename is replaced in the actions.
Supported for clang-linux and msvc toolsets.
6.4. Builtin tools
B2 comes with support for a large number of C++ compilers, and
other tools. This section documents how to use those tools.
Before using any tool, you must declare your intention, and possibly
specify additional information about the tool’s configuration. This is
done by calling the using rule, typically in your user-config.jam,
for example:
using gcc ;
additional parameters can be passed just like for other rules, for
example:
using gcc : 4.0 : g++-4.0 ;
The options that can be passed to each tool are documented in the
subsequent sections.
6.4.1. C++ Compilers
This section lists all B2 modules that support C++ compilers
and documents how each one can be initialized. The name of support
module for compiler is also the value for the toolset feature that can
be used to explicitly request that compiler.
HP aC++ compiler
The acc module supports the
HP
aC++ compiler for the HP-UX operating system.
The module is initialized using the following syntax:
using acc : [version] : [c++-compile-command] : [compiler options] ;
This statement may be repeated several times, if you want to configure
several versions of the compiler.
If the command is not specified, the aCC binary will be searched in
PATH.
The following options can be provided, using
`option-value syntax`:
cflags
Specifies additional compiler flags that will be used when compiling C
sources.
cxxflags
Specifies additional compiler flags that will be used when compiling C++
sources.
compileflags
Specifies additional compiler flags that will be used when compiling both C
and C++ sources.
linkflags
Specifies additional command line options that will be passed to the linker.
Borland C++ Compiler
The borland module supports the 32-bit command line C compilers
running on Microsoft Windows. This is the bcc32 executable for all
versions of Borland C and C Builder, as well as the command line
compatible compiler bcc32c on later versions of C Builder.
The module is initialized using the following syntax:
using borland : [version] : [c++-compile-command] : [compiler options] ;
This statement may be repeated several times, if you want to configure
several versions of the compiler.
If the command is not specified, Boost.Build will search for a binary
named bcc32 in PATH.
The following options can be provided, using
`option-value syntax`:
cflags
Specifies additional compiler flags that will be used when compiling C
sources.
cxxflags
Specifies additional compiler flags that will be used when compiling C++
sources.
compileflags
Specifies additional compiler flags that will be used when compiling both C
and C++ sources.
linkflags
Specifies additional command line options that will be passed to the linker.
user-interface
Specifies the user interface for applications. Valid choices are console
for a console applicatiuon and gui for a Windows application.
Comeau C/C++ Compiler
The como-linux and the como-win modules supports the
Comeau C/C++ Compiler on Linux and
Windows respectively.
The module is initialized using the following syntax:
using como : [version] : [c++-compile-command] : [compiler options] ;
This statement may be repeated several times, if you want to configure
several versions of the compiler.
If the command is not specified, B2 will search for a binary
named como in PATH.
The following options can be provided, using
`option-value syntax`:
cflags
Specifies additional compiler flags that will be used when compiling C
sources.
cxxflags
Specifies additional compiler flags that will be used when compiling C++
sources.
compileflags
Specifies additional compiler flags that will be used when compiling both C
and C++ sources.
linkflags
Specifies additional command line options that will be passed to the linker.
Before using the Windows version of the compiler, you need to setup
necessary environment variables per compiler’s documentation. In
particular, the COMO_XXX_INCLUDE variable should be set, where XXX
corresponds to the used backend C compiler.
Code Warrior
The cw module support CodeWarrior compiler, originally produced by
Metrowerks and presently developed by Freescale. B2 supports
only the versions of the compiler that target x86 processors. All such
versions were released by Metrowerks before acquisition and are not sold
any longer. The last version known to work is 9.4.
The module is initialized using the following syntax:
using cw : [version] : [c++-compile-command] : [compiler options] ;
This statement may be repeated several times, if you want to configure
several versions of the compiler.
If the command is not specified, B2 will search for a binary
named mwcc in default installation paths and in PATH.
The following options can be provided, using
`option-value syntax`:
cflags
Specifies additional compiler flags that will be used when compiling C
sources.
cxxflags
Specifies additional compiler flags that will be used when compiling C++
sources.
compileflags
Specifies additional compiler flags that will be used when compiling both C
and C++ sources.
linkflags
Specifies additional command line options that will be passed to the linker.
setup
The command that sets up environment variables prior to invoking the
compiler. If not specified, cwenv.bat alongside the compiler binary
will be used.
compiler
The command that compiles C and C++ sources. If not specified, mwcc
will be used. The command will be invoked after the setup script was
executed and adjusted the PATH variable.
linker
The command that links executables and dynamic libraries. If not
specified, mwld will be used. The command will be invoked after the
setup script was executed and adjusted the PATH variable.
The module is initialized using the following syntax:
using dmc : [version] : [c++-compile-command] : [compiler options] ;
This statement may be repeated several times, if you want to configure
several versions of the compiler.
If the command is not specified, B2 will search for a binary
named dmc in PATH.
The following options can be provided, using
`option-value syntax`:
cflags
Specifies additional compiler flags that will be used when compiling C
sources.
cxxflags
Specifies additional compiler flags that will be used when compiling C++
sources.
compileflags
Specifies additional compiler flags that will be used when compiling both C
and C++ sources.
linkflags
Specifies additional command line options that will be passed to the linker.
GNU C++
The gcc module supports the GNU C++ compiler on
Linux, a number of Unix-like system including SunOS and on Windows
(either Cygwin or MinGW).
The gcc module is initialized using the following syntax:
using gcc : [version] : [c++-compile-command] : [compiler options] ;
This statement may be repeated several times, if you want to configure
several versions of the compiler.
If the version is not explicitly specified, it will be automatically
detected by running the compiler with the -v option. If the command is
not specified, the g++ binary will be searched in PATH.
The following options can be provided, using
`option-value syntax`:
cflags
Specifies additional compiler flags that will be used when compiling C
sources.
cxxflags
Specifies additional compiler flags that will be used when compiling C++
sources.
compileflags
Specifies additional compiler flags that will be used when compiling both C
and C++ sources.
linkflags
Specifies additional command line options that will be passed to the linker.
root
Specifies root directory of the compiler installation. This option is
necessary only if it is not possible to detect this information from the
compiler command—for example if the specified compiler command is a user
script.
archiver
Specifies the archiver command that is used to produce static
libraries. Normally, it is autodetected using gcc -print-prog-name
option or defaulted to ar, but in some cases you might want to
override it, for example to explicitly use a system version instead of
one included with gcc.
ranlib
Specifies the ranlib command that is used to generated symbol table
for static libraries. Normally, it is autodetected using gcc
-print-prog-name option or defaulted to ranlib, but in some cases
you might want to override it, for example to explicitly use a system
version instead of one included with gcc.
rc
Specifies the resource compiler command that will be used with the
version of gcc that is being configured. This setting makes sense only
for Windows and only if you plan to use resource files. By default
windres will be used.
rc-type
Specifies the type of resource compiler. The value can be either
windres for msvc resource compiler, or rc for borland’s resource
compiler.
In order to compile 64-bit applications, you have to specify
address-model=64, and the instruction-set feature should refer to a 64
bit processor. Currently, those include nocona, opteron, athlon64 and
athlon-fx.
HP C++ Compiler for Tru64 Unix
The hp_cxx modules supports the
HP C++ Compiler
for Tru64 Unix.
The module is initialized using the following syntax:
using hp_cxx : [version] : [c++-compile-command] : [compiler options] ;
This statement may be repeated several times, if you want to configure
several versions of the compiler.
If the command is not specified, B2 will search for a binary
named hp_cxx in PATH.
The following options can be provided, using
`option-value syntax`:
cflags
Specifies additional compiler flags that will be used when compiling C
sources.
cxxflags
Specifies additional compiler flags that will be used when compiling C++
sources.
compileflags
Specifies additional compiler flags that will be used when compiling both C
and C++ sources.
linkflags
Specifies additional command line options that will be passed to the linker.
Intel C++
The intel-* modules support the Intel C++ command-line compiler.
The module is initialized using the following syntax:
using intel : [version] : [c++-compile-command] : [compiler options] ;
This statement may be repeated several times, if you want to configure
several versions of the compiler.
If compiler command is not specified, then B2 will look in PATH
for an executable icpc (on Linux), or icl.exe (on Windows).
The following options can be provided, using
`option-value syntax`:
cflags
Specifies additional compiler flags that will be used when compiling C
sources.
cxxflags
Specifies additional compiler flags that will be used when compiling C++
sources.
compileflags
Specifies additional compiler flags that will be used when compiling both C
and C++ sources.
linkflags
Specifies additional command line options that will be passed to the linker.
root
For the Linux version, specifies the root directory of the compiler installation.
This option is necessary only if it is not possible to detect this information
from the compiler command — for example if the specified compiler command is
a user script. For the Windows version, specifies the directory of the
iclvars.bat file, for versions prior to 21 ( or 2021 ), or of the setvars.bat,
for versions from 21 ( or 2021 ) on up, for configuring the compiler.
Specifying the root option without specifying the compiler command allows the
end-user not to have to worry about whether they are compiling 32-bit or 64-bit code,
as the toolset will automatically configure the compiler for the appropriate address
model and compiler command using the iclvars.bat or setvars.bat batch file.
Microsoft Visual C++
The msvc module supports the
Microsoft Visual C++ command-line
tools on Microsoft Windows. The supported products and versions of
command line tools are listed below:
Visual Studio 2019-14.2
Visual Studio 2017—14.1
Visual Studio 2015—14.0
Visual Studio 2013—12.0
Visual Studio 2012—11.0
Visual Studio 2010—10.0
Visual Studio 2008—9.0
Visual Studio 2005—8.0
Visual Studio .NET 2003—7.1
Visual Studio .NET—7.0
Visual Studio 6.0, Service Pack 5—6.5
The user would then call the boost build executable with the toolset set
equal to msvc-[version number] for example to build with Visual Studio
2019 one could run:
.\b2 toolset=msvc-14.2 target
The msvc module is initialized using the following syntax:
using msvc : [version] : [c++-compile-command] : [compiler options] ;
This statement may be repeated several times, if you want to configure
several versions of the compiler.
If the version is not explicitly specified, the most recent version
found in the registry will be used instead. If the special value all
is passed as the version, all versions found in the registry will be
configured. If a version is specified, but the command is not, the
compiler binary will be searched in standard installation paths for that
version, followed by PATH.
The compiler command should be specified using forward slashes, and
quoted.
The following options can be provided, using
`option-value syntax`:
cflags
Specifies additional compiler flags that will be used when compiling C
sources.
cxxflags
Specifies additional compiler flags that will be used when compiling C++
sources.
compileflags
Specifies additional compiler flags that will be used when compiling both C
and C++ sources.
linkflags
Specifies additional command line options that will be passed to the linker.
assembler
The command that compiles assembler sources. If not specified, ml
will be used. The command will be invoked after the setup script was
executed and adjusted the PATH variable.
compiler
The command that compiles C and C++ sources. If not specified, cl
will be used. The command will be invoked after the setup script was
executed and adjusted the PATH variable.
compiler-filter
Command through which to pipe the output of running the compiler. For
example to pass the output to STLfilt.
idl-compiler
The command that compiles Microsoft COM interface definition files. If
not specified, midl will be used. The command will be invoked after
the setup script was executed and adjusted the PATH variable.
linker
The command that links executables and dynamic libraries. If not
specified, link will be used. The command will be invoked after the
setup script was executed and adjusted the PATH variable.
mc-compiler
The command that compiles Microsoft message catalog files. If not
specified, mc will be used. The command will be invoked after the
setup script was executed and adjusted the PATH variable.
resource-compiler
The command that compiles resource files. If not specified, rc will
be used. The command will be invoked after the setup script was
executed and adjusted the PATH variable.
setup
The filename of the global environment setup script to run before
invoking any of the tools defined in this toolset. Will not be used in
case a target platform specific script has been explicitly specified
for the current target platform. Used setup script will be passed the
target platform identifier (x86, x86_amd64, x86_ia64, amd64 or ia64)
as a parameter. If not specified a default script is chosen based on
the used compiler binary, e.g. vcvars32.bat or vsvars32.bat.
setup-amd64; setup-i386; setup-ia64
The filename of the target platform specific environment setup script
to run before invoking any of the tools defined in this toolset. If
not specified the global environment setup script is used.
64-bit support
Starting with version 8.0, Microsoft Visual Studio can generate binaries
for 64-bit processor, both 64-bit flavours of x86 (codenamed
AMD64/EM64T), and Itanium (codenamed IA64). In addition, compilers that
are itself run in 64-bit mode, for better performance, are provided. The
complete list of compiler configurations are as follows (we abbreviate
AMD64/EM64T to just AMD64):
32-bit x86 host, 32-bit x86 target
32-bit x86 host, 64-bit AMD64 target
32-bit x86 host, 64-bit IA64 target
64-bit AMD64 host, 64-bit AMD64 target
64-bit IA64 host, 64-bit IA64 target
The 32-bit host compilers can be always used, even on 64-bit Windows. On
the contrary, 64-bit host compilers require both 64-bit host processor
and 64-bit Windows, but can be faster. By default, only 32-bit host,
32-bit target compiler is installed, and additional compilers need to be
installed explicitly.
To use 64-bit compilation you should:
Configure you compiler as usual. If you provide a path to the
compiler explicitly, provide the path to the 32-bit compiler. If you try
to specify the path to any of 64-bit compilers, configuration will not
work.
When compiling, use address-model=64, to generate AMD64 code.
To generate IA64 code, use architecture=ia64
The (AMD64 host, AMD64 target) compiler will be used automatically when
you are generating AMD64 code and are running 64-bit Windows on AMD64.
The (IA64 host, IA64 target) compiler will never be used, since nobody
has an IA64 machine to test.
It is believed that AMD64 and EM64T targets are essentially compatible.
The compiler options /favor:AMD64 and /favor:EM64T, which are
accepted only by AMD64 targeting compilers, cause the generated code to
be tuned to a specific flavor of 64-bit x86. B2 will make use
of those options depending on the value of the`instruction-set` feature.
Windows Runtime support
Starting with version 11.0, Microsoft Visual Studio can produce binaries
for Windows Store and Phone in addition to traditional Win32 desktop. To
specify which Windows API set to target, use the windows-api feature.
Available options are desktop, store, or phone. If not specified,
desktop will be used.
When using store or phone the specified toolset determines what
Windows version is targeted. The following options are available:
Windows 8.0: toolset=msvc-11.0 windows-api=store
Windows 8.1: toolset=msvc-12.0 windows-api=store
Windows Phone 8.0: toolset=msvc-11.0 windows-api=phone
Windows Phone 8.1: toolset=msvc-12.0 windows-api=phone
For example use the following to build for Windows Store 8.1 with the
ARM architecture:
Note that when targeting Windows Phone 8.1, version 12.0 didn’t include
the vcvars phone setup scripts. They can be separately downloaded from
here.
Sun Studio
The sun module supports the
Sun Studio C++ compilers
for the Solaris OS.
The module is initialized using the following syntax:
using sun : [version] : [c++-compile-command] : [compiler options] ;
This statement may be repeated several times, if you want to configure
several versions of the compiler.
If the command is not specified, B2 will search for a binary
named CC in /opt/SUNWspro/bin and in PATH.
When using this compiler on complex C code, such as the
http://boost.org[Boost C library], it is recommended to specify the
following options when initializing the sun module:
The following options can be provided, using
`option-value syntax`:
cflags
Specifies additional compiler flags that will be used when compiling C
sources.
cxxflags
Specifies additional compiler flags that will be used when compiling C++
sources.
compileflags
Specifies additional compiler flags that will be used when compiling both C
and C++ sources.
linkflags
Specifies additional command line options that will be passed to the linker.
Starting with Sun Studio 12, you can create 64-bit applications by using
the address-model=64 property.
IBM Visual Age
The vacpp module supports the IBM
Visual Age C++ Compiler, for the AIX operating system. Versions 7.1 and
8.0 are known to work.
The module is initialized using the following syntax:
using vacpp ;
The module does not accept any initialization options. The compiler
should be installed in the /usr/vacpp/bin directory.
Later versions of Visual Age are known as XL C/C++. They were not tested
with the the vacpp module.
6.4.2. Third-party libraries
B2 provides special support for some third-party C++ libraries,
documented below.
STLport library
The STLport library is an alternative implementation
of C++ runtime library. B2 supports using that library on
Windows platform. Linux is hampered by different naming of libraries in
each STLport version and is not officially supported.
Before using STLport, you need to configure it in user-config.jam
using the following syntax:
using stlport : version : header-path : library-path ;
Where version is the version of STLport, for example 5.1.4, headers is
the location where STLport headers can be found, and libraries is the
location where STLport libraries can be found. The version should always
be provided, and the library path should be provided if you’re using
STLport’s implementation of iostreams. Note that STLport 5.* always uses
its own iostream implementation, so the library path is required.
When STLport is configured, you can build with STLport by requesting
stdlib=stlport on the command line.
zlib
Provides support for the zlib library. zlib can be
configured either to use precompiled binaries or to build the library
from source.
zlib can be initialized using the following syntax
using zlib : version : options : condition : is-default ;
Options for using a prebuilt library:
search
The directory containing the zlib binaries.
name
Overrides the default library name.
include
The directory containing the zlib headers.
If none of these options is specified, then the environmental variables
ZLIB_LIBRARY_PATH, ZLIB_NAME, and ZLIB_INCLUDE will be used instead.
Options for building zlib from source:
source
The zlib source directory. Defaults to the environmental variable
ZLIB_SOURCE.
tag
Sets the tag property to adjust the
file name of the library. Ignored when using precompiled binaries.
build-name
The base name to use for the compiled library. Ignored when using
precompiled binaries.
Examples:
# Find zlib in the default system location
using zlib ;
# Build zlib from source
using zlib : 1.2.7 : /home/steven/zlib-1.2.7 ;
# Find zlib in /usr/local
using zlib : 1.2.7 : /usr/local/include /usr/local/lib ;
# Build zlib from source for msvc and find
# prebuilt binaries for gcc.
using zlib : 1.2.7 : C:/Devel/src/zlib-1.2.7 : msvc ;
using zlib : 1.2.7 : : gcc ;
bzip2
Provides support for the bzip2 library. bzip2 can
be configured either to use precompiled binaries or to build the library
from source.
bzip2 can be initialized using the following syntax
using bzip2 : version : options : condition : is-default ;
Options for using a prebuilt library:
search
The directory containing the bzip2 binaries.
name
Overrides the default library name.
include
The directory containing the bzip2 headers.
If none of these options is specified, then the environmental variables
BZIP2_LIBRARY_PATH, BZIP2_NAME, and BZIP2_INCLUDE will be used instead.
Options for building bzip2 from source:
source
The bzip2 source directory. Defaults to the environmental variable
BZIP2_SOURCE.
tag
Sets the tag property to adjust the
file name of the library. Ignored when using precompiled binaries.
build-name
The base name to use for the compiled library. Ignored when using
precompiled binaries.
Examples:
# Find bzip in the default system location
using bzip2 ;
# Build bzip from source
using bzip2 : 1.0.6 : /home/sergey/src/bzip2-1.0.6 ;
# Find bzip in /usr/local
using bzip2 : 1.0.6 : /usr/local/include /usr/local/lib ;
# Build bzip from source for msvc and find
# prebuilt binaries for gcc.
using bzip2 : 1.0.6 : C:/Devel/src/bzip2-1.0.6 : msvc ;
using bzip2 : 1.0.6 : : gcc ;
Python
Provides support for the python language
environment to be linked in as a library.
python can be initialized using the following syntax
The version of Python to use. Should be in Major.Minor format, for example
2.3. Do not include the sub-minor version.
command-or-prefix
Preferably, a command that invokes a Python interpreter. Alternatively, the
installation prefix for Python libraries and includes. If empty, will be
guessed from the version, the platform’s installation patterns, and the
python executables that can be found in PATH.
includes
the include path to Python headers. If empty, will be guessed.
libraries
the path to Python library binaries. If empty, will be guessed. On
MacOS/Darwin, you can also pass the path of the Python framework.
conditions
if specified, should be a set of properties that are matched against the
build configuration when B2 selects a Python configuration to use.
extension-suffix
A string to append to the name of extension modules before the true filename
extension. Ordinarily we would just compute this based on the value of the
feature. However ubuntu’s python-dbg package uses the
windows convention of appending _d to debug-build extension modules. We have
no way of detecting ubuntu, or of probing python for the "_d" requirement,
and if you configure and build python using --with-pydebug, you’ll be using
the standard *nix convention. Defaults to "" (or "_d" when targeting windows
and is set).
Examples:
# Find python in the default system location
using python ;
# 2.7
using python : 2.7 ;
# 3.5
using python : 3.5 ;
# On ubuntu 16.04
using python
: 2.7 # version
: # Interpreter/path to dir
: /usr/include/python2.7 # includes
: /usr/lib/x86_64-linux-gnu # libs
: # conditions
;
using python
: 3.5 # version
: # Interpreter/path to dir
: /usr/include/python3.5 # includes
: /usr/lib/x86_64-linux-gnu # libs
: # conditions
;
# On windows
using python
: 2.7 # version
: C:\\Python27-32\\python.exe # Interperter/path to dir
: C:\\Python27-32\\include # includes
: C:\\Python27-32\\libs # libs
: 32 # conditions - both 32 and unspecified
;
using python
: 2.7 # version
: C:\\Python27-64\\python.exe # Interperter/path to dir
: C:\\Python27-64\\include # includes
: C:\\Python27-64\\libs # libs
: 64 # conditions
;
6.4.3. Documentation tools
B2 support for the Boost documentation tools is documented
below.
xsltproc
To use xsltproc, you first need to configure it using the following
syntax:
using xsltproc : xsltproc ;
Where xsltproc is the xsltproc executable. If xsltproc is not specified,
and the variable XSLTPROC is set, the value of XSLTPROC will be used.
Otherwise, xsltproc will be searched for in PATH.
The following options can be provided, using
`option-value syntax`:
xsl:param
Values should have the form name=value
xsl:path
Sets an additional search path for xi:include elements.
catalog
A catalog file used to rewrite remote URL’s to a local copy.
The xsltproc module provides the following rules. Note that these
operate on jam targets and are intended to be used by another toolset,
such as boostbook, rather than directly by users.
Runs xsltproc to create multiple outputs in a directory. dirname is
unused, but exists for historical reasons. The output directory is
determined from the target.
boostbook
To use boostbook, you first need to configure it using the following
syntax:
using boostbook : docbook-xsl-dir : docbook-dtd-dir : boostbook-dir ;
docbook-xsl-dir is the DocBook XSL stylesheet directory. If not
provided, we use DOCBOOK_XSL_DIR from the environment (if available) or
look in standard locations. Otherwise, we let the XML processor load the
stylesheets remotely.
docbook-dtd-dir is the DocBook DTD directory. If not provided, we use
DOCBOOK_DTD_DIR From the environment (if available) or look in standard
locations. Otherwise, we let the XML processor load the DTD remotely.
boostbook-dir is the BoostBook directory with the DTD and XSL sub-dirs.
The boostbook module depends on xsltproc. For pdf or ps output, it also
depends on fop.
The following options can be provided, using
`option-value syntax`:
Creates a doxygen target. If the target name ends with .html, then
this will generate an html directory. Otherwise it will generate
BoostBook XML.
quickbook
The quickbook module provides a generator to convert from Quickbook to
BoostBook XML.
To use quickbook, you first need to configure it using the following
syntax:
using quickbook : command ;
command is the quickbook executable. If it is not specified, B2
will compile it from source. If it is unable to find the source it will
search for a quickbook executable in PATH.
fop
The fop module provides generators to convert from XSL formatting
objects to Postscript and PDF.
To use fop, you first need to configure it using the following syntax:
using fop : fop-command : java-home : java ;
fop-command is the command to run fop. If it is not specified,
B2 will search for it in PATH and FOP_HOME.
Either java-home or java can be used to specify where to find java.
6.5. Builtin modules
This section describes the modules that are provided by B2. The
import rule allows rules from one module to be used in another module or
Jamfile.
6.5.1. modules
The modules module defines basic functionality for handling modules.
A module defines a number of rules that can be used in other modules.
Modules can contain code at the top level to initialize the module. This
code is executed the first time the module is loaded.
ℹ
A Jamfile is a special kind of module which is managed by the build
system. Although they cannot be loaded directly by users, the other
features of modules are still useful for Jamfiles.
Each module has its own namespaces for variables and rules. If two
modules A and B both use a variable named X, each one gets its own copy
of X. They won’t interfere with each other in any way. Similarly,
importing rules into one module has no effect on any other module.
Every module has two special variables. $(file) contains the name
of the file that the module was loaded from and $(name) contains
the name of the module.
ℹ
$(file) does not contain the full path to the file. If you need
this, use modules.binding.
rule binding ( module-name )
Returns the filesystem binding of the given module.
For example, a module can get its own location with:
Call the given rule locally in the given module. Use this for rules
accepting rule names as arguments, so that the passed rule may be
invoked in the context of the rule’s caller (for example, if the rule
accesses module globals or is a local rule).
ℹ
rules called this way may accept at most 8 parameters.
Example:
rule filter ( f : values * )
{
local m = [ CALLER_MODULE ] ;
local result ;
for v in $(values)
{
if [ modules.call-in $(m) : $(f) $(v) ]
{
result += $(v) ;
}
}
return result ;
}
rule load ( module-name : filename ? : search * )
Load the indicated module if it is not already loaded.
module-name
Name of module to load.
filename
(partial) path to file; Defaults to $(module-name).jam
search
Directories in which to search for filename. Defaults to
$(BOOST_BUILD_PATH).
Load the indicated module and import rule names into the current module.
Any members of rules-opt will be available without qualification in
the caller’s module. Any members of rename-opt will be taken as the
names of the rules in the caller’s module, in place of the names they
have in the imported module. If rules-opt = '*', all rules from the
indicated module are imported into the caller’s module. If rename-opt
is supplied, it must have the same number of elements as rules-opt.
ℹ
The import rule is available without qualification in all modules.
Define exported copies in $(target-module) of all rules exported from
$(source-module). Also make them available in the global module with
qualification, so that it is just as though the rules were defined
originally in $(target-module).
6.5.2. path
Performs various path manipulations. Paths are always in a 'normalized'
representation. In it, a path may be either:
'.', or
['/'] [ ( '..' '/' )* (token '/')* token ]
In plain english, a path can be rooted, '..' elements are allowed only
at the beginning, and it never ends in slash, except for the path
consisting of slash only.
rule make ( native )
Converts the native path into normalized form.
rule native ( path )
Builds the native representation of the path.
rule is-rooted ( path )
Tests if a path is rooted.
rule has-parent ( path )
Tests if a path has a parent.
rule basename ( path )
Returns the path without any directory components.
rule parent ( path )
Returns the parent directory of the path. If no parent exists, an error
is issued.
rule reverse ( path )
Returns path2 such that [ join path path2 ] = ".". The path may not
contain ".." element or be rooted.
rule join ( elements + )
Concatenates the passed path elements. Generates an error if any element
other than the first one is rooted. Skips any empty or undefined path
elements.
rule root ( path root )
If path is relative, it is rooted at root. Otherwise, it is
unchanged.
Returns the list of files matching the given pattern in the specified
directory. Both directories and patterns are supplied as portable paths.
Each pattern should be a non-absolute path, and can’t contain "." or
".." elements. Each slash separated element of a pattern can contain the
following special characters:
'?' matches any character
'*' matches an arbitrary number of characters
A file $(d)/e1/e2/e3 (where 'd' is in $(dirs)) matches the pattern
p1/p2/p3 if and only if e1 matches p1, e2 matches p2 and so on. For
example:
Recursive version of glob.
Builds the glob of files while also searching in the subdirectories of
the given roots. An optional set of exclusion patterns will filter out
the matching entries from the result. The exclusions also apply to the
subdirectory scanning, such that directories that match the exclusion
patterns will not be searched.
rule exists ( file )
Returns true if the specified file exists.
rule all-parents ( path : upper_limit ? : cwd ? )
Find out the absolute name of path and return the list of all the
parents, starting with the immediate one. Parents are returned as
relative names. If upper_limit is specified, directories above it will
be pruned.
Search for patterns in parent directories of dir, up to and
including upper_limit, if it is specified, or till the filesystem root
otherwise.
rule relative ( child parent : no-error ? )
Assuming child is a subdirectory of parent, return the relative path
from parent to child.
rule relative-to ( path1 path2 )
Returns the minimal path to path2 that is relative path1.
rule programs-path ( )
Returns the list of paths which are used by the operating system for
looking up programs.
rule makedirs ( path )
Creates a directory and all parent directories that do not already
exist.
6.5.3. regex
Contains rules for string processing using regular expressions.
"x*" matches the pattern "x" zero or more times.
"x+" matches "x" one or more times.
"x?" matches "x" zero or one time.
"[abcd]" matches any of the characters, "a", "b", "c", and
"d". A character range such as "[a-z]" matches any character between
"a" and "z". "[^abc]" matches any character which is not "a",
"b", or "c".
"x|y" matches either pattern "x" or pattern "y"
(x) matches "x" and captures it.
"^" matches the beginning of the string.
"$" matches the end of the string.
"\<" matches the beginning of a word.
"\>" matches the end of a word.
rule split ( string separator )
Returns a list of the following substrings:
from beginning till the first occurrence of separator or till the
end,
between each occurrence of separator and the next occurrence,
from the last occurrence of separator till the end.
If no separator is present, the result will contain only one element.
rule split-list ( list * : separator )
Returns the concatenated results of applying
regex.split to every element
of the list using the separator pattern.
rule match ( pattern : string : indices * )
Match string against pattern, and return the elements indicated by
indices.
rule transform ( list * : pattern : indices * )
Matches all elements of list against the pattern and returns a list
of elements indicated by indices of all successful matches. If
indices is omitted returns a list of first parenthesized groups of all
successful matches.
rule escape ( string : symbols : escape-symbol )
Escapes all of the characters in symbols using the escape symbol
escape-symbol for the given string, and returns the escaped string.
rule replace ( string match replacement )
Replaces occurrences of a match string in a given string and returns the
new string. The match string can be a regex expression.
rule replace-list ( list * : match : replacement )
Replaces occurrences of a match string in a given list of strings and
returns a list of new strings. The match string can be a regex
expression.
Various useful list functions. Note that algorithms in this module
execute largely in the caller’s module namespace, so that local rules
can be used as function objects. Also note that most predicates can be
multi-element lists. In that case, all but the first element are
prepended to the first argument which is passed to the rule named by the
first element.
rule filter ( predicate + : sequence * )
Return the elements e of $(sequence) for which [ $(predicate) e ]
has a non-null value.
rule transform ( function + : sequence * )
Return a new sequence consisting of [ $(function) $(e) ] for each
element e of $(sequence).
rule reverse ( s * )
Returns the elements of s in reverse order.
rule insertion-sort ( s * : ordered * )
Insertion-sort s using the BinaryPredicate ordered.
rule merge ( s1 * : s2 * : ordered * )
Merge two ordered sequences using the BinaryPredicate ordered.
rule join ( s * : joint ? )
Join the elements of s into one long string. If joint is supplied,
it is used as a separator.
rule length ( s * )
Find the length of any sequence.
rule unique ( list * : stable ? )
Removes duplicates from list. If stable is passed, then the order of
the elements will be unchanged.
rule max-element ( elements + : ordered ? )
Returns the maximum number in elements. Uses ordered for comparisons
or numbers.less if none is provided.
rule select-highest-ranked ( elements * : ranks * )
Returns all of elements for which the corresponding element in the
parallel list rank is equal to the maximum value in rank.
6.5.5. stage
This module defines the install rule, used to copy a set of targets to a
single location.
For example, add-install-dir foo : bar : baz ; creates feature
and adds support for
named directory (foo) to install rule. The rule will try to use the value
of property if present, otherwise will fallback to (baz)/bar.
Arguments:
name: the name of the directory.
suffix: the path suffix appended to the parent named directory.
parent: the optional name of parent named directory.
options: special options that modify treatment of the directory.
Allowed options:
package-suffix: append the package name to the default value. For example:
add-install-dir foo : bar : baz : package-suffix ;
install (foo) : a : xyz ;
installs a into (baz)/bar/xyz.
rule install-dir-names ( )
Returns names of all registered installation directories.
Returns the path to a named installation directory. For a given name=xyz the
rule uses the value of property if it is present in
property-set. Otherwise it tries to construct the default value of the path
recursively getting the path to name's registered base named directory and
relative path. For example:
The argument package-name is used to construct the path for named directories
that were registered with package-suffix option and also to construct
install-prefix when targeting Windows.
Returns the package name that will be used for install targets when
constructing installation location. The rule uses the value of
property if it’s
present in property-set. Otherwise it deduces the package name using
project-module's attributes. It traverses the project hierarchy up to the
root searching for the first project with an id. If none is found, the base
name of the root project’s location is used. If project-module is empty, the
caller module is used (this allows invoking just [ get-package-name $(ps) ]
in project jam files).
6.5.6. type
Deals with target type declaration and defines target class which
supports typed targets.
rule register ( type : suffixes * : base-type ? )
Registers a target type, possible derived from a base-type. Providing
a list of suffixes here is a shortcut for separately calling the
register-suffixes
rule with the given suffixes and the
set-generated-target-suffix
rule with the first given suffix.
rule register-suffixes ( suffixes + : type )
Specifies that files with suffix from suffixes be recognized as
targets of type type. Issues an error if a different type is already
specified for any of the suffixes.
rule registered ( type )
Returns true iff type has been registered.
rule validate ( type )
Issues an error if type is unknown.
rule set-scanner ( type : scanner )
Sets a scanner class that will be used for this type.
rule get-scanner ( type : property-set )
Returns a scanner instance appropriate to type and property-set.
rule base ( type )
Returns a base type for the given type or nothing in case the given type
is not derived.
rule all-bases ( type )
Returns the given type and all of its base types in order of their
distance from type.
rule all-derived ( type )
Returns the given type and all of its derived types in order of their
distance from type.
rule is-derived ( type base )
Returns true if type is equal to base or has base as its direct or
indirect base.
rule set-generated-target-suffix ( type : properties * : suffix )
Sets a file suffix to be used when generating a target of type with
the specified properties. Can be called with no properties if no suffix
has already been specified for the type. The suffix parameter can be
an empty string ("") to indicate that no suffix should be used.
Note that this does not cause files with suffix to be automatically
recognized as being of type. Two different types can use the same
suffix for their generated files but only one type can be auto-detected
for a file with that suffix. User should explicitly specify which one
using the
register-suffixes
rule.
rule change-generated-target-suffix ( type : properties * : suffix )
Change the suffix previously registered for this type/properties
combination. If suffix is not yet specified, sets it.
rule generated-target-suffix ( type : property-set )
Returns the suffix used when generating a file of type with the given
properties.
rule set-generated-target-prefix ( type : properties * : prefix )
Sets a target prefix that should be used when generating targets of
type with the specified properties. Can be called with empty
properties if no prefix for type has been specified yet.
The prefix parameter can be empty string ("") to indicate that no
prefix should be used.
Usage example: library names use the "lib" prefix on unix.
rule change-generated-target-prefix ( type : properties * : prefix )
Change the prefix previously registered for this type/properties
combination. If prefix is not yet specified, sets it.
rule generated-target-prefix ( type : property-set )
Returns the prefix used when generating a file of type with the given
properties.
rule type ( filename )
Returns file type given its name. If there are several dots in filename,
tries each suffix. E.g. for name of "file.so.1.2" suffixes "2", "1", and
"so" will be tried.
Returns the location where the target was declared.
rule full-name ( )
Returns a user-readable name for this target.
rule generate ( property-set )
Generates virtual targets for this abstract target using the specified
properties, unless a different value of some feature is required by the
target. This is an abstract method which must be overridden by derived
classes.
On success, returns:
a property-set with the usage requirements to be applied to dependents
a list of produced virtual targets, which may be empty.
If property-set is empty, performs the default build of this target,
in a way specific to the derived class.
6.6.2. Class project-target
class project-target : abstract-target {
rule generate ( property-set )
rule build-dir ( )
rule main-target ( name )
rule has-main-target ( name )
rule find ( id : no-error ? )
# Methods inherited from abstract-target
rule name ( )
rule project ( )
rule location ( )
rule full-name ( )
}
This class has the following responsibilities:
Maintaining a list of main targets in this project and building them.
rule generate ( property-set )
Overrides
abstract-target.generate.
Generates virtual targets for all the targets contained in this project.
On success, returns:
a property-set with the usage requirements to be applied to dependents
a list of produced virtual targets, which may be empty.
rule build-dir ( )
Returns the root build directory of the project.
rule main-target ( name )
Returns a main-target class
instance corresponding to name. Can only be called after the project
has been fully loaded.
rule has-main-target ( name )
Returns whether a main-target
with the specified name exists. Can only be called after the project has
been fully loaded.
rule find ( id : no-error ? )
Find and return the target with the specified id, treated relative to
self. Id may specify either a target or a file name with the target
taking priority. May report an error or return nothing if the target is
not found depending on the no-error parameter.
A main-target represents a named
top-level target in a Jamfile.
rule generate ( property-set )
Overrides
abstract-target.generate.
Select an alternative for this main target, by finding all alternatives
whose requirements are satisfied by property-set and picking the one
with the longest requirements set. Returns the result of calling
generate on that
alternative.
On success, returns:
a property-set with the usage requirements to be applied to dependents
a list of produced virtual targets, which may be empty.
Implements the most standard way of constructing main target alternative
from sources. Allows sources to be either files or other main targets
and handles generation of those dependency targets.
Overrides
abstract-target.generate.
Determines final build properties, generates sources, and calls
construct. This
method should not be overridden.
On success, returns:
a property-set with the usage requirements to be applied to dependents
a list of produced virtual targets, which may be empty.
rule construct ( name : source-targets * : property-set )
Constructs virtual targets for this abstract target. Returns a
usage-requirements property-set and a list of virtual targets. Should be
overridden in derived classes.
6.6.5. Class typed-target
class typed-target : basic-target {
rule __init__ ( name : project : type : sources * : requirements * : default-build * : usage-requirements * )
rule type ( )
rule construct ( name : source-targets * : property-set )
# Methods inherited from abstract-target
rule name ( )
rule project ( )
rule location ( )
rule full-name ( )
# Methods inherited from basic-target
rule generate ( property-set )
}
typed-target is the most common
kind of target alternative. Rules for creating typed targets are defined
automatically for each type.
rule construct ( name : source-targets * : property-set )
Implements
basic-target.construct.
Attempts to create a target of the correct type using generators
appropriate for the given
property-set. Returns a
property-set containing the
usage requirements and a list of virtual targets.
ℹ
This function is invoked automatically by
basic-target.generate
and should not be called directly by users.
There is 1<→1 correspondence between identity and value. No two
instances of the class are equal. To maintain this property, the
'property-set.create' rule should be used to create new instances.
Instances are immutable.
rule raw ( )
Returns a Jam list of the stored properties.
rule str ( )
Returns the string representation of the stored properties.
Returns a new property-set
containing the union of the properties in this
property-set and in ps.
ℹ
If ps contains non-free properties that should override the values in
this object, use refine
instead.
rule add-raw ( properties * )
Link add, except that it
takes a list of properties instead of a
property-set.
rule refine ( ps )
Refines properties by overriding any non-free and non-conditional
properties for which a different value is specified in ps. Returns the
resulting property-set.
rule get ( feature )
Returns all the values of feature.
6.7. Build process
The general overview of the build process was given in the
user documentation. This section
provides additional details, and some specific rules.
To recap, building a target with specific properties includes the
following steps:
applying the default build,
selecting the main target alternative to use,
determining the "common" properties,
building targets referred by the the sources list and dependency
properties,
adding the usage requirements produced when building dependencies to
the "common" properties,
building the target using generators,
computing the usage requirements to be returned.
6.7.1. Alternative selection
When a target has several alternatives, one of them must be selected.
The process is as follows:
An alternative is viable only if all properties in its condition are
present in the build request.
If there’s only one viable alternative, it’s chosen. Otherwise, an
attempt is made to find the best alternative. An alternative a is better
than another alternative b, if the set of properties in b’s condition is
a strict subset of the set of properties of a’s condition. If one viable
alternative is better than all the others, it’s selected. Otherwise, an
error is reported.
6.7.2. Determining common properties
"Common" properties is a somewhat artificial term. This is the
intermediate property set from which both the build request for
dependencies and the properties for building the target are derived.
Since the default build and alternatives are already handled, we have
only two inputs: the build request and the requirements. Here are the
rules about common properties.
Non-free features can have only one value
A non-conditional property in the requirements is always present in
common properties.
A property in the build request is present in common properties,
unless it is overridden by a property in the requirements.
If either the build request, or the requirements (non-conditional or
conditional) include an expandable property (either composite, or with a
specified sub-feature value), the behavior is equivalent to explicitly
adding all the expanded properties to the build request or the
requirements respectively.
If the requirements include a
conditional property, and the
condition of this property is true in the context of common properties,
then the conditional property should be in common properties as well.
If no value for a feature is given by other rules here, it has
default value in common properties.
These rules are declarative. They don’t specify how to compute the
common properties. However, they provide enough information for the
user. The important point is the handling of conditional requirements.
The condition can be satisfied either by a property in the build
request, by non-conditional requirements, or even by another conditional
property. For example, the following example works as expected:
exe a : a.cpp
: gcc:release
release:FOO ;
6.7.3. Target Paths
Several factors determine the location of a concrete file target. All
files in a project are built under the directory bin unless this is
overridden by the build-dir project attribute. Under bin is a path that
depends on the properties used to build each target. This path is
uniquely determined by all non-free, non-incidental properties. For
example, given a property set containing: gcc4.6.1debugall_DEBUG/usr/local/includestatic, the path will be
gcc-4.6.1/debug/link-static. is an incidental feature and
and are free features, so they do not affect the path.
Sometimes the paths produced by B2 can become excessively long.
There are a couple of command line options that can help with this.
--abbreviate-paths reduces each element to no more than five characters.
For example, link-static becomes lnk-sttc. The --hash option reduces the
path to a single directory using an MD5 hash.
There are two features that affect the build directory. The
feature completely overrides the default build directory. For example,
exe a : a.cpp : . ;
builds all the files produced by a in the directory of the Jamfile.
This is generally discouraged, as it precludes variant builds.
The feature adds a prefix to the path, under the
project’s build directory. For example,
exe a : a.cpp : subdir ;
will create the files for a in bin/subdir/gcc-4.6.1/debug
6.8. Definitions
6.8.1. Features and properties
A feature is a normalized (toolset-independent) aspect of a build
configuration, such as whether inlining is enabled. Feature names may
not contain the ‘>’ character.
Each feature in a build configuration has one or more associated
values. Feature values for non-free features may not contain the
punctuation characters of pointy bracket (‘<’), colon (‘:’ ),
equal sign (‘=’) and dashes (‘-’). Feature values for free
features may not contain the pointy bracket (‘<’) character.
A property is a (feature,value) pair, expressed as value.
A subfeature is a feature that only exists in the presence of its
parent feature, and whose identity can be derived (in the context of its
parent) from its value. A subfeature’s parent can never be another
subfeature. Thus, features and their subfeatures form a two-level
hierarchy.
A value-string for a feature F is a string of the form
value-subvalue1-subvalue2…-subvalueN, where value is a legal
value for F and subvalue1…subvalueN are legal values of some of
F's subfeatures separated with dashes (‘-’).
For example, the properties gcc 3.0.1 can
be expressed more concisely using a value-string, as gcc-3.0.1.
A property set is a set of properties (i.e. a collection without
duplicates), for instance: gcc static.
A property path is a property set whose elements have been joined into
a single string separated by slashes. A property path representation of
the previous example would be gcc/static.
A build specification is a property set that fully describes the set
of features used to build a target.
6.8.2. Property Validity
For free features, all
values are valid. For all other features, the valid values are
explicitly specified, and the build system will report an error for the
use of an invalid feature-value. Subproperty validity may be restricted
so that certain values are valid only in the presence of certain other
subproperties. For example, it is possible to specify that the
mingw property is only valid in the presence of
2.95.2.
6.8.3. Feature Attributes
Each feature has a collection of zero or more of the following
attributes. Feature attributes are low-level descriptions of how the
build system should interpret a feature’s values when they appear in a
build request. We also refer to the attributes of properties, so that an
incidental property, for example, is one whose feature has the
incidental attribute.
incidental
Incidental features are assumed not to affect build products at all. As
a consequence, the build system may use the same file for targets whose
build specification differs only in incidental features. A feature that
controls a compiler’s warning level is one example of a likely
incidental feature.
Non-incidental features are assumed to affect build products, so the
files for targets whose build specification differs in non-incidental
features are placed in different directories as described in
Target Paths.
propagated
Features of this kind are propagated to dependencies. That is, if a
main target is built using a
propagated property, the build systems attempts to use the same property
when building any of its dependencies as part of that main target. For
instance, when an optimized executable is requested, one usually wants
it to be linked with optimized libraries. Thus, the
feature is propagated.
free
Most features have a finite set of allowed values, and can only take on
a single value from that set in a given build specification. Free
features, on the other hand, can have several values at a time and each
value can be an arbitrary string. For example, it is possible to have
several preprocessor symbols defined simultaneously:
NDEBUG=1 HAS_CONFIG_H=1
optional
An optional feature is a feature that is not required to appear in a
build specification. Every non-optional non-free feature has a default
value that is used when a value for the feature is not otherwise
specified, either in a target’s requirements or in the user’s build
request. [A feature’s default value is given by the first value listed
in the feature’s declaration. — move this elsewhere - dwa]
symmetric
Normally a feature only generates a sub-variant directory when its value
differs from its default value, leading to an asymmetric sub-variant
directory structure for certain values of the feature. A symmetric
feature always generates a corresponding sub-variant directory.
path
The value of a path feature specifies a path. The path is treated as
relative to the directory of Jamfile where path feature is used and is
translated appropriately by the build system when the build is invoked
from a different directory
implicit
Values of implicit features alone identify the feature. For example, a
user is not required to write "gcc", but can simply write
"gcc". Implicit feature names also don’t appear in variant paths,
although the values do. Thus: bin/gcc/… as opposed to
bin/toolset-gcc/…. There should typically be only a few such features,
to avoid possible name clashes.
composite
Composite features actually correspond to groups of properties. For
example, a build variant is a composite feature. When generating targets
from a set of build properties, composite features are recursively
expanded and added to the build property set, so rules can find them
if necessary. Non-composite non-free features override components of
composite features in a build property set.
dependency
The value of a dependency feature is a target reference. When used for
building of a main target, the value of dependency feature is treated as
additional dependency.
For example, dependency features allow to state that library A depends
on library B. As the result, whenever an application will link to A, it
will also link to B. Specifying B as dependency of A is different from
adding B to the sources of A.
Features that are neither free nor incidental are called base
features.
6.8.4. Feature Declaration
The low-level feature declaration interface is the feature rule from
the feature module:
A feature’s allowed-values may be extended with the feature.extend
rule.
6.8.5. Property refinement
When a target with certain properties is requested, and that target
requires some set of properties, it is needed to find the set of
properties to use for building. This process is called property
refinement and is performed by these rules
Each property in the required set is added to the original property
set
If the original property set includes property with a different
value of non free feature, that property is removed.
6.8.6. Conditional properties
Sometime it’s desirable to apply certain requirements only for a
specific combination of other properties. For example, one of compilers
that you use issues a pointless warning that you want to suppress by
passing a command line option to it. You would not want to pass that
option to other compilers. Conditional properties allow you to do just
that. Their syntax is:
property ( "," property ) * ":" property
For example, the problem above would be solved by:
would cause the version of cmdline library, optimized for space, to be
linked in even if the compiler executable is build with optimization
for speed.
7. Utilities
7.1. Debugger
7.1.1. Overview
B2 comes with a debugger for Jamfiles. To run the debugger,
start B2 with b2 -dconsole.
$ b2 -dconsole
(b2db) break gcc.init
Breakpoint 1 set at gcc.init
(b2db) run
Starting program: /usr/bin/b2
Breakpoint 1, gcc.init ( ) at /usr/share/boost-build/tools/gcc.jam:74
74 local tool-command = ;
(b2db) quit
7.1.2. Running the Program
The run command is used to start a new b2 subprocess for debugging.
The arguments to run are passed on the command line. If a child
process is already running, it will be terminated before the new child
is launched.
When the program is paused continue will resume execution. The step
command will advance the program by a single statement, stopping on
entry to another function or return from the current function. next is
like step except that it skips over function calls. finish executes
until the current function returns.
The kill command terminates the current child immediately.
7.1.3. Breakpoints
Breakpoints are set using the break command. The location of the
breakpoint can be specified as either the name of a function (including
the module name) or or a file name and line number of the form
file:line. When a breakpoint is created it is given a unique id which
is used to identify it for other commands.
(b2db) break Jamfile:10
Breakpoint 1 set at Jamfile:10
(b2db) break msvc.init
Breakpoint 2 set at msvc.init
A breakpoint can be temporarily disabled using the disable command.
While a breakpoint is disabled, the child will not stop when it is hit.
A disabled breakpoint can be activated again with enable.
(b2db) disable 1
(b2db) enable 1
Breakpoints can be removed permanently with delete or clear. The
difference between them is that delete takes the breakpoint id while
clear takes the location of the breakpoint as originally specified to
break.
quit exits the debugger. help describes the available commands.
8. Extender Manual
8.1. Introduction
This section explains how to extend B2 to accommodate your local
requirements — primarily to add support for non-standard tools you
have. Before we start, be sure you have read and understood the concept
of metatarget, Concepts, which is critical to
understanding the remaining material.
The current version of B2 has three levels of targets, listed
below.
metatarget
Object that is created from declarations in Jamfiles. May be called
with a set of properties to produce concrete targets.
concrete target
Object that corresponds to a file or an action.
jam target
Low-level concrete target that is specific to Boost.Jam build engine.
Essentially a string — most often a name of file.
In most cases, you will only have to deal with concrete targets and the
process that creates concrete targets from metatargets. Extending
metatarget level is rarely required. The jam targets are typically only
used inside the command line patterns.
⚠
All of the Boost.Jam target-related builtin functions, like
DEPENDS or ALWAYS operate on jam targets. Applying them to metatargets or
concrete targets has no effect.
8.1.1. Metatargets
Metatarget is an object that records information specified in Jamfile,
such as metatarget kind, name, sources and properties, and can be called
with specific properties to generate concrete targets. At the code level
it is represented by an instance of class derived from
abstract-target.
[4]
The generate method
takes the build properties (as an instance of the
property-set class) and returns
a list containing:
As front element — Usage-requirements from this invocation (an
instance of property-set)
As subsequent elements — created concrete targets ( instances of the
virtual-target class.)
It’s possible to lookup a metatarget by target-id using the
targets.resolve-reference function, and the
targets.generate-from-reference function can both lookup and generate
a metatarget.
The abstract-target class
has three immediate derived classes:
project-target that
corresponds to a project and is not intended for further subclassing.
The generate method
of this class builds all targets in the project that are not marked as
explicit.
main-target corresponds to a
target in a project and contains one or more target alternatives. This
class also should not be subclassed. The
generate method of this
class selects an alternative to build, and calls the
generate method of
that alternative.
basic-target corresponds to a
specific target alternative. This is base class, with a number of
derived classes. The
generate method
processes the target requirements and requested build properties to
determine final properties for the target, builds all sources, and
finally calls the abstract
construct method with
the list of source virtual targets, and the final properties.
The instances of the
project-target and
main-target classes are created
implicitly — when loading a new Jamfiles, or when a new target
alternative with as-yet unknown name is created. The instances of the
classes derived from
basic-target are typically
created when Jamfile calls a metatarget rule, such as such as exe.
It it permissible to create a custom class derived from
basic-target and create new
metatarget rule that creates instance of such target. However, in the
majority of cases, a specific subclass of
basic-target — typed-target is used. That
class is associated with a type and relays to generators to construct
concrete targets of that type. This process will be explained below.
When a new type is declared, a new metatarget rule is automatically
defined. That rule creates new instance of type-target, associated with
that type.
8.1.2. Concrete targets
Concrete targets are represented by instance of classes derived from
virtual-target. The most commonly used subclass is file-target. A
file target is associated with an action that creates it — an
instance of the action class. The action, in turn, hold a list of
source targets. It also holds the
property-set instance with the
build properties that should be used for the action.
Here’s an example of creating a target from another target, source
local a = [ new action $(source) : common.copy : $(property-set) ] ;
local t = [ new file-target $(name) : CPP : $(project) : $(a) ] ;
The first line creates an instance of the action class. The first
parameter is the list of sources. The second parameter is the name a
jam-level action. The third
parameter is the property-set applying to this action. The second line
creates a target. We specify a name, a type and a project. We also pass
the action object created earlier. If the action creates several
targets, we can repeat the second line several times.
In some cases, code that creates concrete targets may be invoked more
than once with the same properties. Returning two different instances of
file-target that correspond to the same file clearly will result in
problems. Therefore, whenever returning targets you should pass them via
the virtual-target.register function, besides allowing B2 to
track which virtual targets got created for each metatarget, this will
also replace targets with previously created identical ones, as
necessary.[5] Here are a couple of examples:
In theory, every kind of metatarget in B2 (like exe, lib or
obj) could be implemented by writing a new metatarget class that,
independently of the other code, figures what files to produce and what
commands to use. However, that would be rather inflexible. For example,
adding support for a new compiler would require editing several
metatargets.
In practice, most files have specific types, and most tools consume and
produce files of specific type. To take advantage of this fact,
B2 defines concept of target type and generators generators,
and has special metatarget class
typed-target. Target type is
merely an identifier. It is associated with a set of file extensions
that correspond to that type. Generator is an abstraction of a tool. It
advertises the types it produces and, if called with a set of input
target, tries to construct output targets of the advertised types.
Finally, typed-target is
associated with specific target type, and relays the generator (or
generators) for that type.
A generator is an instance of a class derived from generator. The
generator class itself is suitable for common cases. You can define
derived classes for custom scenarios.
8.2. Example: 1-to-1 generator
Say you’re writing an application that generates C++ code. If you ever
did this, you know that it’s not nice. Embedding large portions of C++
code in string literals is very awkward. A much better solution is:
Write the template of the code to be generated, leaving placeholders
at the points that will change
Access the template in your application and replace placeholders
with appropriate text.
Write the result.
It’s quite easy to achieve. You write special verbatim files that are
just C++, except that the very first line of the file contains the name
of a variable that should be generated. A simple tool is created that
takes a verbatim file and creates a cpp file with a single char*
variable whose name is taken from the first line of the verbatim file
and whose value is the file’s properly quoted content.
Let’s see what B2 can do.
First off, B2 has no idea about "verbatim files". So, you must
register a new target type. The following code does it:
import type ;
type.register VERBATIM : verbatim ;
The first parameter to
type.register gives the name
of the declared type. By convention, it’s uppercase. The second
parameter is the suffix for files of this type. So, if B2 sees
code.verbatim in a list of sources, it knows that it’s of type
VERBATIM.
Next, you tell B2 that the verbatim files can be transformed
into C++ files in one build step. A generator is a template for a build
step that transforms targets of one type (or set of types) into another.
Our generator will be called verbatim.inline-file; it transforms
VERBATIM files into CPP files:
Now, we’re ready to tie it all together. Put all the code above in file
verbatim.jam, add import verbatim ; to Jamroot.jam, and it’s
possible to write the following in your Jamfile:
The listed verbatim files will be automatically converted into C++
source files, compiled and then linked to the codegen executable.
In subsequent sections, we will extend this example, and review all the
mechanisms in detail. The complete code is available in the
example/customization directory.
8.3. Target types
The first thing we did in the introduction
was declaring a new target type:
import type ;
type.register VERBATIM : verbatim ;
The type is the most important property of a target. B2 can
automatically generate necessary build actions only because you specify
the desired type (using the different main target rules), and because
B2 can guess the type of sources from their extensions.
The first two parameters for the type.register rule are the name of
new type and the list of extensions associated with it. A file with an
extension from the list will have the given target type. In the case
where a target of the declared type is generated from other sources, the
first specified extension will be used.
Sometimes you want to change the suffix used for generated targets
depending on build properties, such as toolset. For example, some
compiler uses extension elf for executable files. You can use the
type.set-generated-target-suffix rule:
A new target type can be inherited from an existing one.
type.register PLUGIN : : SHARED_LIB ;
The above code defines a new type derived from SHARED_LIB. Initially,
the new type inherits all the properties of the base type - in
particular generators and suffix. Typically, you’ll change the new type
in some way. For example, using type.set-generated-target-suffix you
can set the suffix for the new type. Or you can write a special
generator for the new type. For example, it can generate additional
meta-information for the plugin. In either way, the PLUGIN type can be
used whenever SHARED_LIB can. For example, you can directly link
plugins to an application.
A type can be defined as "main", in which case B2 will
automatically declare a main target rule for building targets of that
type. More details can be found
later.
8.4. Scanners
Sometimes, a file can refer to other files via some include system. To
make B2 track dependencies between included files, you need to
provide a scanner. The primary limitation is that only one scanner can
be assigned to a target type.
First, we need to declare a new class for the scanner:
All the complex logic is in the common-scanner class, and you only
need to override the method that returns the regular expression to be
used for scanning. The parentheses in the regular expression indicate
which part of the string is the name of the included file. Only the
first parenthesized group in the regular expression will be recognized;
if you can’t express everything you want that way, you can return
multiple regular expressions, each of which contains a parenthesized
group to be matched.
After that, we need to register our scanner class:
scanner.register verbatim-scanner : include ;
The value of the second parameter, in this case include, specifies the
properties that contain the list of paths that should be searched for
the included files.
Finally, we assign the new scanner to the VERBATIM target type:
type.set-scanner VERBATIM : verbatim-scanner ;
That’s enough for scanning include dependencies.
8.5. Tools and generators
This section will describe how B2 can be extended to support
new tools.
For each additional tool, a B2 object called generator must be
created. That object has specific types of targets that it accepts and
produces. Using that information, B2 is able to automatically
invoke the generator. For example, if you declare a generator that takes
a target of the type D and produces a target of the type OBJ, when
placing a file with extension .d in a list of sources will cause
B2 to invoke your generator, and then to link the resulting
object file into an application. (Of course, this requires that you
specify that the .d extension corresponds to the D type.)
Each generator should be an instance of a class derived from the
generator class. In the simplest case, you don’t need to create a
derived class, but simply create an instance of the generator class.
Let’s review the example we’ve seen in the
introduction.
We declare a standard generator, specifying its id, the source type and
the target type. When invoked, the generator will create a target of
type CPP with a source target of type VERBATIM as the only source.
But what command will be used to actually generate the file? In
B2, actions are specified using named "actions" blocks and the
name of the action block should be specified when creating targets. By
convention, generators use the same name of the action block as their
own id. So, in above example, the "inline-file" actions block will be
used to convert the source into the target.
There are two primary kinds of generators: standard and composing, which
are registered with the generators.register-standard and the
generators.register-composing rules, respectively. For example:
The first (standard) generator takes a single source of type
VERBATIM and produces a result. The second (composing) generator takes
any number of sources, which can have either the CPP or the LIB
type. Composing generators are typically used for generating top-level
target type. For example, the first generator invoked when building an
exe target is a composing generator corresponding to the proper
linker.
You should also know about two specific functions for registering
generators: generators.register-c-compiler and
generators.register-linker. The first sets up header dependency
scanning for C files, and the seconds handles various complexities like
searched libraries. For that reason, you should always use those
functions when adding support for compilers and linkers.
(Need a note about UNIX)
Custom generator classes
The standard generators allows you to specify source and target types,
an action, and a set of flags. If you need anything more complex, you
need to create a new generator class with your own logic. Then, you have
to create an instance of that class and register it. Here’s an example
how you can create your own generator class:
This generator will work exactly like the verbatim.inline-file
generator we’ve defined above, but it’s possible to customize the
behavior by overriding methods of the generator class.
There are two methods of interest. The run method is responsible for
the overall process - it takes a number of source targets, converts them
to the right types, and creates the result. The generated-targets
method is called when all sources are converted to the right types to
actually create the result.
The generated-targets method can be overridden when you want to add
additional properties to the generated targets or use additional
sources. For a real-life example, suppose you have a program analysis
tool that should be given a name of executable and the list of all
sources. Naturally, you don’t want to list all source files manually.
Here’s how the generated-targets method can find the list of sources
automatically:
class itrace-generator : generator {
...
rule generated-targets ( sources + : property-set : project name ? )
{
local leaves ;
local temp = [ virtual-target.traverse $(sources[1]) : : include-sources ] ;
for local t in $(temp)
{
if ! [ $(t).action ]
{
leaves += $(t) ;
}
}
return [ generator.generated-targets $(sources) $(leafs)
: $(property-set) : $(project) $(name) ] ;
}
}
generators.register [ new itrace-generator nm.itrace : EXE : ITRACE ] ;
The generated-targets method will be called with a single source
target of type EXE. The call to virtual-target.traverse will return
all targets the executable depends on, and we further find files that
are not produced from anything. The found targets are added to the
sources.
The run method can be overridden to completely customize the way the
generator works. In particular, the conversion of sources to the desired
types can be completely customized. Here’s another real example. Tests
for the Boost Python library usually consist of two parts: a Python
program and a C++ file. The C++ file is compiled to Python extension
that is loaded by the Python program. But in the likely case that both
files have the same name, the created Python extension must be renamed.
Otherwise, the Python program will import itself, not the extension.
Here’s how it can be done:
rule run ( project name ? : property-set : sources * )
{
local python ;
for local s in $(sources)
{
if [ $(s).type ] = PY
{
python = $(s) ;
}
}
local libs ;
for local s in $(sources)
{
if [ type.is-derived [ $(s).type ] LIB ]
{
libs += $(s) ;
}
}
local new-sources ;
for local s in $(sources)
{
if [ type.is-derived [ $(s).type ] CPP ]
{
local name = [ $(s).name ] ; # get the target's basename
if $(name) = [ $(python).name ]
{
name = $(name)_ext ; # rename the target
}
new-sources += [ generators.construct $(project) $(name) :
PYTHON_EXTENSION : $(property-set) : $(s) $(libs) ] ;
}
}
result = [ construct-result $(python) $(new-sources) : $(project) $(name)
: $(property-set) ] ;
}
First, we separate all source into python files, libraries and C++
sources. For each C++ source we create a separate Python extension by
calling generators.construct and passing the C++ source and the
libraries. At this point, we also change the extension’s name, if
necessary.
8.6. Features
Often, we need to control the options passed the invoked tools. This is
done with features. Consider an example:
# Declare a new free feature
import feature : feature ;
feature verbatim-options : : free ;
# Cause the value of the 'verbatim-options' feature to be
# available as 'OPTIONS' variable inside verbatim.inline-file
import toolset : flags ;
flags verbatim.inline-file OPTIONS ;
# Use the "OPTIONS" variable
actions inline-file
{
"./inline-file.py" $(OPTIONS) $(<) $(>)
}
We first define a new feature. Then, the flags invocation says that
whenever verbatim.inline-file action is run, the value of the
verbatim-options feature will be added to the OPTIONS variable, and
can be used inside the action body. You’d need to consult online help
(--help) to find all the features of the toolset.flags rule.
Although you can define any set of features and interpret their values
in any way, B2 suggests the following coding standard for
designing features.
Most features should have a fixed set of values that is portable (tool
neutral) across the class of tools they are designed to work with. The
user does not have to adjust the values for a exact tool. For example,
speed has the same meaning for all C++ compilers and the
user does not have to worry about the exact options passed to the
compiler’s command line.
Besides such portable features there are special 'raw' features that
allow the user to pass any value to the command line parameters for a
particular tool, if so desired. For example, the feature
allows you to pass any command line options to a C++ compiler. The
feature allows you to pass any string preceded by -I and
the interpretation is tool-specific. (See Can I get capture external program output using a Boost.Jam variable?
for an example of very smart usage of that feature). Of course one
should always strive to use portable features, but these are still be
provided as a backdoor just to make sure B2 does not take away
any control from the user.
Using portable features is a good idea because:
When a portable feature is given a fixed set of values, you can build
your project with two different settings of the feature and B2
will automatically use two different directories for generated files.
B2 does not try to separate targets built with different raw
options.
Unlike with “raw” features, you don’t need to use specific
command-line flags in your Jamfile, and it will be more likely to work
with other tools.
Steps for adding a feature
Adding a feature requires three steps:
Declaring a feature. For that, the "feature.feature" rule is used.
You have to decide on the set of
feature attributes:
if you want a feature value set for one target to automatically
propagate to its dependent targets then make it “propagated”.
if a feature does not have a fixed list of values, it must be “free.”
For example, the include feature is a free feature.
if a feature is used to refer to a path relative to the Jamfile, it
must be a “path” feature. Such features will also get their values
automatically converted to B2’s internal path representation.
For example, include is a path feature.
if feature is used to refer to some target, it must be a “dependency”
feature.
Representing the feature value in a target-specific variable. Build
actions are command templates modified by Boost.Jam variable expansions.
The toolset.flags rule sets a target-specific variable to the value of
a feature.
Using the variable. The variable set in step 2 can be used in a
build action to form command parameters or files.
Another example
Here’s another example. Let’s see how we can make a feature that refers
to a target. For example, when linking dynamic libraries on Windows, one
sometimes needs to specify a "DEF file", telling what functions should
be exported. It would be nice to use this file like this:
lib a : a.cpp : a.def ;
Actually, this feature is already supported, but anyway…
Since the feature refers to a target, it must be "dependency".
feature def-file : : free dependency ;
One of the toolsets that cares about DEF files is msvc. The
following line should be added to it.
flags msvc.link DEF_FILE ;
Since the DEF_FILE variable is not used by the msvc.link action, we
need to modify it to be:
actions link bind DEF_FILE
{
$(.LD) .... /DEF:$(DEF_FILE) ....
}
Note the bind DEF_FILE part. It tells B2 to translate the
internal target name in DEF_FILE to a corresponding filename in the
link action. Without it the expansion of $(DEF_FILE) would be a
strange symbol that is not likely to make sense for the linker.
We are almost done, except for adding the following code to msvc.jam:
rule link
{
DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ;
}
This is a workaround for a bug in B2 engine, which will
hopefully be fixed one day.
Variants and composite features.
Sometimes you want to create a shortcut for some set of features. For
example, release is a value of and is a shortcut for a set
of features.
It is possible to define your own build variants. For example:
variant crazy : speed off
on on ;
will define a new variant with the specified set of properties. You can
also extend an existing variant:
variant super_release : release : USE_ASM ;
In this case, super_release will expand to all properties specified by
release, and the additional one you’ve specified.
You are not restricted to using the variant feature only. Here’s
example that defines a brand new feature:
This will allow you to specify the value of feature parallelism, which
will expand to link to the necessary library.
8.7. Main target rules
A main target rule (e.g “exe” Or
“lib”) creates a top-level target. It’s
quite likely that you’ll want to declare your own and there are two ways
to do that.
The first way applies when your target rule
should just produce a target
of specific type. In that case, a rule is already defined for you! When
you define a new type, B2 automatically defines a corresponding
rule. The name of the rule is obtained from the name of the type, by
down-casing all letters and replacing underscores with dashes. For
example, if you create a module obfuscate.jam containing:
and import that module, you’ll be able to use the rule "obfuscated-cpp"
in Jamfiles, which will convert source to the OBFUSCATED_CPP type.
The second way is to write a wrapper rule that calls any of the existing
rules. For example, suppose you have only one library per directory and
want all cpp files in the directory to be compiled into that library.
You can achieve this effect using:
lib codegen : [ glob *.cpp ] ;
If you want to make it even simpler, you could add the following
definition to the Jamroot.jam file:
Note that because you can associate a custom generator with a target
type, the logic of building can be rather complicated. For example, the
boostbook module declares a target type BOOSTBOOK_MAIN and a custom
generator for that type. You can use that as example if your main target
rule is non-trivial.
8.8. Toolset modules
If your extensions will be used only on one project, they can be placed
in a separate .jam file and imported by your Jamroot.jam. If the
extensions will be used on many projects, users will thank you for a
finishing touch.
The using rule provides a standard mechanism for loading and
configuring extensions. To make it work, your module should provide an
init rule. The rule will be called with the same parameters that were
passed to the using rule. The set of allowed parameters is determined
by you. For example, you can allow the user to specify paths, tool
versions, and other options.
Here are some guidelines that help to make B2 more consistent:
The init rule should never fail. Even if the user provided an
incorrect path, you should emit a warning and go on. Configuration may
be shared between different machines, and wrong values on one machine
can be OK on another.
Prefer specifying the command to be executed to specifying the tool’s
installation path. First of all, this gives more control: it’s possible
to specify
/usr/bin/g++-snapshot
time g++
as the command. Second, while some tools have a logical "installation
root", it’s better if the user doesn’t have to remember whether a
specific tool requires a full command or a path.
Check for multiple initialization. A user can try to initialize the
module several times. You need to check for this and decide what to do.
Typically, unless you support several versions of a tool, duplicate
initialization is a user error. If the tool’s version can be specified
during initialization, make sure the version is either always specified,
or never specified (in which case the tool is initialized only once). For
example, if you allow:
using yfc ;
using yfc : 3.3 ;
using yfc : 3.4 ;
Then it’s not clear if the first initialization corresponds to version
3.3 of the tool, version 3.4 of the tool, or some other version. This
can lead to building twice with the same version.
If possible, init must be callable with no parameters. In which
case, it should try to autodetect all the necessary information, for
example, by looking for a tool in PATH or in common installation
locations. Often this is possible and allows the user to simply write:
using yfc ;
Consider using facilities in the tools/common module. You can take a
look at how tools/gcc.jam uses that module in the init rule.
9. Frequently Asked Questions
9.1. How do I get the current value of feature in Jamfile?
This is not possible, since Jamfile does not have "current" value of any
feature, be it toolset, build variant or anything else. For a single run
of B2, any given main target can be built with several property
sets. For example, user can request two build variants on the command
line. Or one library is built as shared when used from one application,
and as static when used from another. Each Jamfile is read only once so
generally there is no single value of a feature you can access in
Jamfile.
A feature has a specific value only when building a target, and there
are two ways you can use that value:
Define a custom generator and a custom main target type. The custom
generator can do arbitrary processing or properties. See the
extender manual
9.2. I am getting a "Duplicate name of actual target" error. What does that mean?
The most likely case is that you are trying to compile the same file
twice, with almost the same, but differing properties. For example:
exe a : a.cpp : /usr/local/include ;
exe b : a.cpp ;
The above snippet requires two different compilations of a.cpp, which
differ only in their include property. Since the include feature is
declared as free B2 does not create a separate build
directory for each of its values and those two builds would both produce
object files generated in the same build directory. Ignoring this and
compiling the file only once would be dangerous as different includes
could potentially cause completely different code to be compiled.
To solve this issue, you need to decide if the file should be compiled
once or twice.
To compile the file only once, make sure that properties are the
same for both target requests:
exe a : a.cpp : /usr/local/include ;
exe b : a.cpp : /usr/local/include ;
or:
alias a-with-include : a.cpp : /usr/local/include ;
exe a : a-with-include ;
exe b : a-with-include ;
or if you want the includes property not to affect how any other
sources added for the built a and b executables would be compiled:
obj a-obj : a.cpp : /usr/local/include ;
exe a : a-obj ;
exe b : a-obj ;
Note that in both of these cases the include property will be applied
only for building these object files and not any other sources that
might be added for targets a and b.
To compile the file twice, you can tell B2 to compile it to
two separate object files like so:
which will cause B2 to actually change the generated object
file names a bit for you and thus avoid any conflicts.
Note that in both of these cases the include property will be applied
only for building these object files and not any other sources that
might be added for targets a and b.
A good question is why B2 can not use some of the above
approaches automatically. The problem is that such magic would only help
in half of the cases, while in the other half it would be silently doing
the wrong thing. It is simpler and safer to ask the user to clarify his
intention in such cases.
9.3. Accessing environment variables
Many users would like to use environment variables in Jamfiles, for
example, to control the location of external libraries. In many cases it
is better to declare those external libraries in the site-config.jam
file, as documented in the recipes
section. However, if the users already have the environment variables
set up, it may not be convenient for them to set up their
site-config.jam files as well and using the environment variables might
be reasonable.
Boost.Jam automatically imports all environment variables into its
built-in .ENVIRON module so user can read them from there directly or by
using the helper os.environ rule. For example:
import os ;
local unga-unga = [ os.environ UNGA_UNGA ] ;
ECHO $(unga-unga) ;
or a bit more realistic:
import os ;
local SOME_LIBRARY_PATH = [ os.environ SOME_LIBRARY_PATH ] ;
exe a : a.cpp : $(SOME_LIBRARY_PATH) ;
9.4. How to control properties order?
For internal reasons, B2 sorts all the properties
alphabetically. This means that if you write:
exe a : a.cpp : b a ;
then the command line with first mention the a include directory, and
then b, even though they are specified in the opposite order. In most
cases, the user does not care. But sometimes the order of includes, or
other properties, is important. For such cases, a special syntax is
provided:
exe a : a.cpp : a&&b ;
The && symbols separate property values and specify that their order
should be preserved. You are advised to use this feature only when the
order of properties really matters and not as a convenient shortcut.
Using it everywhere might negatively affect performance.
9.5. How to control the library linking order on Unix?
On Unix-like operating systems, the order in which static libraries are
specified when invoking the linker is important, because by default, the
linker uses one pass though the libraries list. Passing the libraries in
the incorrect order will lead to a link error. Further, this behavior
is often used to make one library override symbols from another. So,
sometimes it is necessary to force specific library linking order.
B2 tries to automatically compute the right order. The primary
rule is that if library a "uses" library b, then library a will
appear on the command line before library b. Library a is considered
to use b if b is present either in the a library’s sources or its
usage is listed in its requirements. To explicitly specify the use
relationship one can use the feature. For example, both of the
following lines will cause a to appear before b on the command line:
lib a : a.cpp b ;
lib a : a.cpp :
The same approach works for searched libraries as well:
lib z ;
lib png : :
9.6. Can I get capture external program output using a Boost.Jam variable?
The SHELL builtin rule may be used for this purpose:
local gtk_includes = [ SHELL "gtk-config --cflags" ] ;
9.7. How to get the project root (a.k.a. Jamroot) location?
You might want to use your project’s root location in your Jamfiles. To
access it just declare a path constant in your Jamroot.jam file using:
path-constant TOP : . ;
After that, the TOP variable can be used in every Jamfile.
9.8. How to change compilation flags for one file?
If one file must be compiled with special options, you need to
explicitly declare an obj target for that file and then use that
target in your exe or lib target:
exe a : a.cpp b ;
obj b : b.cpp : off ;
Of course you can use other properties, for example to specify specific
C/C++ compiler options:
9.9. Why are the dll-path and hardcode-dll-paths properties useful?
ℹ
This entry is specific to Unix systems.
Before answering the questions, let us recall a few points about shared
libraries. Shared libraries can be used by several applications, or
other libraries, without physically including the library in the
application which can greatly decrease the total application size. It is
also possible to upgrade a shared library when the application is
already installed.
However, in order for application depending on shared libraries to be
started the OS may need to find the shared library when the application
is started. The dynamic linker will search in a system-defined list of
paths, load the library and resolve the symbols. Which means that you
should either change the system-defined list, given by the
LD_LIBRARY_PATH environment variable, or install the libraries to a
system location. This can be inconvenient when developing, since the
libraries are not yet ready to be installed, and cluttering system paths
may be undesirable. Luckily, on Unix there is another way.
An executable can include a list of additional library paths, which will
be searched before system paths. This is excellent for development
because the build system knows the paths to all libraries and can
include them in the executables. That is done when the
hardcode-dll-paths feature has the true value, which is the default.
When the executables should be installed, the story is different.
Obviously, installed executable should not contain hardcoded paths to
your development tree. (The install rule explicitly disables the
hardcode-dll-paths feature for that reason.) However, you can use the
dll-path feature to add explicit paths manually. For example:
will allow the application to find libraries placed in the
/usr/lib/snake directory.
If you install libraries to a nonstandard location and add an explicit
path, you get more control over libraries which will be used. A library
of the same name in a system location will not be inadvertently used. If
you install libraries to a system location and do not add any paths, the
system administrator will have more control. Each library can be
individually upgraded, and all applications will use the new library.
Which approach is best depends on your situation. If the libraries are
relatively standalone and can be used by third party applications, they
should be installed in the system location. If you have lots of
libraries which can be used only by your application, it makes sense to
install them to a nonstandard directory and add an explicit path, like
the example above shows. Please also note that guidelines for different
systems differ in this respect. For example, the Debian GNU guidelines
prohibit any additional search paths while Solaris guidelines suggest
that they should always be used.
9.10. Targets in site-config.jam
It is desirable to declare standard libraries available on a given
system. Putting target declaration in a specific project’s Jamfile is
not really good, since locations of the libraries can vary between
different development machines and then such declarations would need to
be duplicated in different projects. The solution is to declare the
targets in B2’s site-config.jam configuration file:
project site-config ;
lib zlib : : z ;
Recall that both site-config.jam and user-config.jam are projects,
and everything you can do in a Jamfile you can do in those files as
well. So, you declare a project id and a target. Now, one can write:
exe hello : hello.cpp /site-config//zlib ;
in any Jamfile.
9.11. Header-only libraries
In modern C++, libraries often consist of just header files, without any
source files to compile. To use such libraries, you need to add proper
includes and possibly defines to your project. But with a large number
of external libraries it becomes problematic to remember which libraries
are header only, and which ones you have to link to. However, with
B2 a header-only library can be declared as B2 target
and all dependents can use such library without having to remember
whether it is a header-only library or not.
Header-only libraries may be declared using the alias rule, specifying
their include path as a part of its usage requirements, for example:
alias my-lib
: # no sources
: # no build requirements
: # no default build
: whatever ;
The includes specified in usage requirements of my-lib are
automatically added to all of its dependents build properties. The
dependents need not care if my-lib is a header-only or not, and it is
possible to later make my-lib into a regular compiled library without
having to add the includes to its dependents declarations.
If you already have proper usage requirements declared for a project
where a header-only library is defined, you do not need to duplicate
them for the alias target:
project my : usage-requirements whatever ;
alias mylib ;
9.12. What is the difference between B2, b2, bjam and Perforce Jam?
B2 is the name of the complete build system. The executable
that runs it is b2. That executable is written in C and implements
performance-critical algorithms, like traversal of dependency graph and
executing commands. It also implements an interpreted language used to
implement the rest of B2. This executable is formally called
"B2 engine".
The B2 engine is derived from an earlier build tool called
Perforce Jam. Originally, there were just minor changes, and the
filename was bjam. Later on, with more and more changes, the
similarity of names became a disservice to users, and as of Boost
1.47.0, the official name of the executable was changed to b2. A copy
named bjam is still created for compatibility, but you are encouraged
to use the new name in all cases.
Perforce Jam was an important foundation, and we gratefully acknowledge
its influence, but for users today, these tools share only some basics
of the interpreted language.
10. Extra Tools
10.1. Documentation Tools
10.1.1. Asciidoctor
The asciidoctor tool converts the ascidoc documentation format to various
backend formats for either viewing or further processing by documentation
tools. This tool supports the baseline asciidoctor distribution (i.e. the
Ruby based tool).
Feature: asciidoctor-attribute
Defines arbitrary asciidoctor attributes. The value of the feature should be
specified with the CLI syntax for attributes.
For example to use as a target requirement:
html example : example.adoc :
idprefix=ex ;
This is a free feature and is not propagated. I.e. it applies only to the
target it’s specified on.
Feature: asciidoctor-doctype
Specifies the doctype to use for generating the output format. Allowed
doctype values are: article, book, manpage, and inline.
Feature: asciidoctor-backend
Specifies the backend to use to produce output from the source asciidoc.
This feature is automatically applied to fit the build target type. For
example, when specifying an html target for an asciidoc source:
html example : example.adoc ;
The target will by default acquire the html5
requirement. The default for each target type are:
html: html5
docbook: docbook45
man: manpage
pdf: pdf
To override the defaults you specify it as a requirement on the target:
To use the asciidoctor tool you need to declare it in a configuration file
with the using rule. The initialization takes the following arguments:
command: The command, with any extra arguments, to execute.
For example you could insert the following in your user-config.jam:
using asciidoctor : "/usr/local/bin/asciidoctor" ;
If no command is given it defaults to just asciidoctor with assumption
that the asciidoctor is available in the search PATH.
10.2. Miscellaneous Tools
10.2.1. pkg-config
The pkg-config program is used to retrieve information about installed
libraries in the system. It retrieves information about packages from special
metadata files. These files are named after the package, and have a .pc
extension. The package name specified to pkg-config is defined to be the name
of the metadata file, minus the .pc extension.
Feature: pkg-config
Selects one of the initialized pkg-config configurations. This feature is
propagated to dependencies. Its use is dicussed in
section Initialization.
Feature: pkg-config-define
This free feature adds a variable assignment to pkg-config invocation. For
example,
Main target rule that imports a pkg-config package. When its consumer targets
are built, pkg-config command will be invoked with arguments that depend on
current property set. The features that have an effect are:
: adds a --define-variable argument;
: adds --static argument when static;
: adds --static argument when static;
: specifies package name (target name is used instead if the property
is not present);
: specifies package version range, can be used multiple times and
should be a dot-separated sequence of numbers optionally prefixed with =,
<, >, ⇐ or >=.
config: the name of initialized configuration. The name can be omitted, in
which case the configuration will become the default one.
command: the command, with any extra arguments, to execute. If no command
is given, first PKG_CONFIG environment variable is checked, and if its
empty the string pkg-config is used.
options: options that modify pkg-config behavior. Allowed options are:
: sets PKG_CONFIG_PATH environment variable;
multiple occurences are allowed.
: sets PKG_CONFIG_LIBDIR environment variable;
multiple occurences are allowed.
: sets PKG_CONFIG_ALLOW_SYSTEM_CFLAGS
environment variable; multiple occurences are allowed.
: sets PKG_CONFIG_ALLOW_SYSTEM_LIBS
environment variable; multiple occurences are allowed.
: sets PKG_CONFIG_SYSROOT_DIR environment variable;
multiple occurences are allowed.
: adds a variable definition argument to command invocation;
multiple occurences are allowed.
Class pkg-config-target
class pkg-config-target : alias-target-class {
rule construct ( name : sources * : property-set )
rule version ( property-set )
rule variable ( name : property-set )
}
The class of objects returned by import rule. The objects themselves could be
useful in situations that require more complicated logic for consuming a
package. See Tips for examples.
rule version ( property-set )
Returns the package’s version, in the context of property-set.
rule variable ( name : property-set )
Returns the value of variable name in the package, in the context of
property-set.
Tips
Using several configurations
Suppose, you have 2 collections of .pc files: one for platform A, and another
for platform B. You can initialize 2 configurations of pkg-config tool each
corresponding to specific collection:
using pkg-config : A : : path/to/collection/A ;
using pkg-config : B : : path/to/collection/B ;
Then, you can specify that builds for platform A should use configuration A,
while builds for B should use configuration B:
Thanks to the fact, that project-config, user-config and site-config
modules are parents of jamroot module, you can put it in any of those files.o
Choosing the package name based on the property set
Since a file for a package should be named after the package suffixed with
.pc, some projects came up with naming schemes in order to allow simultaneous
installation of several major versions or build variants. In order to pick the
specific name corresponding to the build request you can use
property in requirements:
pkg-config.import mypackage : requirements @infer-name ;
rule infer-name ( properties * )
{
local name = mypackage ;
local variant = [ property.select : $(properties) ] ;
if $(variant) = debug
{
name += -d ;
}
return $(name) ;
}
The common.format-name rule can be very useful in this situation.
Modify usage requirements based on package version or variable
Sometimes you need to apply some logic based on package’s version or a
variable that it defines. For that you can use property in
usage requirements:
This tool converts SASS and SCSS files into CSS. This tool explicitly supports
both the version written in C (sassc) and the original Ruby implementation
(scss) but other variants might also work. In addition to tool-specific
features, described in this section, the tool recognizes features
and .
Feature: sass-style
Sets the output style. Available values are
nested: each property is put on its own line, rules are indented based on
how deeply they are nested;
expanded: each property is put on its own line, rules are not indented;
compact: each rule is put on a single line, nested rules occupy adjacent
lines, while groups of unrelated rules are separated by newlines;
compressed: takes minimum amount of space: all unnecessary whitespace is
removed, property values are compressed to have minimal representation.
The feature is optional and is not propagated to dependent targets. If no
style is specified, then, if property set contains property on,
compressed style is selected. Otherwise, nested style is selected.
Feature: sass-line-numbers
Enables emitting comments showing original line numbers for rules. This can be
useful for debugging a stylesheet. Available values are on and off. The
feature is optional and is not propagated to dependent targets. If no value
for this feature is specified, then one is copied from the feature
debug-symbols.
Initialization
To use the sass tool you need to declare it in a configuration file with the
using rule. The initialization takes the following arguments:
command: the command, with any extra arguments, to execute.
For example you could insert the following in your user-config.jam:
using sass : /usr/local/bin/psass -p2 ; # Perl libsass-based version
If no command is given, sassc is tried, after which scss is tried.
11. Examples
11.1. Introduction
Here we include a collection of simple to complex fully working examples of
using Boost Build v2 for various tasks. They show the gamut from simple
to advanced features. If you find yourself looking at the examples and not
finding something you want to see working please post to our support list
and we’ll try and come up with a solution and add it here for others to learn
from.
11.2. Hello
This example shows a very basic Boost Build project set up so it compiles a
single executable from a single source file:
hello.cpp
#include
int main()
{
std::cout << "Hello!\n";
}
Our jamroot.jam is minimal and only specifies one exe target for the
program:
The actual paths in the bin sub-directory will depend on your
toolset.
11.3. Sanitizers
This example shows how to enable sanitizers when using a clang or gcc toolset
main.cpp
int main()
{
char* c = nullptr;
std::cout << "Hello sanitizers\n " << *c;
}
Our jamroot.jam is minimal and only specifies one exe target for the
program:
jamroot.jam
exe main : main.cpp ;
Sanitizers can be enabled by passing on or norecover to the appropriate sanitizer feature
(e.g. thread-sanitizer=on). The norecover option causes the program to terminate after
the first sanitizer issue is detected. The following example shows how to enable address and undefined
sanitizers in a simple program:
Running the produced program may produce an output simillar to the following:
> ./bin/gcc-7.3.0/debug/address-sanitizer-norecover/undefined-sanitizer-on/main
Hello sanitizers
main.cpp:6:43: runtime error: load of null pointer of type 'char'
ASAN:DEADLYSIGNAL
=================================================================
==29767==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x55ba7988af1b bp 0x7ffdf3d76560 sp 0x7ffdf3d76530 T0)
==29767==The signal is caused by a READ memory access.
==29767==Hint: address points to the zero page.
#0 0x55ba7988af1a in main /home/damian/projects/boost/tools/build/example/sanitizers/main.cpp:6
#1 0x7f42f2ba1b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
#2 0x55ba7988adb9 in _start (/home/damian/projects/boost/tools/build/example/sanitizers/bin/gcc-7.3.0/debug/address-sanitizer-norecover/undefined-sanitizer-on/main+0xdb9)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/damian/projects/boost/tools/build/example/sanitizers/main.cpp:6 in main
==29767==ABORTING
ℹ
The actual paths in the bin sub-directory will depend on your
toolset and configuration. The presented output may vary depending on your compiler version.
12. Boost.Jam Documentation
Jam is a make(1) replacement that makes building simple things simple and building
complicated things manageable.
12.1. Building B2
Installing B2 after building it is simply a matter of copying the
generated executables someplace in your PATH. For building the
executables there are a set of build bootstrap scripts to accommodate
particular environments. The scripts take one optional argument, the
name of the toolset to build with. When the toolset is not given an
attempt is made to detect an available toolset and use that. The build
scripts accept these arguments:
build [toolset]
Running the scripts without arguments will give you the best chance of
success. On Windows platforms from a command console do:
cd jam source location
.\build.bat
On Unix type platforms do:
cd jam source location
sh ./build.sh
For the Boost.Jam source included with the Boost distribution the jam
source location is BOOST_ROOT/tools/build/src/engine.
If the scripts fail to detect an appropriate toolset to build with your
particular toolset may not be auto-detectable. In that case, you can
specify the toolset as the first argument, this assumes that the toolset
is readily available in the PATH.
ℹ
The toolset used to build Boost.Jam is independent of the toolsets used
for B2. Only one version of Boost.Jam is needed to use
B2.
The supported toolsets, and whether they are auto-detected, are:
Table 2. Supported Toolsets
Script
Platform
Toolset
Detection and Notes
build.bat
Windows
vc142
Microsoft Visual Studio C++ 2019
Uses vswhere utility.
vc141
Microsoft Visual Studio C++ 2017
Uses vswhere utility.
Common install location: %ProgramFiles%\Microsoft Visual Studio\2017\Enterprise\VC\
Common install location: %ProgramFiles%\Microsoft Visual Studio\2017\Professional\VC\
Common install location: %ProgramFiles%\Microsoft Visual Studio\2017\Community\VC\
vc14
Microsoft Visual Studio C++ 2015
Env var %VS140COMNTOOLS%
Common install location: %ProgramFiles%\Microsoft Visual Studio 14.0\VC\
vc12
Microsoft Visual Studio C++ 2013
Env var %VS120COMNTOOLS%
Common install location: %ProgramFiles%\Microsoft Visual Studio 12.0\VC\
borland
Embarcadero C++Builder
bcc32c.exe in PATH
intel-win32
Intel C++ Compiler for Windows
icl.exe in PATH
mingw
GNU GCC as the MinGW configuration
Common install location: C:\MinGW
como
Comeau Computing C/C++
gcc,
GNU GCC
clang
Clang LLVM
gcc-nocygwin
GNU GCC
build.sh
Unix, Linux, Cygwin, Windows Bash, etc.
gcc
GNU GCC
g++ in PATH
clang
Clang LLVM
clang++ in PATH
intel-linux
Intel C++ (oneAPI) for Linux
icpx in PATH
icc in PATH
icpc in PATH
setvars.sh in common install locations: $HOME/intel/oneapi,
/opt/intel/oneapi, /opt/intel/inteloneapi
iccvars.sh in common install locations: /opt/intel/cc/9.0/bin,
/opt/intel_cc_80/bin
mipspro
SGI MIPSpro C++
uname is "IRIX" or "IRIX64" and CC in PATH
true64cxx
Compaq C++ Compiler for True64 UNIX
uname is "OSF1" and cc in PATH
qcc
QNX Neutrino
uname is "QNX" and QCC in PATH
xlcpp and vacpp
IBM VisualAge C++
uname is "Linux" and xlC_r in PATH (xlcpp or vacpp depending on
machine endian)
uname is "AIX" and xlC_r in PATH (vacpp)
pgi
PGI Compilers
pgc++ in PATH
pathscale
Pathscale C++
pathCC in PATH
como
Comeau Computing C/C++
como in PATH
kylix
Borland C++
bc++ in PATH (kylix)
acc
HP-UX aCC
aCC in PATH
sunpro
Sun Workshop 6 C++
Standard install location: /opt/SUNWspro/bin/CC
The built executables are placed in the src/engine directory.
The build.sh script supports additional invocation options used to
control the the build and custom compilers:
build.sh [--option|--option=x] [toolset]
--help
Shows some help information, including these options.
--verbose
Show messages about what this script is doing.
--debug
Builds debugging versions of the executable. The default is to build an
optimized executable.
--guess-toolset
Print the toolset we can detect for building. This is used by external
scripts, like the Boost Libraries main bootstrap script.
--cxx=CXX
The compiler exec to use instead of the detected compiler exec.
--cxxflags=CXXFLAGS
The compiler flags to use in addition to the flags for the detected
compiler.
12.2. Language
B2 has an interpreted, procedural language. Statements in b2 are
rule (procedure) definitions, rule invocations, flow-of-control
structures, variable assignments, and sundry language support.
12.2.1. Lexical Features
B2 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 rule action is treated as a single string. A backslash
(\) can escape a double quote, or any single whitespace character.
B2 requires whitespace (blanks, tabs, or newlines) to surround all
tokens, including the colon (:) and semicolon (;) tokens.
B2 keywords (an 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.
Comments start with the # character and extend until the end of line.
And block comments start with #| and extend until the next |#.
12.2.2. Targets
The essential b2 data entity is a target. Build targets are files to
be updated. Source targets are the files used in updating built targets.
Built targets and source targets are collectively referred to as file
targets, and frequently built targets are source targets for other built
targets. Pseudo-targets are symbols representing 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 b2`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).
Binding Detection
Whenever a target is bound to a location in the filesystem, Boost Jam
will look for a variable called BINDRULE (first "on" the target being
bound, then in the global module). If non-empty, $(BINDRULE[1]) names
a rule which is called with the name of the target and the path it is
being bound to. The signature of the rule named by $(BINDRULE[1])
should match the following:
rule bind-rule ( target : path )
This facility is useful for correct header file scanning, since many
compilers will search for #include files first in the directory
containing the file doing the #include directive. $(BINDRULE) can be
used to make a record of that directory.
12.2.3. Rules
The basic b2 language entity is called a rule. A rule is defined in
two parts: the procedure and the actions. The procedure is a body of jam
statements to be run when the rule is invoked; the actions are the OS
shell commands to execute when updating the built targets of the rule.
Rules can return values, which can be expanded into a list with "[
ruleargs … ]". A rule’s value is the value of its last statement,
though only the following statements have values: 'if' (value of the leg
chosen), 'switch' (value of the case chosen), set (value of the
resulting variable), and 'return' (value of its arguments).
The b2 statements for defining and invoking rules are as follows:
Define a rule’s procedure, replacing any previous definition.
rule rulename { statements }
Define a rule’s updating actions, replacing any previous definition.
actions [ modifiers ] rulename { commands }
Invoke a rule.
rulename field1 : field2 : ... : fieldN ;
Invoke a rule under the influence of target’s specific variables..
A rule is invoked with values in field1 through fieldN. They may be
referenced in the procedure’s statements as $(1) through $(N) (9
max), and the first two only may be referenced in the action’s
commands as $(1) and $(2). $(<) and $(>) are synonymous with
$(1) and $(2).
Rules fall into two categories: updating rules (with actions), and pure
procedure rules (without actions). Updating rules treat arguments $(1)
and $(2) as built targets and sources, respectively, while pure
procedure rules can take arbitrary arguments.
When an updating rule is invoked, its updating 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,
commands are passed to the OS command shell, with $(1) and $(2)
replaced by bound versions of the target names. See Binding above.
Rule invocation may be indirected through a variable:
The variable’s value names the rule (or rules) to be invoked. A rule is
invoked for each element in the list of $(var)`s values. The fields
`field1 : field2 : … are passed as arguments for each invocation For the [
… ] forms, the return value is the concatenation of the return values
for all of the invocations.
Action Modifiers
The following action modifiers are understood:
actions bind vars
$(vars) will be replaced with bound values.
actions existing
$(>) includes only source targets currently existing.
actions ignore
The return status of the commands is ignored.
actions piecemeal
commands are repeatedly invoked with a subset of $(>) small enough
to fit in the command buffer on this OS.
actions quietly
The action is not echoed to the standard output.
actions together
The $(>) from multiple invocations of the same action on the same
built target are glommed together.
actions updated
$(>) includes only source targets themselves marked for updating.
Argument lists
You can describe the arguments accepted by a rule, and refer to them by
name within the rule. For example, the following prints "I’m sorry,
Dave" to the console:
rule report ( pronoun index ? : state : names + )
{
local he.suffix she.suffix it.suffix = s ;
local I.suffix = m ;
local they.suffix you.suffix = re ;
ECHO $(pronoun)'$($(pronoun).suffix) $(state), $(names[$(index)]) ;
}
report I 2 : sorry : Joe Dave Pete ;
Each name in a list of formal arguments (separated by : in the rule
declaration) is bound to a single element of the corresponding actual
argument unless followed by one of these modifiers:
Symbol
Semantics of preceding symbol
?
optional
*
Bind to zero or more unbound elements of the actual argument. When
* appears where an argument name is expected, any number of additional
arguments are accepted. This feature can be used to implement "varargs"
rules.
+
Bind to one or more unbound elements of the actual argument.
The actual and formal arguments are checked for inconsistencies, which
cause b2 to exit with an error code:
### argument error
# rule report ( pronoun index ? : state : names + )
# called with: ( I 2 foo : sorry : Joe Dave Pete )
# extra argument foo
### argument error
# rule report ( pronoun index ? : state : names + )
# called with: ( I 2 : sorry )
# missing argument names
If you omit the list of formal arguments, all checking is bypassed as in
"classic" Jam. Argument lists drastically improve the reliability and
readability of your rules, however, and are strongly recommended for
any new Jam code you write.
12.2.4. Built-in Rules
B2 has a growing set of 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.
Dependency Building
DEPENDS
rule DEPENDS ( targets1 * : targets2 * )
Builds a direct dependency: makes each of targets1 depend on each of
targets2. Generally, targets1 will be rebuilt if targets2 are
themselves rebuilt or are newer than targets1.
INCLUDES
rule INCLUDES ( targets1 * : targets2 * )
Builds a sibling dependency: makes any target that depends on any of
targets1 also depend on each of targets2. This reflects the
dependencies that arise when one source file includes another: the
object built from the source file depends both on the original and
included source file, but the two sources files don’t depend on each
other. For example:
DEPENDS foo.o : foo.c ;
INCLUDES foo.c : foo.h ;
foo.o depends on foo.c and foo.h in this example.
Modifying Binding
The six rules ALWAYS, LEAVES, NOCARE, NOTFILE, NOUPDATE, and
TEMPORARY modify the dependency graph so that b2 treats the targets
differently during its target binding phase. See Binding above.
Normally, b2 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:
ALWAYS
rule ALWAYS ( targets * )
Causes targets to be rebuilt regardless of whether they are up-to-date
(they must still be in the dependency graph). This is used for the clean
and uninstall targets, as they have no dependencies and would otherwise
appear never to need building. It is best applied to targets that are
also NOTFILE targets, but it can also be used to force a real file to
be updated as well.
LEAVES
rule LEAVES ( targets * )
Makes each of targets depend only on its leaf sources, and not on any
intermediate targets. This makes it immune to its dependencies being
updated, as the "leaf" dependencies are those without their own
dependencies and without updating actions. This allows a target to be
updated only if original source files change.
NOCARE
rule NOCARE ( targets * )
Causes b2 to ignore targets that neither can be found nor have
updating actions to build them. Normally for such targets b2 issues a
warning and then skips other targets that depend on these missing
targets. The HdrRule in Jambase uses NOCARE on the header file
names found during header file scanning, to let b2 know that the
included files may not exist. For example, if an #include is within an
#ifdef, the included file may not actually be around.
⚠
For targets with build actions: if their build actions exit with a
nonzero return code, dependent targets will still be built.
NOTFILE
rule NOTFILE ( targets * )
Marks targets as pseudo-targets and not real files. No timestamp is
checked, and so the actions on such a target are only executed if the
target’s dependencies are updated, or if the target is also marked with
ALWAYS. The default b2 target all is a pseudo-target In
Jambase, NOTFILE is used to define several addition convenient
pseudo-targets
NOUPDATE
rule NOUPDATE ( targets * )
Causes the timestamps on targets to be ignored. This has two effects:
first, once the target has been created it will never be updated;
second, manually updating target will not cause other targets to be
updated. In Jambase, for example, this rule is applied to directories
by the MkDir rule, because MkDir only cares that the target
directory exists, not when it has last been updated.
TEMPORARY
rule TEMPORARY ( targets * )
Marks targets as temporary, allowing them to be removed after other
targets that depend upon them have been updated. If a TEMPORARY target
is missing, b2 uses the timestamp of the target’s parent. Jambase
uses TEMPORARY to mark object files that are archived in a library
after they are built, so that they can be deleted after they are
archived.
FAIL_EXPECTED
rule FAIL_EXPECTED ( targets * )
For handling targets whose build actions are expected to fail (e.g. when
testing that assertions or compile-time type checking work properly),
Boost Jam supplies the FAIL_EXPECTED rule in the same style as
NOCARE, et. al. During target updating, the return code of the build
actions for arguments to FAIL_EXPECTED is inverted: if it fails,
building of dependent targets continues as though it succeeded. If it
succeeds, dependent targets are skipped.
RMOLD
rule RMOLD ( targets * )
B2 removes any target files that may exist on disk when the rule used
to build those targets fails. However, targets whose dependencies fail
to build are not removed by default. The RMOLD rule causes its
arguments to be removed if any of their dependencies fail to build.
ISFILE
rule ISFILE ( targets * )
ISFILE marks targets as required to be files. This changes the way
b2 searches for the target such that it ignores matches for file
system items that are not files, like directories. This makes it
possible to avoid #include "exception" matching if one happens to have
a directory named exception in the header search path.
⚠
This is currently not fully implemented.
Utility
The two rules ECHO and EXIT are utility rules, used only in `b2`s
parsing phase.
ECHO
rule ECHO ( args * )
Blurts out the message args to stdout.
EXIT
rule EXIT ( message * : result-value ? )
Blurts out the message to stdout and then exits with a failure status
if no result-value is given, otherwise it exits with the given
result-value.
Echo, echo, Exit, and exit are accepted as aliases for
ECHO and EXIT, since it is hard to tell that these are built-in
rules and not part of the language, like include.
Using the same wildcards as for the patterns in the switch statement. It
is invoked by being used as an argument to a rule invocation inside of
"[ ]". For example: FILES = [ GLOB dir1 dir2 : *.c *.h ] sets FILES to
the list of C source
and header files in dir1 and dir2. The resulting filenames are the
full pathnames, including the directory, but the pattern is applied only
to the file name without the directory.
If downcase-opt is supplied, filenames are converted to all-lowercase
before matching against the pattern; you can use this to do
case-insensitive matching using lowercase patterns. The paths returned
will still have mixed case if the OS supplies them. On Windows NT and
Cygwin, and OpenVMS, filenames are always down-cased before matching.
GLOB_ARCHIVE
The GLOB_ARCHIVE rule does name globing of object archive members.
Similarly to GLOB, this rule is used to match names of member files in
an archive (static object library). List of successfully matched members
is returned or null otherwise. The resulting member names are qualified
with pathname of the containing archive in the form
archive-path(member-name). Member patterns are for matching member
name only; when no wildcards specified — an exact match is assumed.
Member names generally correspond to object file names and as such are
platform-specific — use of platform-defined object suffix in the
matching patterns can allow for portability.
If downcase-opt is supplied, the member names are converted to
all-lowercase before matching against the pattern; you can use this to
do case-insensitive matching using lowercase patterns. The paths
returned will still have mixed case if the OS supplies them. On Windows
NT, Cygwin, and OpenVMS, filenames are always down-cased before matching.
Additionally, members can be matched with symbol/function patterns on
supported platforms (currently, OpenVMS only). In this case, members
containing the matching symbols are returned. Member and symbol patterns
are applied as OR conditions, with member patterns taking precedence. On
unsupported platforms, null is returned when any symbol patterns are
specified.
MATCH
The MATCH rule does pattern matching.
rule MATCH ( regexps + : list * )
Matches the egrep(1) style regular expressions regexps against the
strings in list. The result is a list of matching () subexpressions
for each string in list, and for each regular expression in regexps.
BACKTRACE
rule BACKTRACE ( )
Returns a list of quadruples: filenamelinemodulerulename…,
describing each shallower level of the call stack. This rule can be used
to generate useful diagnostic messages from Jam rules.
UPDATE
rule UPDATE ( targets * )
Classic jam treats any non-option element of command line as a name of
target to be updated. This prevented more sophisticated handling of
command line. This is now enabled again but with additional changes to
the UPDATE rule to allow for the flexibility of changing the list of
targets to update. The UPDATE rule has two effects:
It clears the list of targets to update, and
Causes the specified targets to be updated.
If no target was specified with the UPDATE rule, no targets will be
updated. To support changing of the update list in more useful ways, the
rule also returns the targets previously in the update list. This makes
it possible to add targets as such:
Defined only for win32 platform. It reads the registry of Windows.
'path' is the location of the information, and 'data' is the name of
the value which we want to get. If 'data' is omitted, the default
value of 'path' will be returned. The 'path' value must conform to
MS key path format and must be prefixed with one of the predefined root
keys. As usual,
HKLM is equivalent to HKEY_LOCAL_MACHINE.
HKCU is equivalent to HKEY_CURRENT_USER.
HKCR is equivalent to HKEY_CLASSES_ROOT.
Other predefined root keys are not supported.
Currently supported data types : REG_DWORD, REG_SZ,
REG_EXPAND_SZ, REG_MULTI_SZ. The data with REG_DWORD type
will be turned into a string, REG_MULTI_SZ into a list of strings,
and for those with REG_EXPAND_SZ type environment variables in it
will be replaced with their defined values. The data with REG_SZ
type and other unsupported types will be put into a string without
modification. If it can’t receive the value of the data, it just return
an empty list. For example,
Defined only for win32 platform. It reads the registry of Windows.
'path' is the location of the information, and 'result-type' is
either subkeys or values. For more information on 'path'
format and constraints, please see W32_GETREG.
Depending on 'result-type', the rule returns one of the following:
subkeys
Names of all direct sub-keys of 'path'.
values
Names of values contained in registry key given by 'path'. The
"default" value of the key appears in the returned list only if its
value has been set in the registry.
If 'result-type' is not recognized, or requested data cannot be
retrieved, the rule returns an empty list. Example:
local key = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths" ;
local subkeys = [ W32_GETREGNAMES "$(key)" : subkeys ] ;
for local subkey in $(subkeys)
{
local values = [ W32_GETREGNAMES "$(key)\\$(subkey)" : values ] ;
for local value in $(values)
{
local data = [ W32_GETREG "$(key)\\$(subkey)" : "$(value)" ] ;
ECHO "Registry path: " $(key)\\$(subkey) ":" $(value) "=" $(data) ;
}
}
SHELL
rule SHELL ( command : * )
SHELL executes command, and then returns the standard output of
command. SHELL only works on platforms with a popen() function in
the C library. On platforms without a working popen() function,
SHELL is implemented as a no-op. SHELL works on Unix, MacOS X, and
most Windows compilers. SHELL is a no-op on Metrowerks compilers under
Windows. There is a variable set of allowed options as additional
arguments:
exit-status
In addition to the output the result status of the executed command is
returned as a second element of the result.
no-output
Don’t capture the output of the command. Instead an empty ("") string
value is returned in place of the output.
strip-eol
Remove trailing end-of-line character from output, if any.
Because the Perforce/Jambase defines a SHELL rule which hides the
builtin rule, COMMAND can be used as an alias for SHELL in such a
case.
MD5
rule MD5 ( string )
MD5 computes the MD5 hash of the string passed as parameter and
returns it.
SPLIT_BY_CHARACTERS
rule SPLIT_BY_CHARACTERS ( string : delimiters )
SPLIT_BY_CHARACTERS splits the specified string on any delimiter
character present in delimiters and returns the resulting list.
PRECIOUS
rule PRECIOUS ( targets * )
The PRECIOUS rule specifies that each of the targets passed as the
arguments should not be removed even if the command updating that target
fails.
PAD
rule PAD ( string : width )
If string is shorter than width characters, pads it with whitespace
characters on the right, and returns the result. Otherwise, returns
string unmodified.
FILE_OPEN
rule FILE_OPEN ( filename : mode )
The FILE_OPEN rule opens the specified file and returns a file
descriptor. The mode parameter can be either "w" or "r". Note that at
present, only the UPDATE_NOW rule can use the resulting file
descriptor number.
The UPDATE_NOW caused the specified targets to be updated immediately.
If update was successful, non-empty string is returned. The log
parameter, if present, specifies a descriptor of a file where all output
from building is redirected. If the ignore-minus-n parameter is
specified, the targets are updated even if the -n parameter is
specified on the command line.
12.2.5. Flow-of-Control
B2 has several simple flow-of-control statements:
for var in list { statements }
Executes statements for each element in list, setting the variable
var to the element value.
if cond { statements }
[ else { statements } ]
Does the obvious; the else clause is optional. cond is built of:
a
true if any a element is a non-zero-length string
a = b
list a matches list b string-for-string
a != b
list a does not match list b
a < b
a[i] string is less than b[i] string, where i is first
mismatched element in lists a and b
a <= b
every a string is less than or equal to its b counterpart
a > b
a[i] string is greater than b[i] string, where i is first
mismatched element
a >= b
every a string is greater than or equal to its b counterpart
a in b
true if all elements of a can be found in b, or if a has no
elements
! cond
condition not true
cond && cond
conjunction
cond || cond
disjunction
( cond )
precedence grouping
include file ;
Causes b2 to read the named file. The file is bound like a regular
target (see Binding above) but unlike a regular target the include
file cannot be built.
The include file is inserted into the input stream during the parsing
phase. The primary input file and all the included file(s) are treated
as a single file; that is, b2 infers no scope boundaries from included
files.
local vars [ = values ] ;
Creates new vars inside to the enclosing {} block, obscuring any
previous values they might have. The previous values for vars are
restored when the current block ends. Any rule called or file included
will see the local and not the previous value (this is sometimes called
Dynamic Scoping). The local statement may appear anywhere, even outside
of a block (in which case the previous value is restored when the input
ends). The vars are initialized to values if present, or left
uninitialized otherwise.
return values ;
Within a rule body, the return statement sets the return value for an
invocation of the rule and returns to the caller.
switch value
{
case pattern1 : statements ;
case pattern2 : statements ;
...
}
The switch statement executes zero or one of the enclosed statements,
depending on which, if any, is the first case whose pattern matches
value. The pattern values are not variable-expanded. The pattern
values may include the following wildcards:
?
match any single character
*
match zero or more characters
[chars]
match any single character in chars
[^chars]
match any single character not in chars
\x
match x (escapes the other wildcards)
while cond { statements }
Repeatedly execute statements while cond remains true upon entry.
(See the description of cond expression syntax under if, above).
break ;
Immediately exits the nearest enclosing while or for loop.
continue ;
Jumps to the top of the nearest enclosing while or for loop.
12.2.6. Variables
B2 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 updating of the
specific target.
A variable is defined with:
variable = elements ;
variable += elements ;
variable on targets = elements ;
variable on targets += elements ;
variable default = elements ;
variable ?= elements ;
The first two forms set variable globally. The third and forth 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 final two forms are
synonymous: they set variable globally, but only if it was previously
unset.
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.
B2 variables are not re-exported to the environment of the shell that
executes the updating actions, but the updating actions can reference
b2 variables with $(variable).
Variable Expansion
During parsing, b2 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:
$(X) -> a b c
t$(X) -> ta tb tc
$(X)z -> az bz cz
$(X)-$(X) -> a-a a-b a-c b-a b-b b-c c-a c-b c-c
The variable name and modifiers can themselves contain a variable
reference, and this partakes of the product as well:
$(X) -> a b c
$(Y) -> 1 2
$(Z) -> X Y
$($(Z)) -> a b c 1 2
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 can be
negative in which case the element number n from the last leftward
is returned.
[n-m]
Select elements number n through m. n and m can be negative in
which case they refer to elements counting from the last leftward.
[n-]
Select elements number n through the last. n can be negative in
which case it refers to the element counting from the last leftward.
:B
Select filename base — a basename without extension.
:S
Select file extension — a (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.
:T
Converts all back-slashes ("\") to forward slashes ("/"). For example
x = "C:\\Program Files\\Borland" ; ECHO $(x:T) ;
prints C:/Program Files/Borland
:W
When invoking Windows-based tools from Cygwin
it can be important to pass them true windows-style paths. The :W
modifier, under Cygwin only, turns a cygwin path into a Win32 path
using the
cygwin_conv_to_win32_path
function. For example
x = "/cygdrive/c/Program Files/Borland" ; ECHO $(x:W) ;
prints C:\Program Files\Borland on Cygwin
Similarly, when used on OpenVMS, the :W modifier translates a
POSIX-style path into native VMS-style format using decc$to_vms CRTL
function. This modifier is generally used inside action blocks to
properly specify file paths in VMS-specific commands. For example
x = "subdir/filename.c" ; ECHO $(x:W) ;
prints [.subdir]filename.c on OpenVMS
On other platforms, the string is unchanged.
:chars
Select the components listed in chars.
For example, :BS selects filename (basename and extension).
: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
Assign value to the variable if it is unset.
:J=joinval
Concatenate list elements into single element, separated by
joinval.
:O=value
Sets semantic options for the evaluation of the variable. The format of the
value is specific to either variable or generated file expansion.
On VMS, $(var:P) is the parent directory of $(var:D).
:⇐value
After evaluating the expansion of the variable prefixes the given value
to the elements of the expanded expression values.
:>=value
After evaluating the expansion of the variable postfixes the given value
to the elements of the expanded expression values.
Local For Loop Variables
Boost Jam allows you to declare a local for loop control variable right
in the loop:
x = 1 2 3 ;
y = 4 5 6 ;
for local y in $(x)
{
ECHO $(y) ; # prints "1", "2", or "3"
}
ECHO $(y) ; # prints "4 5 6"
Generated File Expansion
During expansion of expressions b2 also looks for subexpressions of
the form @(filename:E=filecontents) and replaces the expression with
filename after creating the given file with the contents set to
filecontents. This is useful for creating compiler response files, and
other "internal" files. The expansion works both during parsing and
action execution. Hence it is possible to create files during any of the
three build phases. This expansion follows the same modifiers as variable
expansion. The generated file expansion accepts these (:O=) expansion
option values:
F
Always replace the @() reference with the name of the file generated.
C
Always replace the @() reference with the contents, i.e. the value
in the :E=value expression.
FC or CF
Replace with either the file or contents depending on the length of the
contents (:E=value). It will replace with the contents in an action
if the length of the command is shorter than the allowed command length
limit. Otherwise the reference is replaced with the filename.
Built-in Variables
This section discusses variables that have special meaning to b2. All
of these must be defined or used in the global module — using those
variables inside a named module will not have the desired effect. See
Modules.
SEARCH and LOCATE
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:
If $(LOCATE) is set then the target is bound relative to the first
directory in $(LOCATE). Only the first element is used for binding.
If $(SEARCH) is set then the target is bound to the first directory
in $(SEARCH) where the target file already exists.
If the $(SEARCH) search fails, the target is bound relative to the
current directory anyhow.
Both $(SEARCH) and $(LOCATE) should be set target-specific and not
globally. If they were set globally, b2 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
These two variables 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. This is the only place
where b2 invokes a rule through a variable setting.
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, b2 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).
Semaphores
It is sometimes desirable to disallow parallel execution of some
actions. For example:
Old versions of yacc use files with fixed names. So, running two yacc
actions is dangerous.
One might want to perform parallel compiling, but not do parallel
linking, because linking is i/o bound and only gets slower.
Craig McPeeters has extended Perforce Jam to solve such problems, and
that extension was integrated in Boost.Jam.
Any target can be assigned a semaphore, by setting a variable called
SEMAPHORE on that target. The value of the variable is the semaphore
name. It must be different from names of any declared target, but is
arbitrary otherwise.
The semantic of semaphores is that in a group of targets which have the
same semaphore, only one can be updated at the moment, regardless of
-j option.
Platform Identifier
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
Jam Version
JAMDATE
Time and date at b2 start-up as an ISO-8601 UTC value.
JAMUNAME
Output of uname(1) command (Unix only)
JAMVERSION
b2 version, as a sematic triplet "X.Y.Z".
JAM_VERSION
A predefined global variable with two elements indicates the version
number of Boost Jam. Boost Jam versions start at 0300.
Earlier versions of Jam do not automatically define JAM_VERSION.
JAMSHELL
When b2 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.
B2 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 b2 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:
#!/bin/sh
# This sample JAMSHELL uses the SunOS on(1) command to execute a
# command string with an identical environment on another host.
# Set JAMSHELL = jamshell ! %
#
# where jamshell is the name of this shell file.
#
# This version handles up to -j6; after that they get executed
# locally.
case $1 in
1|4) on winken sh -c "$2";;
2|5) on blinken sh -c "$2";;
3|6) on nod sh -c "$2";;
*) eval "$2";;
esac
__TIMING_RULE__ and __ACTION_RULE__
The __TIMING_RULE__ and __ACTION_RULE__ can be set to the name of a
rule for b2 to call after an action completes for a target. They
both give diagnostic information about the action that completed. For
__TIMING_RULE__ the rule is called as:
rule timing-rule ( args * : target : start end user system )
And __ACTION_RULE__ is called as:
rule action-rule ( args * : target : command status start end user system : output ? )
The arguments for both are:
args
Any values following the rule name in the __TIMING_RULE__ or
__ACTION_RULE__ are passed along here.
target
The b2 target that was built.
command
The text of the executed command in the action body.
status
The integer result of the executed command.
start
The starting timestamp of the executed command as a ISO-8601 UTC
value.
end
The completion timestamp of the executed command as a ISO-8601 UTC
value.
user
The number of user CPU seconds the executed command spent as a
floating point value.
system
The number of system CPU seconds the executed command spent as a
floating point value.
output
The output of the command as a single string. The content of the
output reflects the use of the -pX option.
ℹ
If both variables are set for a target both are called, first
__TIMING_RULE__ then __ACTION_RULE__.
12.2.7. Modules
Boost Jam introduces support for modules, which provide some rudimentary
namespace protection for rules and variables. A new keyword, module
was also introduced. The features described in this section are
primitives, meaning that they are meant to provide the operations needed
to write Jam rules which provide a more elegant module interface.
Declaration
module expression { ... }
Code within the { … } executes within the module named by evaluating
expression. Rule definitions can be found in the module’s own namespace,
and in the namespace of the global module as module-name.rule-name,
so within a module, other rules in that module may always be invoked
without qualification:
When an invoked rule is not found in the current module’s namespace, it
is looked up in the namespace of the global module, so qualified calls
work across modules:
Each module has its own set of dynamically nested variable scopes. When
execution passes from module A to module B, all the variable bindings
from A become unavailable, and are replaced by the bindings that belong
to B. This applies equally to local and global variables:
module A
{
x = 1 ;
rule f ( )
{
local y = 999 ; # becomes visible again when B.f calls A.g
B.f ;
}
rule g ( )
{
ECHO $(y) ; # prints "999"
}
}
module B
{
y = 2 ;
rule f ( )
{
ECHO $(y) ; # always prints "2"
A.g ;
}
}
The only way to access another module’s variables is by entering that
module:
Note that because existing variable bindings change whenever a new
module scope is entered, argument bindings become unavailable. That
explains the use of $(>) in the peek rule above.
Local Rules
local rule rulename...
The rule is declared locally to the current module. It is not entered in
the global module with qualification, and its name will not appear in
the result of:
[ RULENAMES module-name ]
The RULENAMES Rule
rule RULENAMES ( module ? )
Returns a list of the names of all non-local rules in the given module.
If module is omitted, the names of all non-local rules in the global
module are returned.
The VARNAMES Rule
rule VARNAMES ( module ? )
Returns a list of the names of all variable bindings in the given
module. If module is omitted, the names of all variable bindings in
the global module are returned.
ℹ
This includes any local variables in rules from the call stack which
have not returned at the time of the VARNAMES invocation.
The IMPORT rule copies rules from the source_module into the
target_module as local rules. If either source_module or
target_module is not supplied, it refers to the global module.
source_rules specifies which rules from the source_module to import;
target_rules specifies the names to give those rules in
target_module. If source_rules contains a name which doesn’t
correspond to a rule in source_module, or if it contains a different
number of items than target_rules, an error is issued. For example,
# import m1.rule1 into m2 as local rule m1-rule1.
IMPORT m1 : rule1 : m2 : m1-rule1 ;
# import all non-local rules from m1 into m2
IMPORT m1 : [ RULENAMES m1 ] : m2 : [ RULENAMES m1 ] ;
The EXPORT Rule
EXPORT allows rule name aliasing across modules:
rule EXPORT ( module ? : rules * )
The EXPORT rule marks rules from the source_module as non-local
(and thus exportable). If an element of rules does not name a rule in
module, an error is issued. For example,
module X {
local rule r { ECHO X.r ; }
}
IMPORT X : r : : r ; # error - r is local in X
EXPORT X : r ;
IMPORT X : r : : r ; # OK.
The CALLER_MODULE Rule
rule CALLER_MODULE ( levels ? )
CALLER_MODULE returns the name of the module scope enclosing the call
to its caller (if levels is supplied, it is interpreted as an integer
number of additional levels of call stack to traverse to locate the
module). If the scope belongs to the global module, or if no such module
exists, returns the empty list. For example, the following prints "{Y}
{X}":
DELETE_MODULE removes all of the variable bindings and
otherwise-unreferenced rules from the given module (or the global
module, if no module is supplied), and returns their memory to the
system.
ℹ
Though it won’t affect rules that are currently executing until they
complete, DELETE_MODULE should be used with extreme care because it
will wipe out any others and all variable (including locals in that
module) immediately. Because of the way dynamic binding works, variables
which are shadowed by locals will not be destroyed, so the results can
be really unpredictable.
12.3. Miscellaneous
12.3.1. Diagnostics
In addition to generic error messages, b2 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
B2 removed a partially built target after being interrupted.
12.3.2. Bugs, Limitations
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.
A poorly set $(JAMSHELL) is likely to result in silent failure.
12.3.3. Fundamentals
This section is derived from the official Jam documentation and from
experience using it and reading the Jambase rules. We repeat the
information here mostly because it is essential to understanding and
using Jam, but is not consolidated in a single place. Some of it is
missing from the official documentation altogether. We hope it will be
useful to anyone wishing to become familiar with Jam and the Boost build
system.
Jam rules are actually simple procedural entities. Think of them
as functions. Arguments are separated by colons.
A Jam target is an abstract entity identified by an arbitrary
string. The built-in DEPENDS rule creates a link in the dependency
graph between the named targets.
Note that the original Jam documentation for the built-in INCLUDES
rule is incorrect: INCLUDES targets1 : targets2 causes everything that
depends on a member of
targets1 to depend on all members of targets2. It does this in an
odd way, by tacking targets2 onto a special tail section in the
dependency list of everything in targets1. It seems to be OK to create
circular dependencies this way; in fact, it appears to be the "right
thing to do" when a single build action produces both targets1 and
targets2.
When a rule is invoked, if there are actions declared with the same
name as the rule, the actions are added to the updating actions for the
target identified by the rule’s first argument. It is actually possible
to invoke an undeclared rule if corresponding actions are declared: the
rule is treated as empty.
Targets (other than NOTFILE targets) are associated with paths in
the file system through a process called binding. Binding is a process
of searching for a file with the same name as the target (sans grist),
based on the settings of the target-specific SEARCH and LOCATE
variables.
In addition to local and global variables, jam allows you to set a
variable on a target. Target-specific variable values can usually not
be read, and take effect only in the following contexts:
In updating actions, variable values are first looked up on the
target named by the first argument (the target being updated). Because
Jam builds its entire dependency tree before executing actions, Jam
rules make target-specific variable settings as a way of supplying
parameters to the corresponding actions.
Binding is controlled entirely by the target-specific setting of
the SEARCH and LOCATE variables, as described here.
In the special rule used for header file scanning, variable values
are first looked up on the target named by the rule’s first argument
(the source file being scanned).
The "bound value" of a variable is the path associated with the target
named by the variable. In build actions, the first two arguments are
automatically replaced with their bound values. Target-specific
variables can be selectively replaced by their bound values using the
bind action modifier.
Note that the term "binding" as used in the Jam documentation
indicates a phase of processing that includes three sub-phases:
binding (yes!), update determination, and header file scanning. The
repetition of the term "binding" can lead to some confusion. In
particular, the Modifying Binding section in the Jam documentation
should probably be titled "Modifying Update Determination".
"Grist" is just a string prefix of the form <characters>. It is
used in Jam to create unique target names based on simpler names. For
example, the file name test.exe may be used by targets in separate
sub-projects, or for the debug and release variants of the "same"
abstract target. Each distinct target bound to a file called "test.exe"
has its own unique grist prefix. The Boost build system also takes full
advantage of Jam’s ability to divide strings on grist boundaries,
sometimes concatenating multiple gristed elements at the beginning of a
string. Grist is used instead of identifying targets with absolute paths
for two reasons:
The location of targets cannot always be derived solely from what
the user puts in a Jamfile, but sometimes depends also on the binding
process. Some mechanism to distinctly identify targets with the same
name is still needed.
Grist allows us to use a uniform abstract identifier for each built
target, regardless of target file location (as allowed by setting
ALL_LOCATE_TARGET).
When grist is extracted from a name with $(var:G), the result includes
the leading and trailing angle brackets. When grist is added to a name
with $(var:G=expr), existing grist is first stripped. Then, if expr is
non-empty, leading s are added if necessary to form an
expression of the form ; is then prepended.
When Jam is invoked it imports all environment variable settings into
corresponding Jam variables, followed by all command-line (-s…)
variable settings. Variables whose name ends in PATH, Path, or path are
split into string lists on OS-specific path-list separator boundaries
(e.g. ":" for UNIX and ";" for Windows). All other variables are split
on space (" ") boundaries. Boost Jam modifies that behavior by allowing
variables to be quoted.
A variable whose value is an empty list or which consists entirely of
empty strings has a negative logical value. Thus, for example, code like
the following allows a sensible non-empty default which can easily be
overridden by the user:
MESSAGE ?\= starting jam... ;
if $(MESSAGE) { ECHO The message is: $(MESSAGE) ; }
If the user wants a specific message, he invokes jam with
-sMESSAGE=message
text. If he wants no message, he invokes jam with
-sMESSAGE= and nothing at all is printed.
The parsing of command line options in Jam can be rather unintuitive,
with regards to how other Unix programs accept options. There are two
variants accepted as valid for an option:
-xvalue, and
-x value.
13. History
13.1. Version 4.6.1
Fix building b2 engine with cygwin64. — René Ferdinand Rivera Morell
Fix version detection of clang toolset from compiler exec. — Nikita Kniazev
13.2. Version 4.6.0
This release wraps up a few new features that make using some toolsets easier
(thanks to Nikita). It’s now also possible to specify empty flags features on
the command line, like cxxfalgs=, and have those be ignored. This helps to
make CI scripts shorter as they don’t need to handle those cases specially.
And as usual there are many bug fixes and adjustments. Thanks to everyone who
contributed to this release.
New: Allow clang toolset to be auto-configured to a specific version by using
toolset=clang-xx on the command line. — Nikita Kniazev
New: Include pch header automatically and on-demand on gcc and msvc toolset to
mirror clang functionality. — Nikita Kniazev
New: Features that are narked as 'free' and 'optional' will now be ignored when
the value specified on the command line is empty. Hence once can specify
cxxflags= on the command line without errors. — René Ferdinand Rivera Morell
Preserve bootstrap.sh invoke arguments to forward to the build.sh script. — tkoecker
Remove use of local in buils.sh to be compatible with some, not fully
capable, shells. — Tanzinul Islam
Workaround shell array ref error in build.sh on busybox shells. — tkoecker
Check for needing -pthread to build engine with gcc on some platforms. — tkoecker
Default to using clang on MacOS. — Stéphan Kochen
Add /python//numpy target to use as a dependency to communicate version
specific properties. — Peter Dimov
Add default value for cxx and cxxflags from env vars CXX and CXXFLAGS
when using the custom cxx toolset to build the engine. — Samuel Debionne and René Ferdinand Rivera Morell
Fix detection of intel-linux toolset installation when only the compiler
executable is in the PATH. — René Ferdinand Rivera Morell
Fix b2 executable path determination for platforms that don’t have a
native method of getting the path to executables, like OpenBSD. — René Ferdinand Rivera Morell
Fix property.find error message. — Thomas Brown
13.3. Version 4.5.0
Some minor fixes to improve some old issues.
Reenable ability of generators to return property-set as first item. — Andrew McCann
Fix examples to return 0 on success. — Mateusz Łoskot
Handle spaces in CXX path in config_toolset.bat.
Fix Conan b2 generator link, and pkg-config doc build error. — René Ferdinand Rivera Morell
13.4. Version 4.4.2
This release is the first of the new home for B2 at Build Frameworks Group.
Change references in documentation and sources of boost.org to point
at equivalent bfgroup resources. — René Ferdinand Rivera Morell
New theme for B2 site and documentation. — René Ferdinand Rivera Morell
13.5. Version 4.4.1
Minor patch to correct missing fix for macOS default engine compiler.
Fix engine build defaulting to gcc instead of clang on macOS/Xcode. — René Ferdinand Rivera Morell
13.6. Version 4.4.0
Along with a variety of fixes this version introduces "dynamic" response file
support for some toolsets. This means that under most circumstances, if
supported by the toolset, response files are not generated. Instead the
command is expanded to include the options directly.
New: Add response-file feature to control the kind of response file usage in
toolset action. — René Ferdinand Rivera Morell
New: Add :O=value variable modifier for @() expansion. — René Ferdinand Rivera Morell
New: Add :⇐value and :>=value variable modifiers for prefix and postfix
values after the complete expansion of variable references. — René Ferdinand Rivera Morell
New: Implement PCH on clang-win and clang-darwin. — Nikita Kniazev
New: Add support for Intel oneAPI release to intel-linux toolset. — René Ferdinand Rivera Morell
New: Add support for Intel oneAPI release to intel-windows toolset. — Edward Diener
Remove one at time linking limit. Once upon a time this was a performance
tweak as hardware and software was not up to doing multiple links at once.
Common setups are better equipped. — René Ferdinand Rivera Morell
Fix building engine with GCC on AIX. — René Ferdinand Rivera Morell
Support building engine as either 32 or 64 bit addressing model. — René Ferdinand Rivera Morell
Basic support for building b2 engine on GNU/Hurd. — Pino Toscano
Update "borland" toolset to bcc32c for building B2. — Tanzinul Islam
Ensure Embarcadero toolset name is only "embtc". — Tanzinul Islam
Adapt for Emscripten 2.0 change of default behavior for archives. — Basil Fierz
Fix path to bootstrap for back compat. — René Ferdinand Rivera Morell
Add missing BOOST_ROOT to boot strap search. — René Ferdinand Rivera Morell
Fix for engine compile on FreeBSD. — René Ferdinand Rivera Morell
Default MSVC to a native platform, and remove ambiguous implicit
address-model ARM/ARM64 values. — Nikita Kniazev
Fix detection of MIPS32 for b2 engine build. — Ivan Melnikov
Enable building b2 engine with clang on Windows. — Gei0r
Fix building b2 engine with Intel Linux icpc. — Alain Miniussi
Rework build.sh to fix many bugs and to avoid use of common env vars. — René Ferdinand Rivera Morell
Remove limitation of relevant features for configure checks. — René Ferdinand Rivera Morell
Reformat configure check output to inform the variants of the checks in a
reasonably brief form. — René Ferdinand Rivera Morell
Support building engine on Windows Bash with Mingw. — René Ferdinand Rivera Morell
13.7. Version 4.3.0
There are many invidual fixes in this release. Many thanks for the
contributions. Special thanks to Nikita for the many improvements to msvc
and general plugging of support holes in all the compilers.
There are some notable new features from Dmitry, Edward, and Nkita:
New: Add force-include feature to include headers before all sources. — Nikita Kniazev
New: Partial support for Embarcadero C++ compilers based on clang-5. — Edward Diener
New: Implement configurable installation prefixes that use features. — Dmitry Arkhipov
New: Add translate-path feature. The translate-path feature allows for
custom path handling, with a provided rule, on a per target basis. This can
be used to support custom path syntax. — René Ferdinand Rivera Morell
New: Add portable B2 system install option. This allows the b2 executable
and the build system files to live side by side. And hence to be (re)located
anywhere on disk. Soon to be used to supports Windows and other installers.
This removes the need for the boost-build.jam file for bootstrap. Making
it easier for users to get started. — René Ferdinand Rivera Morell
Unbreak building from VS Preview command prompt. — Marcel Raad
Fix compiler version check on macOS darwin toolset. — Bo Anderson
Remove pch target naming restriction on GCC. — Nikita Kniazev
Select appropriate QNX target platform. — Alexander Karzhenkov
Various space & performance improvements to the b2 engine build on Windows. — Nikita Kniazev
Fill extra and pedantic warning options for every compiler. — Nikita Kniazev
Include OS error reason for engine IO failures. — Nikita Kniazev
Use /Zc:inline and /Zc:throwingNew flags for better language conformance. — Nikita Kniazev
Add cxxstd value 20 for C++20. — Andrey Semashev
Parallel B2 engine compilation on MSVC. — Nikita Kniazev
Updated instruction-set feature with new x86 targets. — Andrey Semashev
Pass /nologo to rc on Windows compilers. — Nikita Kniazev
Fixed negation in conditional properties. — Nikita Kniazev
Remove leftover manifest generation early exiting. — Nikita Kniazev
Fix timestamp delta calculation. — Nikita Kniazev
Add missing assembler options to clang-win.jam, to enable Context to build. — Peter Dimov
Updated scarce :chars documentation with :BS example. — Nikita Kniazev
Fix link statically against boost-python on linux. — Joris Carrier
Ongoing cleanup of engine build warnings. — René Ferdinand Rivera Morell
Allow self-testing of toolsets that use response files. — René Ferdinand Rivera Morell
Port Jambase to native C++. Hence removing one of the oldest parts of the
original Jam bootstrap process. — René Ferdinand Rivera Morell
13.8. Version 4.2.0
This release is predominantly minor fixes and cleanup of the engine. In
particular the bootstrap/build process now clearly communicates C++11
requirement.
Add saxonhe_dir action. — Richard Hodges
Add CI testing for historical Boost versions on Windows MSVC. — René Ferdinand Rivera Morell
Check for C++11 support when building engine. Including an informative
error message as to that fact. — René Ferdinand Rivera Morell
Update Jam grammar parser with latest bison version. — René Ferdinand Rivera Morell
Allow root b2 b2 engine build to work even if bison grammar generator
is not available. — René Ferdinand Rivera Morell
Warning free engine build on at least Windows, macOS, and Linux. — René Ferdinand Rivera Morell
Sanitize Windows engine build to consistently use ANSI Win32 API. — Mateusz Loskot
Fix b2 engine not exiting, with error, early when it detects a Jam language
error. — Mateusz Loskot
Print help for local modules, i.e. current dir. — Thomas Brown
13.9. Version 4.1.0
Many small bug fixes in this release. But there are some new features also.
There’s now an lto feature to specify the use of LTO, and what kind. The
existing stdlib feature now has real values and corresponding options
for some toolsets. But most importantly there’s new documentation for all
the features.
Thank to all the users that contributed to this release with these changes:
Support for VS2019 for intel-vin 19.0. — Edward Diener
Fix compiler warnings about -std=gnu11 when building b2 on Cygwin. — Andrey Semashev
Add example of creating multiple PCHs for individual headers. — René Ferdinand Rivera Morell
Add QNX threading flags for GCC toolset. — Aurelien Chartier
Fix version option for IBM and Sun compilers when building b2 engine — Juan Alday
Rename strings.h to jam_strings.h in b2 engine to avoid clash with
POSIX strings.h header. — Andrey Semashev
Add options for cxxstd feature for IBM compiler. — Edward Diener
Many fixes to intel-win toolset. — Edwad Diener
Add z15 instruction set for gcc based toolsets. — Neale Ferguson
Improve using MSVC from a Cygwin shell. — Michael Haubenwallner
Add LTO feature and corresponding support for gcc and clang toolsets. — Dmitry Arkhipov
Fix errors when a source doesn’t have a type. — Peter Dimov
Add documentation for features. — Dmitry Arkhipov
Enhance stdlib feature, and corresponding documentation, for clang, gcc,
and sun toolsets. — Dmitry Arkhipov
Install rule now makes explicit only the immediate targets it creates. — Dmitry Arkhipov
Add armasm (32 and 64) support for msvc toolset. — Michał Janiszewski
Fix errors with custom un-versioned gcc toolset specifications. — Peter Dimov
Allow arflags override in gcc toolset specifications. — hyc
Fix founds libs not making it to the clang-win link command line. — Peter Dimov
Updated intel-win toolset to support for Intel C++ 19.1. — Edward Diener
Detect difference between MIPS32 and MIPS64 for OS in b2 engine. — YunQiang Su
13.10. Version 4.0.1
This patch release fixes a minor issue when trying to configure toolsets that
override the toolset version with a non-version tag. Currently this is only
known to be a problem if you: (a) configure a toolset version to something
like “tot” (b) in Boost 1.72.0 when it creates cmake install artifacts.
Fix for this was provided Peter Dimov.
13.11. Version 4.0.0
After even more years of development the landscape of build systems has changed
considerably, and so has the landscape of compilers. This version marks the
start of B2 transitioning to a C++ implementation. Initially this means that
the engine will be compiled as C++ source but that source is still the base
C implementation. Over time it will transform to a C++ code base in both the
engine and build system. Some changes in this start:
Requires C++ 11 to build engine.
Simplified build scripts to make it easier to maintain.
Building with C++ optimizations gives an immediate performance improvement.
Other changes in this release:
Add support for using prebuilt OpenSSL. — Damian Jarek
Define the riscv architecture feature. — Andreas Schwab
Add ARM64 as a valid architecture for MSVC. — Marc Sweetgall
Set coverage flags, from coverage feature, for gcc and clang. — Damian Jarek
Add s390x CPU and support in gcc/clang. — Neale Ferguson
Support importing pkg-config packages. — Dmitry Arkhipov
Support for leak sanitizer. — Damian Jarek
Fix missing /manifest option in clang-win to fix admin elevation for exes
with "update" in the name. — Peter Dimov
Add freertos to os feature. — Thomas Brown
Default parallel jobs (-jX) to the available CPU threads. — René Ferdinand Rivera Morell
Simpler coverage feature. — Hans Dembinski
Better stacks for sanitizers. — James E. King III
⚠
The default number of parallel jobs has changed in this release from
"1" to the number of cores. There are circumstances when that default can be
larger than the allocated cpu resources, for instance in some virtualized
container installs.