![]() |
When building a target X
that 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:
b2 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
dependants. 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 <library>/boost/filesystem//fs ; |