diff --git a/v2/doc/src/tutorial.xml b/v2/doc/src/tutorial.xml
index 175e1f27e..8eee49a50 100644
--- a/v2/doc/src/tutorial.xml
+++ b/v2/doc/src/tutorial.xml
@@ -11,6 +11,10 @@
+
Hello, world
@@ -26,9 +30,10 @@ exe hello : hello.cpp ;
Even with this simple setup, you can do some interesting
things. First of all, just invoking bjam will
- build the debug variant of the hello>
+ build the hello
executable by compiling and
- linking hello.cpp. Now, to build the
+ linking hello.cpp. By default, debug variant
+ is built. Now, to build the
release variant of hello, invoke
@@ -45,12 +50,8 @@ bjam release
exe hello2 : hello.cpp ;
- Now we can build both the debug and release variants of our
- project:
-
-
-
-
+ Now let us build both the debug and release variants of our project
+ again:
bjam debug release
@@ -71,9 +72,6 @@ bjam --clean debug release
following two commands, respectively, build or clean only the
debug version of hello2.
-
-
bjam hello2
bjam --clean hello2
@@ -131,8 +129,6 @@ bjam variant=release inlining=off debug-symbols=on
A complete description of features can be found in .
-
-
@@ -140,12 +136,12 @@ bjam variant=release inlining=off debug-symbols=on
Build Requests and Target Requirements
- The set of properties specified in the command line constitute
+ The set of properties specified on the command line constitute
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 is typically a
+ properties used for building targets are typically a
combination of the build request and properties derived from
the project's Jamroot (and its other
Jamfiles, as described in
exe hello
: hello.cpp
- : <include>/home/ghost/Work/boost <threading>multi
+ : <include>boost <threading>multi
;
-
-
When hello is built, the two
- requirements specified above will normally always be present.
+ requirements specified above will always be present.
If the build request given on the bjam
command-line explictly contradicts a target's requirements,
- the command-line usually overrides (or, in the case of
- “free”” features like <include>,
+ the target requirements usually override (or, in the case of
+ “free”” features like
+ <include>,
See
- augments) the target requirements.
-
-
-
-
-
-
-
+
+ augments) the build request.
+
+ The value of the <include> feature is
+ relative to the location of Jamroot where it's
+ used.
+
+
+
Project Attributes
@@ -243,15 +230,12 @@ exe hello2 : hello.cpp ;
Jamroot file in an ancestor directory. For
example, in the following directory layout:
-
-
-
top/
|
+-- Jamroot
|
- +-- src/
+ +-- app/
| |
| +-- Jamfile
| `-- app.cpp
@@ -264,12 +248,10 @@ top/
. `-- bar.cpp
-
-
the project root is top/. Because there is
no Jamfile in
top/util/, the projects in
- top/src/ and
+ top/app/ and
top/util/foo/ are immediate children of the
root project.
@@ -318,28 +300,19 @@ top/
top/Jamroot might contain:
-build-project src ;
+build-project app ;
- which would cause the project in top/src/
+ 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/src/.
+ top/ or top/app/.
- Libraries and Dependent Targets
-
- TODO: need to make this
- section consistent with "examples-v2/libraries".
-
-
+ Dependent Targets
Targets that are “needed” by other targets are called
@@ -349,15 +322,16 @@ build-project src ;
To get a feeling of target dependencies, let's continue the
- above example and see how src/Jamfile can
- use libraries from util/foo. If
- util/foo/Jamfile contains
+ 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 src/Jamfile, we can write:
+ then to use this library in top/app/Jamfile, we can
+ write:
exe app : app.cpp ../util/foo//bar ;
@@ -366,41 +340,43 @@ 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. When linking the
- app executable, the appropriate version of
- bar will be built and linked in. What do we mean by
- “appropriate”? For example, suppose we build app with:
+ ../util/foo.
+
-
-bjam app optimization=full cxxflags=-w-8080
-
+
+ Some other build system have special syntax for listing dependent
+ libraries, for example LIBS variable. In Boost.Build,
+ you just add the library to the list of sources.
+
+
-
+ Suppose we build app with:
+
+bjam app optimization=full define=USE_ASM
+
+ Which properties will be used to build foo? The answer is
+ that some features are
+ propagated—Boost.Build attempts to use
+ dependencies with the same value of propagated features. The
+ <optimization> feature is propagated, so both
+ app and foo will be compiled
+ with full optimization. But <define> is not
+ propagated: its value will be added as-is to the compiler flags for
+ a.cpp, but won't affect foo.
+
- Which properties must be used to build foo? The
- answer is that some properties are
- propagated—Boost.Build attempts to
- use dependencies with the same value of propagated features. The
- <optimization> feature is propagated, so both app and
- foo will be compiled with full optimization. But
- <cxxflags> is not propagated: its value will be
- added as-is to the compiler flags for a.cpp, but won't affect
- foo. There are still a couple of problems. First, the library
+
+ 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 neccessary
#include paths to app's
requirements as values of the
- <include> feature, but then this work will be repeated for all programs
+ <include> 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:
-
-
project
: usage-requirements <include>.
@@ -412,362 +388,186 @@ lib foo : foo.cpp ;
Usage requirements are applied not to the target being declared
but to its
dependents. In this case, <include>. will be applied to all
- targets that use foo—i.e. targets that have foo
- either in their sources or in their dependency properties.
-
- You'd need to
- specify usage requirements only once, and programs that use foo
- don't have to care about include paths any longer.
-
- Of course, the
- path will be interpreted relatively to util/foo and will be
- adjusted according to the bjam invocation
- directory.
-
- For
- example, if building from project root, the final compiler
- command line will contain .
+ targets that directly depend on foo.
-
- The second problem
- is that we hardcode the path to library's Jamfile. Imagine it's
- hardcoded in 20 different places and we change the directory
- layout. The solution is to use project ids —symbolic names
- not tied to directory layout. First, we assign a project id to the
- project in util/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
+ Jamroot:
+
+use-project /library-example/foo : util/foo ;
+
+ Second, we modify app/Jamfile to use the
+ project id:
-project foo
- : usage-requirements <include>.
- ;
+exe app : app.cpp /library-example/foo//bar ;
-
-
- Second, we use the project id to refer to the library in
- src/Jamfile:
-
-
-exe app : app.cpp /foo//bar ;
-
-
-
-
- The /foo//bar syntax is used to refer to the target bar in
-
- the project with global id /foo (the slash
- is used to specify global id).
-
- This way, users of foo do not depend on its
- location, only on id, which is supposedly stable. The only thing
- left is to make sure that src/Jamfile knows
- the project id that it uses. We add the following line to
- top/Jamroot:
-
-
-use-project /foo : util/foo ;
-
-
- Now, all projects can refer to foo using the symbolic
- name. If the library is moved somewhere, only a single line in the
- top-level Jamfile should be changed.
+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 Jamroot must be modified.
+ Note that project ids are global—two Jamfiles are not
+ allowed to assign the same project id to different directories.
+
-
-
- Library dependencies
-
- The previous example was simple, but there are often long chains
- of dependencies between libraries. For example, the main application might be a thin
- wrapper on top of library with core logic, which uses another library of
- utility functions, which in turn uses the boost filesystem library.
- Expressing these dependencies is straightforward:
-
-
-lib utils : utils.cpp /boost/filesystem//fs ;
-lib core : core.cpp utils ;
-exe app : app.cpp core ;
-
-
-
-
- So, what's the reason to even mention this case? First,
- because it's a bit more complex that it seems. When using shared
- linking, libraries are build just as written, and everything will
- work. However, what happens with static linking? It's not
- possible to include another library in static library.
- Boost.Build solves this problem by returning back library targets
- that appear as sources for static libraries. In this case, if
- everything is built statically, the app target will link not
- only core library, but also utils and
- /boost/filesystem//fs.
-
- So, the net result is that the above code will work for both
- static linking and for shared linking.
-
-
- If you want all applications in some project to link
+
+ If you want all applications in some project to link
to a certain library, you can avoid having to specify it directly the sources of every
target by using the
<source> property. For example, if /boost/filesystem//fs
should be linked to all applications in your project, you can add
<source>/boost/filesystem//fs to the project's requirements, like this:
-
+
project
: requirements <source>/boost/filesystem//fs
;
-
-
-
-
+
+
+
+
Static and shared libaries
- While the
- previous section explained how to create and use libraries, it
- omitted one important detail.
-
- 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. Boost.Build can work with both
- types.
-
- By default, all libraries are shared. This is much more
- efficient in build time and space. But the need to install all
- libraries to some location
-
- is not always convenient, especially
- for debug builds.
-
- Also, if the installed shared library changes,
- all applications that use it might start to behave differently.
+ 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. Boost.Build can create and use both kinds.
-
- Static libraries do not suffer from these problems, but
- can considerably increase the size of an application. Before describing
- how to use static libraries, it's reasonable to give another, quite simple
- approach. If your project is built with
- <hardcode-dll-paths>true property, the application
- will include the full paths to all shared libraries, eliminating
- the above problems.
-
- Unfortunately, once that's done, you can no longer move that shared
- library to a different location, which makes this option suitable
- only for debug builds. Further, only gcc compiler supports this
- option.
-
-
-
- Building a library statically is easy; you just change
- the value of <link> feature from it's default value
- shared to static. So, to build everything as
- static libraries, you'd say
-
-
+
+ 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 static library, the value
+ should be static. You can either requiest static build
+ on the command line:
+
bjam link=static
-
+
+ or in the library's requirements:
+
+lib l : l.cpp : <link>static ;
+
+
- on the command line.
-
-
- We can also use the <link> 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:
+
+ We can also use the <link> 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:
+ as I was.
+ VP: to be addressed when this section is moved. See comment
+ below.
+-->
-
-exe important : main.cpp helpers/<link>static ;
-
+
+exe important : main.cpp helpers/<link>static ;
-No matter what arguments are specified on the bjam
-command-line, important will only be linked with
-the static version of helpers.
-
+ No matter what arguments are specified on the bjam
+ 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:
-
-
- A library that can only be built statically (or
- dynamically) can be described by putting the
- <link> feature in its
- requirements:
-
-
-lib l : l.cpp : <link>static ;
-
-
-
-
-
- If you need 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, you
- could use target references
- everywhere:
-
-
+
exe e1 : e1.cpp /other_project//bar/<link>static ;
-exe e10 : e10.cpp /other_project//bar/<link>static ;
-
+exe e10 : e10.cpp /other_project//bar/<link>static ;
- 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:
+ 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:
-
+
alias foo : /other_project//bar/<link>static ;
exe e1 : e1.cpp foo ;
-exe e10 : e10.cpp foo ;
-
+exe e10 : e10.cpp foo ;
- The alias
- rule is specifically used to rename a reference to a target and possibly
- change the properties.
-
-
+ The alias
+ rule is specifically used to rename a reference to a target and possibly
+ change the properties.
+
+
+
+
+
+
+ When one library uses another, you put the second library is
+ the source list of the first. For example:
+
+lib utils : utils.cpp /boost/filesystem//fs ;
+lib core : core.cpp utils ;
+exe app : app.cpp core ;
+ This works no matter what kind of linking is used. When
+ core is built as a shared library, it is linked
+ directly into utils. 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 Boost.Build testing facilities—the
+ PATH variable will be automatically adjusted before
+ running executable.
+
+
+
- Conditions and alternatives
-
-
- As we've just seen, properties can significally affect the
- way targets are built.
-
- The processing of the <link> feature is
- built in, and is quite complex, but
-
- there are a couple
- of mechanisms that allow ordinary users to do different things
- depending on properties.
-
-
-
-
-
- The first mechanism is called a conditional
+ Sometimes, particular relationships need to be maintained
+ among a target's build properties. This can be achieved with
+ conditional
requirement. 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.
-
-
+
lib network : network.cpp
: <link>shared:<define>NEWORK_LIB_SHARED
<variant>release:<define>EXTRA_FAST
@@ -788,7 +588,7 @@ lib network : network.cpp
it. We can express this situation using target
alternatives:
-lib demangler : dummy_demangler.cpp ; # alternative 1
+lib demangler : dummy_demangler.cpp ; # alternative 1
lib demangler : demangler_gcc.cpp : <toolset>gcc ; # alternative 2
lib demangler : demangler_msvc.cpp : <toolset>msvc ; # alternative 3
@@ -797,36 +597,19 @@ lib demangler : demangler_msvc.cpp : <toolset>msvc ; # alternative 3
will use a source file specific to the toolset. Otherwise, it
will use a generic source file,
dummy_demangler.cpp.
-
-
Prebuilt targets
- We've just learned how to use libraries that are created by
- Boost.Build. But some libraries are not.
-
- At the same time, those
- libraries can have different versions (release and debug, for
- example), that we
- should select depending on build properties. Prebuilt targets
- provide a mechanism for that. The Jamfile in util/lib2 can contain:
-
-
+ 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:
# util/lib2/Jamfile
lib lib2
@@ -840,12 +623,10 @@ lib lib2
;
- This code
- defines two alternatives for lib2, and for each
- one names a prebuilt file. Naturally, there are no sources.
- Instead, the <file> feature is used to
- specify the file name.
+ This example defines two alternatives for lib2, and
+ for each one names a prebuilt file. Naturally, there are no sources.
+ Instead, the <file> feature is used to specify
+ the file name.
Once a prebuilt target has been declared, it can be used just like any other target:
@@ -854,7 +635,7 @@ lib lib2
exe app : app.cpp ../util/lib2//lib2 ;
- As with any library target, the alternative selected depends on the
+ As with any target, the alternative selected depends on the
properties propagated from lib2's dependents.
If we build the the release and debug versions of app will be linked
with lib2_release.a and lib2_debug.a, respectively.
@@ -895,12 +676,8 @@ lib pythonlib : : <name>python22_d <variant>debug ;
A more advanced use of prebuilt targets is described in .
-
-
-
-
+ linkend="bbv2.recipies.site-config"/>.
+