You wish to use Boost.Build to build an executable that depends on several static and dynamic libraries.
Follow these steps:
For each library on which the executable depends—unless it is distributed as a prebuilt binary—create a Jamfile as described in Recipe 1.8 and Recipe 1.9.
Create a Jamroot file in the directory where you want the executable to be created.
In the file Jamroot, invoke the
exe
rule to declare an executable target. Specify your .cpp files and the library targets on which the executable depends as sources. Also, add properties of the form<include>
path
as sources, if necessary, to tell the compiler where to search for library headers.In the file Jamroot, invoke the
install
rule, specifying the properties<install-dependencies>on
,<install-type>EXE
, and<install-type>SHARED_LIB
as requirements.Run bjam from the directory containing Jamroot as described in Recipe 1.7.
For example, to build an executable from the source files listed in Example 1-3, create a file named Jamroot in the directory hellobeatles as shown in Example 1-13.
Example 1-13. A Jamfile to build the executable hellobeatles.exe or hellobeatles
# Jamfile for project hellobeatles exe hellobeatles : # sources ../johnpaul//libjohnpaul ../georgeringo//libgeorgeringo hellobeatles.cpp ; install dist : # sources hellobeatles : # requirements <install-dependencies>on <install-type>EXE <install-type>SHARED_LIB <location>. ;
Now enter:
> bjam hellobeatles
from the directory hellobeatles. This first
builds the two projects on which the target hellobeatles
depends, and then builds the target hellobeatles
. Finally, enter:
> bjam dist
This copies the executable hellobeatles and the dynamic library georgeringo to the directory containing hellobeatles.cpp.
As discussed in Recipe 1.5, before you can run hellobeatles, you may need to place a copy of your toolset’s dynamic runtime library in a location where it can be found by the operating system.
The
library targets on which a target depends are specified as sources using
the notation path
//
target-name
. In Recipe 1.8 and Recipe 1.9, I showed how to declare a
target for a library to be built from source code by Boost.Build. If a library is
available as a prebuilt binary, however, you can declare a target for it as
follows:
libtarget-name
: : <file>file-name
;
As explained in Recipe 1.7, most main targets correspond not to a single file but to collections of related files, such as the debug and release build of an executable. To declare a target for a prebuilt library that has several variants, you can use the following notation:
libtarget-name
: : <file>file-name requirements
; lib
target-name
: : <file>other-file-name other-requirements
;
For example, debug and release variants of a prebuilt library might be declared as follows:
lib cryptolib : : <file> ../libraries/cryptolib/cryptolib_debug.lib
<variant>debug
; lib cryptolib : : <file> ../libraries/cryptolib/cryptolib.lib <variant>release
;
If a prebuilt library is located in one the directories that is searched automatically by the linker, as described in Recipe 1.5, you can declare a target for it as follows:
libtarget-name
: : <name>library-name
;
Here, library-name
is the name that should be passed to
the linker, which may differ from the actual file name, as discussed in Recipe 1.5. To tell the linker to look in
a particular directory, you can write
libtarget-name
: : <name>library-name
<search>library-path
;
A complex application may need to be installed together with a number of additional
executables and dynamic libraries on which it depends. Rather than specifying all
these files individually, you can use the install-dependencies
features, which allows you to specify only the
top-level executable target and the type of dependencies that should be installed. In
Example 1-13, the requirement
<install-dependencies>on
turns on the
install-dependencies
feature, and the
requirements <install-type>EXE
and <install-type>SHARED_LIB
tells Boost.Build to
install all dependencies that are executables or shared libraries. Other possible
values of the install-type
feature include LIB
and IMPORT_LIB
.
All three Jamfiles involved in building the executable hellobeatles are named Jamroot. This is fine in such a simple example, but in general it’s a good idea to organize a collection of Jamfiles hierarchically, with a single top-level Jamfile defining the project root. Arranging projects in this manner allows you to take advantage of some of Boost.Build’s more sophisticated features, such as allowing properties to be inherited by child projects. One way to accomplish this in the present case is to change the names of the Jamfiles in the directories johnpaul, georgeringo, and hellobeatles from Jamroot to Jamfile, and add to a Jamroot file in the parent directory with the following content:
# jamfile for example application build-project hellobeatles ;
The rule build-project
simply tells bjam to build a given project, which can be specified
either by pathname or by a symbolic identifier. If you change to the directory
containing Jamroot and run bjam, the three
child projects will be
built.
Recipe 1.5, Recipe 1.13, and Recipe 1.18
Get C++ Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.