![]() |
When a building a target X
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
.
![]() |
Tip |
---|---|
Some other build system have special syntax for listing dependent
libraries, for example |
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.
![]() |
Tip |
---|---|
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
project : requirements <source>/boost/filesystem//fs ; |