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 ;