![]() |
Home | Libraries | People | FAQ | More |
Targets that are “needed” by other targets are called dependencies of those other targets. The targets that need the other targets are called dependent targets.
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 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.
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 app's
requirements as values of the
<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>.
;
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 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
Jamroot:
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 Jamroot 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 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
;