User documentation
This section will provide the information necessary to create your own projects using Boost.Build. The information provided here is relatively high-level, and detailed reference as well as the on-line help system must be used to obtain low-level documentation (see the help option).
The Boost.Build actually consists of two parts - Boost.Jam, which is a build engine with its own interpreted language, and Boost.Build itself, implemented in Boost.Jam's language. The chain of event which happen when you type "bjam" on the command is:
Boost.Jam tries to find Boost.Build and loads the top-level module. The exact process is described in the section on initialization
Boost.Build 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 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 commands.
So, to be able to successfully use Boost.Build, you'd need to know only three things:
How to configure Boost.Build
How to write Jamfiles
How the build process works

Configuration
The Boost.Build configuration is specified in the file "user-config.jam". You can edit the one which comes with Boost.Build, or create a copy in your home directory and edit that. (See the reference for the exact search paths.) The primary function of that file is to declarate which compilers and other tools are available. The simplest syntax to configure a tool is:

using <tool-name> ;

The "using" rule is given a name of tool, and will make that tool available to Boost.Build. For example, "using gcc ;" will make available the gcc compiler.
Since nothing but tool name is specified, Boost.Build will pick some default settings -- for example will use gcc found in path, or look in some known installation locations. For ordinary users, this is quite fine. In case you have several version of a compiler, or it's located in some unusual location, or you need to tweak the configuration, you'd need to pass additional parameters to the "using" rule. Generally, for every tool module, the parameters differ, and you can obtain the documentaiton by running

bjam --help <tool-name>.init

on the command line. However, for all compilers the meaning of the first three parameters is the same: version, invocation command and options.
The "version" parameter identifies the compiler, in case you have several. It can have any form you like, but it's recommended that you use a numeric identifier, like "7.1". The "invocation command" parameter is the command which must be executed to run the compiler. This might be just compiler name, or a name with a path in it. Here are some examples.
To configure a compiler installed in non-standard location and not present in path, you can do the following:

using msvc : : Z:/Programs/Microsoft Visual Studio/vc98/bin/cl.exe ;

To configure several versions of a compiler, the following can be used.

using gcc : 3.3 ;
using gcc : 3.4 : g++-3.4 ;
using gcc : 3.2 : g++-3.2 ;

Note that in the first call to "using", the compiler found in path will be used, and there's no need to explicitly specify the command.
As shown above, both "version" and "invocation command" parameters are optional, but there's an important restriction: if you configure the same compiler more then once, you must pass the "version" parameter every time. For example, the following is not allowed:

using gcc ;
using gcc : 3.4 : g++-3.4 ;

because the first "using" does not specify the version.
The options parameter is used to fine-tune the configuration. All compilers allow to pass four option, intentionally similiar in spelling to builtin features: cflags, cxxflags, compileflags and linkflags. They specify additional options which will be always passed to the corresponding tools. The cflags option applies only to the C compiler, the cxxflags option applies only to the C++ compiler and the compileflags options applies to both. For example, to use 64 bit mode with gcc you can use:

using gcc : 3.4 : : <compileflags>-m64 <linkflags>-m64 ;

Writing Jamfiles

Overview
Jamfiles are the thing which is most important to the user, bacause they declare the targets which should be build. Jamfiles are also used for organizing targets -- each Jamfile is a separate project, which can be build independently from the other projects.
Jamfile mostly contain calls to Boost.Build functions, which do all the work, specifically:
declare main targets
define project properties
do various other things
In addition to Jamfiles, Boost.Build has another user-editable file, project-root.jam, which is mostly useful to declare constants global to all the projects. It is described in more detail below.

Main targets
Main target is a user-defined named entity which can be build, for example a named executable file. Declaring a main target is usually done using one of main target functions. The user can also declare custom main target function.
Most main targets rules in Boost.Build use similiar syntax:

function-name main-target-name 
    : sources 
    : requirements 
    : default-build 
    : usage-requirements 
    ;

"main-target-name" is the name used to request the target on command line and to use it from other main targets. Main target name may contain alphanumeric characters and symbols '-' and '_';
"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.
"usage-requirements" is the list of properties that will be propagated to all main targets that use this one, i.e. to all dependents.
Note that the actual requirements, default-build and usage-requirements attributes for a target are obtained by combining the explicitly specified one with those specified for the project where a target is declared.
Some main target rules have shorter list of parameters, and you should consult their documentation for details.
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'd want to use all files with the same extension as sources, in which case you can use the "glob" rule. Here are two examples:

exe a : a.cpp ;
exe b : [ glob *.cpp ] ;

Unless you specify a files with absolute path, the name is considered relative to the source directory -- which is typically the same as directory when Jamfile is located, but can be changed as described here
The list of sources can also reference other main targets. The targets in the same project can be referred by using the name, and targets in other project need to specify directory or a symbolic name of the other project. For example:

lib helper : helper.cpp ;
exe a : a.cpp helper ;
exe b : b.cpp ..//utils ;
exe c : c.cpp /boost/program_options//program_opions ;

The first exe uses the library defined in the same project. The second one uses some target (most likely library) defined by Jamfile one level higher. Finally, the third target uses some C++ Boost library, using the symbolic name to refer to it. More information about it can be found in tutorial and in target id reference.
Requirements are the properties that should always be present when building a target. Typically, they are includes and defines:

exe hello : hello.cpp : <include>/opt/boost <define>MY_DEBUG ;

In special circumstances, other properties can be used, for example if a library does not work if it's shared, or a file can't be compiled with optimization due to a compiler bug, one can use

lib util : util.cpp : <link>static ;
obj main : main.cpp : <optimization>off ;

Sometimes, requirements are necessary only for a specific compiler, or build variant. The conditional properties can be used in that case:

lib util : util.cpp : <toolset>msvc:<link>static ;

In means when whenever <toolset>msvc property is in build properties, the <link>static property will be included as well. The conditional requirements can be "chained":

lib util : util.cpp : <toolset>msvc:<link>static 
                      <link>static:<define>STATIC_LINK ;

will set of static link and the STATIC_LINK define on the msvc toolset.
The default-build attribute is a set of properties which should be used if build request does not specify a value. For example:

exe hello : hello.cpp : : <threading>multi ;

would build the target in multi-threaded mode, unless the user explicitly requests single-threaded version. The difference between requirements and default-build is that requirements cannot be overriden in any way.
A target of the same name can be declared several times. In that case is declaration is called an alternative. When the target is build, one of the alternatives will be selected and use. Alternatives need not be defined by the same main target rule. The following is OK:

lib helpers : helpers.hpp ;
alias helpers : helpers.lib : <toolset>msvc ;

Building of the same main target can differ greatly from platform to platform. For example, you might have different list of sources for different compilers, or different options for those compilers. Two approaches to this are explained in the tutorial.
Sometimes a main target is really needed only by some other main target. For example, a rule that declares a test-suite uses a main target that represent test, but those main targets are rarely needed by themself.
It is possible to declare target inline, i.e. the "sources" parameter may include call to other main rules. For example:

exe hello : hello.cpp 
    [ obj helpers : helpers.cpp : <optimization>off ] ;

Will cause "helpers.cpp" to be always compiled without optimization. It's possible to request main targets declared inline, but since they are considered local, they are renamed to "parent-main-target_name..main-target-name". In the example above, to build only helpers, one should run "bjam hello..helpers".

Projects
As mentioned before, targets are grouped into project, and each Jamfile is a separate project. Projects are useful because it allows to group related targets together, define properties common to all those targets, and assign a symbolic name to the project, allowing to easily refer to the targets in the project. Two last goals are accompished with the "project" rule.
The rule has this syntax

project id : <attributes> ;

Here, attributes is a sequence of (attribute-name, attribute-value) pairs. 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 <threading>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 subprojects.
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 for the 'project' rule	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	If parent has a build dir set, the value of it, joined with the relative path from parent to the current project. Otherwise, empty	Sets to the passed value, interpreted as relative to the project's location.

Additional Jamfile rules
There's a number of other helper rules which can be used in Jamfile, described in the following table.

Rule	Semantic
project	Define project attributes.
use-project	Make another project known.
build-project	Build another project when this one is built.
explicit	States that the target should be built only by explicit request.
glob	Takes a list of wildcards, and returns the list of files which match any of the wildcards.
Each project is also associated with project root. That's a root for a tree of projects, which specifies some global properties.

Project root
Project root for a projects is the nearest parent directory which contains a file called project-root.jam. That file defines certain properties which apply to all projects under project root. It can:
configure toolsets, via call to toolset.using
refer to other projects, via the use-project rule
declare constants, via the constant and path-constant rules.
To facilitate declaration of simple projects, Jamfile and project-root can be merged together. To achieve this effect, the project root file should call the project rule. The semantic is precisely the same as if the call was made in Jamfile, except that project-root.jam will start to serve as Jamfile. The Jamfile in the directory of project-root.jam will be ignored, and project-root.jam will be able to declare main targets as usual.

Build process
When you've described your targets, you want Boost.Build 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 Boost.Build, unlike other build tools, the targets you declare do not correspond to specific files. What you declare in Jamfiles is more like "metatarget". Depending on the properties that 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 build several times with different properties, and will, of course, produce different files.
This means that for Boost.Build, you cannot directly obtain build variant from Jamfile. There could be several variants requested by the user, and each target can be build with different properties.

Build request
The command line specifies which targets to build and with what properties. For example:

bjam app1 lib1//lib1 toolset=gcc variant=debug optimization=full

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:

bjam app1 lib1//lib1 gcc debug optimization=full

The complete syntax which has some additional shortcuts if described here.

Building a main target
When you request, directly or indirectly, a build of a main target with specific requirements, the following steps are made. Some brief explanation is provided, and more detailes are given in the reference.
Applying default build. If the default-build property of a target specifies a value of a feature which 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 large 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 produces 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, Boost.Build uses "generators" --- objects which correspond to tools like compilers and linkers. Each generator declares what type of targets in can produce and what type of sources it requires. Using this information, Boost.Build 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.

Building a project
Often, user request a build of a complete project, not just one main target. In fact, invoking bjam without parameters builds the project defined in the current directory.
When a project is build, 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.

Builtin target types

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 
          : <threading>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 which is created by Boost.Build. Generally, sources can include C and C++ files, object files and libraries. Boost.Build will automatically try to convert targets of other types.
On Windows, if an application uses dynamic libraries, and both the application and the libraries are built by Boost.Build, its 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 place the application and the libraries to the same directory, for example using the stage rule.

Libraries
Libraries are created using the lib rule, which follows the common syntax. For example:

lib helpers : helpers.cpp : <include>boost : : <include>. ;

In the most common case, the lib creates a library from the specified sources. Depending on the value of <link> feature the library will be either static or shared. There are two other cases. First is when the library is installed somewhere in compiler's search paths, and should be searched by the compiler (typically, using the -l option). The second case is where the library is available as a prebuilt file and the full path is known.
The syntax for these case is given below:

lib z : : <name>z <search>/home/ghost ;            
lib compress : : <file>/opt/libs/compress.a ;

The name property specifies the name which should be passed to the -l option, and the file property specifies the file location. The search feature specifies paths where the library should be searched. That feature can be specified several time, or can be omitted -- in which case only default compiler paths will be searched.
The difference between using the file feature as opposed to the name name feature together with the search feature is that file is more precise. A specific file will be used. On the other hand, the search feature only adds a library path, and the name feature gives the basic name of the library. The search rules are specific to the linker. For example, given these definition:

lib a : : <variant>release <file>/pool/release/a.so ;
lib a : : <variant>debug <file>/pool/debug/a.so ;
lib b : : <variant>release <file>/pool/release/b.so ;
lib b : : <variant>debug <file>/pool/debug/b.so ;

It's possible to use release version of a and debug version of b. Had we used the name and search features, the linker would always pick either release or debug versions.
For convenience, the following syntax is allowed:

lib z ;
lib gui db aux ;

and is does exactly the same as:

lib z : : <name>z ;            
lib giu : : <name>gui ;            
lib db : : <name>db ;            
lib aux : : <name>aux ;

When a library uses another library you should put that another library in the 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, othewise, static linking on Unix won't work. For example:

lib z ;
lib png : z : <name>png ;

When a library (say, a), which has another library, (say, b) is linked dynamically, the b library will be incorporated in a. (If b is dynamic library as well, then a will only refer to it, and not include any extra code.) When the a library is linked statically, Boost.Build will assure that all executables which link to a will also link to b.
One feature of Boost.Build which is very important for libraries is usage requirements. For example, if you write:

lib helpers : helpers.cpp : : : <include>. ;

then compiler include path for all targets which use helpers will contain the directory where the target is defined.path to "helpers.cpp". So, the user need only to add helpers to the list of sources, and don't bother about other requirements. This allows to greatly simplify Jamfiles.
If you don't want shared libraries to include all libraries which are specified in sources (especially statically linked ones), you'd need to use the following:

lib b : a.cpp ;
lib a : a.cpp : <use>b : : <library>b ;

This specifies that a uses b, and causes all executables which link to a also link to b. In this case, even for shared linking, the a library won't even refer to b.

Alias
The alias rule follows the common syntax. For example:

alias core : im reader writer ;

will build the sources and return the generated source targets without modification.
The alias rule is a convenience tool. If you often build the same group of targets at the same time, you can define the alias to save typing.
Another use of the alias rule is to change build properties. For example, if you always want static linking for a specific C++ Boost library, you can write the following:

alias boost_thread : /boost/thread//boost_thread : <link>static ;

and use only the boost_thread alias in your Jamfiles.
It is also allowed to specify usage requirements for the alias target. If you write the following:

alias header_only_library : : : :  <include>/usr/include/header_only_library ;

then using header_only_library in sources will only add an include path. Also note that when there are some sources, their usage requirements are propagated, too. For example:

lib lib : lib.cpp : : : <include>. ;
alias lib_alias ;
exe main : main.cpp lib_alias ;

will compile main.cpp with the additional include.

Installing
For installing the built target you should use the stage rule follows the common syntax. For example:

stage dist : hello helpers ;

will cause the targets hello and helpers to be moved to the dist directory. The directory can be changed with the location property:

stage dist : hello helpers : <location>/usr/bin ;

Specifying the names of all libraries to install can be boring. The stage allows to specify only the top-level executable targets to install, and automatically install all dependencies:

stage dist : hello 
           : <traverse-dependencies>on <include-type>EXE
             <include-type>LIB
           ;

will find all targets that hello depends on, and install all of the which are either executables or libraries.

Testing
Boost.Build has convenient support for running unit tests. The simplest way is the unit-test rule, which follows the common syntax. For example:

unit-test helpers_test : helpers_test.cpp helpers ;

The unit-test rule behaves like the exe rule, but after the executable is created it is run. If the executable returns error, the build system will also return error and will try running the executable on the next invocation until it runs successfully. This behaviour ensures that you can't miss a unit test failure.
There are rules for more elaborate testing: compile, compile-fail, run and run-fail. They are more suitable for automated testing, and are not covered here yet.

Builtin features
variant	 The feature which combines several low-level features in order to make building most common variants simple.
Allowed values:debug, release, profile
The value debug expands to

            <optimization>off <debug-symbols>on <inlining>off <runtime-debugging>on

The value release expands to

            <optimization>speed <debug-symbols>off <inlining>full <runtime-debugging>off

The value profile expands to the same as release, plus:

            <profiling>on <debug-symbols>on

Rationale: Runtime debugging is on in debug build to suit expectations of people used various IDEs. It's assumed other folks don't have any specific expectation in this point.
link	 Feature which controls how libraries are built.
Allowed values:shared, static
source	 Tthe <source>X feature has the same effect on building a target as putting X in the list of sources. The feature is sometimes more convenient: you can put <source>X in the requirements for a project and it will be linked to all executables.
library	 This feature is equivalent to the <source> feature, and exists for backward compatibility reasons.
use	 Causes the target referenced by the value of this feature to be constructed and adds it's usage requirements to build properties. The constructed targets are not used in any other way. The primary use case is when you use some library and want it's usage requirements (such as include paths) to be applied, but don't want to link to the library.
dll-path	 Specify an additional path where shared libraries should be searched where the executable or shared library is run. This feature only affect Unix compilers. Plase see the FAQ entry for details.
hardcode-dll-paths	 Controls automatic generation of dll-path properties.
Allowed values:true, false. This property is specific to Unix systems. If an executable is build with <hardcode-dll-paths>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. Plase see the FAQ entry for details.

Differences to Boost.Build V1
While Boost.Build V2 is based on the same ideas as Boost.Build V1, some of the syntax was changed, and some new important features were added. This chapter describes most of the changes.

Configuration
In V1, there were two methods to configure a toolset. One is to set some environment variable, or use "-s" command line option to set variable inside BJam. Another method was creating new toolset module, which would set the variables and then invoke basic toolset. Neither method is necessary now, the "using" rule provides a consistent way to initialize toolset, including several versions. See section on configuraton for details.

Writing Jamfiles
Probably one of the most important differences in V2 Jamfiles is the project requirements. In V1, if several targets have the same requirements (for example, common include path), it was necessary to manually write that requirements, or use a helper rule. In V2, the common properties can be specified with the "requirements" project attribute, as documented here.
The usage requirements is also important mechanism to simplify Jamfile. If a library requires all clients to use specific includes, or macros when compiling the code which depends on the library, this information can be cleanly represented.
The difference between "lib" and "dll" targets in V1 is completely eliminated in V2. There's only one target -- "lib", which can create either static or shared library depending on the value of the <link> feature. If your target should be only build in one variant, you can add <link>shared or <link>static to requirements.
The syntax for referring to other targets was changed a bit. While in V1 one would use:

exe a : a.cpp <lib>../foo/bar ;

the V2 syntax is:

exe a : a.cpp ../foo//bar ;

Note that you don't need to specify the type of other target, but the last element should be separated to double slash, to indicate that you're referring to target "bar" in project "../foo", and not to project "../foo/bar".

Build process
The command line syntax in V2 is completely different. For example

bjam -sTOOLS=msvc -sBUILD=release some_target

now becomes:

bjam toolset=msvc variant=release some_target

or, using shortcuts, just:

bjam msvc release some_target

See the reference for complete description of the syntax.