Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Chapter4.Overview

This section will provide the information necessary to create your own projects using Boost.Build. The information provided here is relatively high-level, and Chapter6, Reference as well as the on-line help system must be used to obtain low-level documentation (see --help).

Boost.Build actually consists of two parts - Boost.Jam, a build engine with its own interpreted language, and Boost.Build itself, implemented in Boost.Jam's language. The chain of events when you type b2 on the command line is as follows:

  1. The Boost.Build executable tries to find Boost.Build modules and loads the top-level module. The exact process is described in the section called “Initialization”

  2. The top-level module loads user-defined configuration files, user-config.jam and site-config.jam, which define available toolsets.

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

  4. Finally, using the build request specified on the command line, Boost.Build 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 Boost.Build, you need to know only four things:

Concepts

Boost.Build 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 flavour 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 a 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 multivariant builds, Boost.Build introduces the concept of a 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, Boost.Build 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, Boost.Build considers the properties requested on the command line. Supposed you have invoked Boost.Build 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, Boost.Build 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. Boost.Build 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 Boost.Build article.

PrevUpHomeNext