mirror of
https://github.com/boostorg/build.git
synced 2026-02-01 20:32:17 +00:00
913 lines
36 KiB
XML
913 lines
36 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
|
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
|
|
|
|
<?psgml nofill screen programlisting literallayout?>
|
|
|
|
<chapter id="bbv2.tutorial" status="draft">
|
|
<title>Tutorial</title>
|
|
|
|
<!-- You can't launch into this stuff without describing how to configure -->
|
|
<!-- Boost.Build... unless of course you think it's likely to work with -->
|
|
<!-- no configuration. But even if you do you have to tell people how to -->
|
|
<!-- configure their installation in case it doesn't work. -->
|
|
|
|
<section id="bbv2.tutorial.hello">
|
|
<title>Hello, world</title>
|
|
|
|
<para>The simplest project that Boost.Build can construct is
|
|
stored in <filename>example/hello/</filename> directory. The
|
|
project is described by a file
|
|
called <filename>Jamfile</filename> that contains:
|
|
|
|
<programlisting>
|
|
exe hello : hello.cpp ;
|
|
</programlisting>
|
|
|
|
Even with this simple setup, you can do some interesting
|
|
things. First of all, just invoking <command>bjam</command> will
|
|
build the debug variant of the <filename>hello</filename>>
|
|
executable by compiling and
|
|
linking <filename>hello.cpp</filename>. Now, to build the
|
|
release variant of <filename>hello</filename>, invoke
|
|
|
|
<screen>
|
|
bjam release
|
|
</screen>
|
|
|
|
Note that debug and release variants are created in different
|
|
directories, so you can switch between variants or even build
|
|
multiple variants at once, without any unneccessary
|
|
recompilation. Let's extend the example by adding another line
|
|
to our project's <filename>Jamfile</filename>:
|
|
|
|
<programlisting>
|
|
exe hello2 : hello.cpp ;
|
|
</programlisting>
|
|
|
|
Now we can build both the debug and release variants of our
|
|
project:
|
|
|
|
<!-- The phrasing above misleadingly makes it seem as though adding -->
|
|
<!-- this line makes it possible to build two variants, whereas -->
|
|
<!-- they're totally unrelated. -->
|
|
|
|
<screen>
|
|
bjam debug release
|
|
</screen>
|
|
|
|
Note that two variants of <filename>hello2</filename> are linked.
|
|
Since we have already built both variants
|
|
of <filename>hello</filename>, hello.cpp won't be recompiled;
|
|
instead the existing object files will just be linked into the
|
|
corresponding variants of <filename>hello2</filename>. Now
|
|
let's remove all the built products:
|
|
|
|
<screen>
|
|
bjam --clean debug release
|
|
</screen>
|
|
|
|
It's also possible to build or clean specific targets. The
|
|
following two commands, respectively, build or clean only the
|
|
debug version of <filename>hello2</filename>.
|
|
|
|
<!-- You can't say that without first telling people that the debug
|
|
variant is the default one, or you just sow confusion. -->
|
|
|
|
<screen>
|
|
bjam hello2
|
|
bjam --clean hello2
|
|
</screen>
|
|
</para>
|
|
|
|
</section>
|
|
<section id="bbv2.tutorial.properties">
|
|
<title>Properties</title>
|
|
|
|
<para>
|
|
To portably represent aspects of target configuration such as
|
|
debug and release variants, or single- and multi-threaded
|
|
builds, Boost.Build uses <firstterm>features</firstterm> with
|
|
associated <firstterm>values</firstterm>. For
|
|
example, the <code>debug-symbols</code> feature can have a value of <code>on</code> or
|
|
<code>off</code>. A <firstterm>property</firstterm> is just a (feature,
|
|
value) pair. When a user initiates a build, Boost.Build
|
|
automatically translates the requested properties into appropriate
|
|
command-line flags for invoking toolset components like compilers
|
|
and linkers.</para>
|
|
|
|
<para>There are many built-in features that can be combined to
|
|
produce arbitrary build configurations. The following command
|
|
builds the project's <code>release</code> variant with inlining
|
|
disabled and debug symbols enabled:
|
|
|
|
<screen>
|
|
bjam release inlining=off debug-symbols=on
|
|
</screen>
|
|
</para>
|
|
|
|
<para>Properties on the command-line are specified with the syntax:
|
|
|
|
<screen>
|
|
<replaceable>feature-name</replaceable>=<replaceable>feature-value</replaceable>
|
|
</screen>
|
|
</para>
|
|
|
|
<para>The <option>release</option> and <option>debug</option> that we've seen
|
|
in <command>bjam</command> invocations are just a shorthand way to
|
|
specify values of the <varname>variant</varname> feature. For example, the command
|
|
above could also have been written this way:
|
|
|
|
<screen>
|
|
bjam variant=release inlining=off debug-symbols=on
|
|
</screen>
|
|
</para>
|
|
|
|
<para> <varname>variant</varname> is so commonly-used that it has
|
|
been given special status as an <firstterm>implicit</firstterm>
|
|
feature—Boost.Build will deduce the its identity just
|
|
from the name of one of its values.
|
|
</para>
|
|
|
|
<para>
|
|
A complete description of features can be found in <xref linkend="bbv2.reference.features"/>.
|
|
<!-- <link linkend="bbv2.reference.features">here</link>. -->
|
|
<!-- You can't use "here" style links because they don't work in printed documentation. -->
|
|
</para>
|
|
|
|
|
|
<section id="bbv2.tutorial.properties.requirements">
|
|
<title>Build Requests and Target Requirements</title>
|
|
|
|
<para>
|
|
The set of properties specified in the command line constitute a
|
|
<firstterm>build request</firstterm>—a description of
|
|
the desired properties for building the requested targets (or,
|
|
if no targets were explicitly requested, the project in the
|
|
current directory). The <emphasis>actual</emphasis> properties
|
|
used for building targets is typically a combination of the
|
|
build request and properties derived from the
|
|
project's <filename>Jamfile</filename>s. For example, the
|
|
locations of <code>#include</code>d header files are normally
|
|
not specified on the command-line, but described
|
|
in <filename>Jamfile</filename>s as <firstterm>target
|
|
requirements</firstterm> and automatically combined with the
|
|
build request for those targets. Multithread-enabled
|
|
compilation is another example of a typical target requirement.
|
|
The <filename>Jamfile</filename> fragment below illustrates how
|
|
these requirements might be specified.
|
|
</para>
|
|
|
|
<programlisting>
|
|
exe hello
|
|
: hello.cpp
|
|
: <include>/home/ghost/Work/boost <threading>multi
|
|
;
|
|
</programlisting>
|
|
|
|
<!-- Can those requirements be written as
|
|
"include=/home/ghost/Work/boost threading=multi"? If so, we
|
|
should do everything in the manual, or at the very least in the
|
|
tutorial, that way. If not, why not? -->
|
|
|
|
<para>
|
|
When <filename>hello</filename> is built, the two
|
|
requirements specified above will normally always be present.
|
|
If the build request given on the <command>bjam</command>
|
|
command-line explictly contradicts a target's requirements,
|
|
the command-line usually overrides (or, in the case of
|
|
“free” features like <varname><include></varname>,
|
|
<footnote>
|
|
<para>
|
|
See <xref linkend="bbv2.reference.features.attributes"/>
|
|
augments) the target requirements.
|
|
</para>
|
|
</footnote>
|
|
<!--
|
|
However, when a
|
|
contradiction of a target's requrements involves certain
|
|
<firstterm>link-incompatible</firstterm> features, the target
|
|
will be skipped. See <xref linkend=
|
|
"bbv2.reference.variants.compat"/> for more information.
|
|
-->
|
|
|
|
<!-- Don't leave flotsam in the document/code. If the above is wrong, take -->
|
|
<!-- it out. That's what source control is for. -->
|
|
|
|
|
|
</para>
|
|
|
|
</section>
|
|
<section id="bbv2.tutorial.properties.project_attributes">
|
|
<title>Project Attributes</title>
|
|
|
|
<para>
|
|
If we want the same requirements for our other
|
|
target, <filename>hello2</filename>, we could simply duplicate
|
|
them. However, as projects grow, that approach leads to a great
|
|
deal of repeated boilerplate in Jamfiles.
|
|
|
|
Fortunately, there's a better way. Each project (i.e. each
|
|
<filename>Jamfile</filename>), can specify a set of <firstterm>attributes</firstterm>,
|
|
including requirements:
|
|
|
|
<programlisting>
|
|
project
|
|
: requirements <include>/home/ghost/Work/boost <threading>multi
|
|
;
|
|
|
|
exe hello : hello.cpp ;
|
|
exe hello2 : hello.cpp ;
|
|
</programlisting>
|
|
|
|
The effect would be as if we specified the same requirement for
|
|
both <filename>hello</filename> and <filename>hello2</filename>.
|
|
</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="bbv2.tutorial.hierarchy">
|
|
<title>Project Hierarchies</title>
|
|
|
|
<para>So far we've only considered examples with one project
|
|
(i.e. with one <filename>Jamfile</filename>). A typical large
|
|
codebase would be composed of many projects organized
|
|
into a tree. The top of the tree is called the
|
|
<firstterm>project root</firstterm>. Besides a
|
|
<filename>Jamfile</filename>, the project root directory
|
|
contains a file called <filename>project-root.jam</filename>. Every other
|
|
<filename>Jamfile</filename> in the project has a single parent
|
|
project, rooted in the nearest parent directory containing a
|
|
<filename>Jamfile</filename>. For example, in the following
|
|
directory layout:
|
|
|
|
<!-- Shouldn't we be introducing Jamroot here instead of -->
|
|
<!-- project-root.jam? It certainly is simpler. -->
|
|
|
|
<screen>
|
|
top/
|
|
|
|
|
+-- Jamfile
|
|
+-- project-root.jam
|
|
|
|
|
+-- src/
|
|
| |
|
|
| +-- Jamfile
|
|
| `-- app.cpp
|
|
|
|
|
`-- util/
|
|
|
|
|
+-- foo/
|
|
. |
|
|
. +-- Jamfile
|
|
. `-- bar.cpp
|
|
</screen>
|
|
|
|
<!-- "lib/lib1/lib1" changed to "util/foo/bar" to avoid confusion -->
|
|
|
|
the project root is <filename>top/</filename>. Because there is
|
|
no <filename>Jamfile</filename> in
|
|
<filename>top/util/</filename>, the projects in
|
|
<filename>top/src/</filename> and
|
|
<filename>top/util/foo/</filename> are immediate children of the
|
|
root project.
|
|
</para>
|
|
|
|
<para>
|
|
Projects inherit all attributes (such as requirements)
|
|
from their parents. Inherited requirements are combined with
|
|
any requirements specified by the sub-project.
|
|
For example, if <filename>top/Jamfile</filename> has
|
|
|
|
<programlisting>
|
|
<include>/home/ghost/local
|
|
</programlisting>
|
|
|
|
in its requirements, then all of its sub-projects will have it
|
|
in their requirements, too. Of course, any project can add
|
|
include paths to those specified by its parents. <footnote>
|
|
<para>Many
|
|
features will be overridden,
|
|
rather than added-to, in sub-projects. See <xref
|
|
linkend="bbv2.reference.features.attributes"/> for more
|
|
information</para>
|
|
</footnote>
|
|
More details can be found in
|
|
<xref linkend= "bbv2.advanced.projects"/>.
|
|
</para>
|
|
|
|
<para>
|
|
Invoking <command>bjam</command> without explicitly specifying
|
|
any targets on the command-line builds the project rooted in the
|
|
current directory. Building a project does not automatically
|
|
cause its sub-projects to be built unless the parent project's
|
|
<filename>Jamfile</filename> explicitly requests it. In our
|
|
example, <filename>top/Jamfile</filename> might contain:
|
|
|
|
<programlisting>
|
|
build-project src ;
|
|
</programlisting>
|
|
|
|
which would cause the project in <filename>top/src/</filename>
|
|
to be built whenever the project in <filename>top/</filename> is
|
|
built. However, targets in <filename>top/util/foo/</filename>
|
|
will be built only if they are needed by targets in
|
|
<filename>top/</filename> or <filename>top/src/</filename>.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="bbv2.tutorial.libs">
|
|
<title>Libraries and Dependent Targets</title>
|
|
|
|
<remark>TODO: need to make this
|
|
section consistent with "examples-v2/libraries".</remark>
|
|
|
|
<!--
|
|
What does that mean? Either make that change (much preferred),
|
|
or leave a comment that someone else can understand and use to
|
|
fix this section (only an option for the lazy ;->).
|
|
-->
|
|
|
|
<para>
|
|
Targets that are “needed” by other targets are called
|
|
<firstterm>dependencies</firstterm> of those other targets. The
|
|
targets that need the other targets are called
|
|
<firstterm>dependent</firstterm> targets.
|
|
</para>
|
|
|
|
<para>To get a feeling of target dependencies, let's continue the
|
|
above example and see how <filename>src/Jamfile</filename> can
|
|
use libraries from <filename>util/foo</filename>. Assume
|
|
util/foo/Jamfile contains:
|
|
|
|
<programlisting>
|
|
lib bar : bar.cpp ;
|
|
</programlisting>
|
|
|
|
Then, to use this library in <filename>src/Jamfile</filename>, we can write:
|
|
|
|
<programlisting>
|
|
exe app : app.cpp ../util/foo//bar ;
|
|
</programlisting>
|
|
|
|
While <code>app.cpp</code> refers to a regular source file,
|
|
<code>../util/foo//bar</code> is a reference to another target:
|
|
a library <filename>bar</filename> declared in the <filename>Jamfile</filename> at
|
|
<filename>../util/foo</filename>. When linking the
|
|
<filename>app</filename> executable, the appropriate version of
|
|
<code>bar</code> will be built and linked in. What do we mean by
|
|
“appropriate”? For example, suppose we build <filename>app</filename> with:
|
|
|
|
<screen>
|
|
bjam app optimization=full cxxflags=-w-8080
|
|
</screen>
|
|
|
|
<!-- I think it's a bad idea to expose nonportable features like
|
|
cxxflags this early in the documentation. It will tend to
|
|
encourage people who aren't familiar with Boost.Build to use them
|
|
when it could be avoided. I suggest using a portable feature like
|
|
<include> or <define> -->
|
|
|
|
Which properties must be used to build <code>foo</code>? The
|
|
answer is that some properties are
|
|
<firstterm>propagated</firstterm>—Boost.Build attempts to
|
|
use dependencies with the same value of propagated features. The
|
|
<varname><optimization></varname> feature is propagated, so both <filename>app</filename> and
|
|
<filename>foo</filename> will be compiled with full optimization. But
|
|
<varname><cxxflags></varname> is not propagated: its value will be
|
|
added as-is to the compiler flags for <filename>a.cpp</filename>, but won't affect
|
|
<filename>foo</filename>. There are still a couple of problems. First, the library
|
|
probably has some headers that must be used when compiling
|
|
<filename>app.cpp</filename>. We could manually add the neccessary
|
|
<code>#include</code> paths to <filename>app</filename>'s
|
|
requirements as values of the
|
|
<varname><include></varname> feature, but then this work will be repeated for all programs
|
|
that use <filename>foo</filename>. A better solution is to modify
|
|
<filename>util/foo/Jamfile</filename> in this way:
|
|
|
|
<!-- Look up the rules for using "that" vs. "which." It's "Janfile,"
|
|
not "Jamfilie." Take care to avoid silly typos. -->
|
|
|
|
<programlisting>
|
|
project
|
|
: usage-requirements <include>.
|
|
;
|
|
|
|
lib foo : foo.cpp ;
|
|
</programlisting>
|
|
|
|
Usage requirements are applied not to the target being declared
|
|
but to its
|
|
dependents. In this case, <literal><include>.</literal> will be applied to all
|
|
targets that use <filename>foo</filename>—i.e. targets that have <filename>foo</filename>
|
|
either in their sources or in their dependency properties.
|
|
<!-- You can't use the term "dependency properties" without first
|
|
defining it! This sort of thing happens over and over. I
|
|
suggest just saying "all targets that directly depend on foo." -->
|
|
You'd need to
|
|
specify usage requirements only once, and programs that use <filename>foo</filename>
|
|
don't have to care about include paths any longer.
|
|
<!-- Point of good writing: programs are inanimate and don't
|
|
"care" about include paths. I suggest striking the previous
|
|
sentence anyway as it's redundant. -->
|
|
Of course, the
|
|
path will be interpreted relatively to <filename>util/foo</filename> and will be
|
|
adjusted according to the <command>bjam</command> invocation
|
|
directory.
|
|
<!-- You need to explain this path adjustment in the first place
|
|
you introduce #include paths, probably with a "Tip"
|
|
element. It applies to all relative paths in
|
|
Boost.Build, some of which you've covered. -->
|
|
For
|
|
example, if building from project root, the final compiler
|
|
command line will contain <option>-Ilib/foo</option>.
|
|
</para>
|
|
|
|
<para>
|
|
The second problem <!-- by this point I've completely forgotten
|
|
that there was a first problem. I suggest starting the a new
|
|
paragraph for the first one, and describing these as improvements
|
|
we can make, rather than problems. -->
|
|
is that we hardcode the path to library's Jamfile. Imagine it's
|
|
hardcoded in 20 different places and we change the directory
|
|
layout. The solution is to use project ids —symbolic names
|
|
not tied to directory layout. First, we assign a project id to the
|
|
project in <filename>util/foo:</filename>
|
|
</para>
|
|
|
|
<programlisting>
|
|
project foo
|
|
: usage-requirements <include>.
|
|
;
|
|
</programlisting>
|
|
|
|
<para>
|
|
Second, we use the project id to refer to the library in
|
|
src/Jamfile:
|
|
|
|
<programlisting>
|
|
exe app : app.cpp /foo//bar ;
|
|
</programlisting>
|
|
|
|
<!-- It is counterintuitive and confusing to assign a top-level
|
|
absolute project ID to this subproject. It should be something
|
|
like /myproject/foo.
|
|
|
|
In fact I'm beginning to
|
|
wonder what the point of labelling the project root with
|
|
project-root.jam or Jamroot is. See my jamboost post. -DWA
|
|
-->
|
|
|
|
The <filename>/foo//bar</filename> syntax is used to refer to the target <filename>bar</filename> in
|
|
<!-- I assume I was right to change foo into bar here. Please
|
|
take care not to make errors like this one; it leaves the
|
|
reader mightily confused about what's really going on if he
|
|
assumes the documentation is correct. -->
|
|
the project with global id <filename>/foo</filename> (the slash
|
|
is used to specify global id).
|
|
<!-- as opposed to what? There's no such thing as a "local" id
|
|
is there? This parenthetical remark is more confusing than
|
|
enlightening. It gives the impression that we could leave
|
|
the slash off and still have a project id, but a path
|
|
without a preceding slash always specifies a file path
|
|
(right?) -->
|
|
This way, users of <filename>foo</filename> do not depend on its location, only
|
|
on id, which is supposedly stable. The only thing left is to make
|
|
sure that <filename>src/Jamfile</filename> knows the project id that it uses. We add to
|
|
<filename>top/Jamfile</filename> the following line:
|
|
|
|
<programlisting>
|
|
use-project /foo : util/foo ;
|
|
</programlisting>
|
|
|
|
Now, all projects can refer to <filename>foo</filename> using the symbolic
|
|
name. If the library is moved somewhere, only a single line in the
|
|
top-level Jamfile should be changed.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="bbv2.tutorial.depends">
|
|
<title>Library dependencies</title>
|
|
|
|
<para>The previous example was simple, but there are often long chains
|
|
of dependencies between libraries. For example, the main application might be a thin
|
|
wrapper on top of library with core logic, which uses another library of
|
|
utility functions, which in turn uses the boost filesystem library.
|
|
Expressing these dependencies is straightforward:</para>
|
|
|
|
<programlisting>
|
|
lib utils : utils.cpp /boost/filesystem//fs ;
|
|
lib core : core.cpp utils ;
|
|
exe app : app.cpp core ;
|
|
</programlisting>
|
|
|
|
<!-- Point of style: the "ask a question and then answer it" style
|
|
you frequently use just complication. Use fewer words;
|
|
just come out and say what you mean.
|
|
|
|
Also, you can't have a "First,..." without a "Second,..." or
|
|
a "Next,...." Don't underestimate how much confusion that can
|
|
add for the reader.
|
|
|
|
Also, "built just as written, and everything will work" is
|
|
vague and confusing.
|
|
|
|
This information might be too low-level for the main flow of
|
|
the tutorial. It also might turn out to be specific to some
|
|
particular platforms. It would be much better to handle it
|
|
in a callout box if you feel compelled to mention it here.
|
|
|
|
If you want to keep the info here, the whole paragraph needs
|
|
to be rewritten. You could say all this (including the
|
|
one-sentence paragraph that follows) in one or two sentences.
|
|
|
|
"When core is built as a dynamic library, it is linked
|
|
directly into utils. Static libraries can't link to other
|
|
libraries, so when core is built as a static library, its
|
|
dependency on utils is passed along to core's dependents,
|
|
causing app to be linked with both core and utils."
|
|
|
|
The material here probably doesn't warrant a whole section of
|
|
the document. "Libraries and Dependent Targets" isn't easy
|
|
to distinguish from "Library Dependencies" anyway. Merge the
|
|
two.
|
|
|
|
You *definitely* can't talk about "returning back" library
|
|
targets. That assumes the reader has a mental model of the
|
|
Boost.Build internals!
|
|
|
|
-->
|
|
|
|
<para>So, what's the reason to even mention this case? First,
|
|
because it's a bit more complex that it seems. When using shared
|
|
linking, libraries are build just as written, and everything will
|
|
work. However, what happens with static linking? It's not
|
|
possible to include another library in static library.
|
|
Boost.Build solves this problem by returning back library targets
|
|
that appear as sources for static libraries. In this case, if
|
|
everything is built statically, the <filename>app</filename> target will link not
|
|
only <filename>core</filename> library, but also <filename>utils</filename> and
|
|
<filename>/boost/filesystem//fs</filename>.</para>
|
|
|
|
<para>So, the net result is that the above code will work for both
|
|
static linking and for shared linking.</para>
|
|
|
|
<tip>
|
|
<para>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
|
|
<varname><source></varname> property. For example, if <filename>/boost/filesystem//fs</filename>
|
|
should be linked to all applications in your project, you can add
|
|
<code><source>/boost/filesystem//fs</code> to the project's requirements, like this:</para>
|
|
|
|
<programlisting>
|
|
project
|
|
: requirements <source>/boost/filesystem//fs
|
|
;
|
|
</programlisting>
|
|
</tip>
|
|
|
|
</section>
|
|
|
|
<section id="bbv2.tutorial.linkage">
|
|
<title>Static and shared libaries</title>
|
|
|
|
<para>While the
|
|
previous section explained how to create and use libraries, it
|
|
omitted one important detail.
|
|
<!-- The foregoing sentence adds nothing -->
|
|
Libraries can be either
|
|
<emphasis>static</emphasis>, which means they are included in executable
|
|
files that use them, or <emphasis>shared</emphasis> (a.k.a.
|
|
<emphasis>dynamic</emphasis>), which are only referred to from executables,
|
|
and must be available at run time. Boost.Build can work with both
|
|
types.
|
|
<!-- This section seems to be introducing the idea of static and
|
|
shared libraries, but you just spent a couple of paragraphs
|
|
talking about them in the previous section! Clearly that is
|
|
not "one important detail that was omitted." Please take care
|
|
that terms are defined and concepts introduced before they're
|
|
used. -->
|
|
By default, all libraries are shared. This is much more
|
|
efficient in build time and space. But the need to install all
|
|
libraries to some location
|
|
<!-- If I'm a reader who doesn't know about shared linking as
|
|
this section seems to assume, I have absolutely no context
|
|
for "the need to install all libraries to some location."
|
|
It has no obvious relationship to anything we're discussing
|
|
here. -->
|
|
is not always convenient, especially
|
|
for debug builds.
|
|
<!-- An incongruous assumption about the reader's knowledge.
|
|
The relationship of debug builds to all this is
|
|
non-obvious. -->
|
|
Also, if the installed shared library changes,
|
|
all applications that use it might start to behave differently.
|
|
</para>
|
|
|
|
<para>Static libraries do not suffer from these problems, but
|
|
can considerably increase the size of an application. Before describing
|
|
how to use static libraries, it's reasonable to give another, quite simple
|
|
approach. If your project is built with
|
|
<code><hardcode-dll-paths>true</code> property, the application
|
|
will include the full paths to all shared libraries, eliminating
|
|
the above problems.
|
|
<!-- Not the last one. So it solves just one of two problems
|
|
mentioned above. -->
|
|
Unfortunately, once that's done, you can no longer move that shared
|
|
library to a different location, which makes this option suitable
|
|
only for debug builds. Further, only gcc compiler supports this
|
|
option.
|
|
<!-- Now you tell me?! You should put all this information in a
|
|
<tip> box that begins "If you're a GCC user..." -->
|
|
</para>
|
|
|
|
<para>Building a library statically is easy; you just change
|
|
the value of <varname><link></varname> feature from it's default value
|
|
<literal>shared</literal> to <literal>static</literal>. So, to build everything as
|
|
static libraries, you'd say
|
|
|
|
<screen>
|
|
bjam link=static
|
|
</screen>
|
|
|
|
on the command line. </para>
|
|
|
|
<para>
|
|
We can also use the <varname><link></varname> property
|
|
to express linking requirements on a per-target basis.
|
|
<!-- <orderedlist> The use of an orderedlist is inappropriate here. -->
|
|
For example, if a particular executable can be correctly built
|
|
only with the static version of a library, we can qualify the
|
|
executable's <link
|
|
linkend="bbv2.reference.targets.references">target
|
|
reference</link> to the library as follows:
|
|
|
|
<!-- There has been no earlier indication that target references can
|
|
contain properties. You can't assume that the reader will
|
|
recognize that strange incantation as a target reference, or that
|
|
she'll know what it means. You also can't assume that hyperlinks
|
|
will help the reader, because she may be working from a printout,
|
|
as I was. -->
|
|
|
|
<programlisting>
|
|
exe important : main.cpp helpers/<link>static ;
|
|
</programlisting>
|
|
|
|
No matter what arguments are specified on the <command>bjam</command>
|
|
command-line, <filename>important</filename> will only be linked with
|
|
the static version of <filename>helpers</filename>.
|
|
</para>
|
|
|
|
|
|
<!-- Take note of the difference between "build" and
|
|
"built." This error is repeated throughout. -->
|
|
<para>
|
|
A library that can only be built statically (or
|
|
dynamically) can be described by putting the
|
|
<varname><link></varname> feature in its
|
|
requirements:
|
|
|
|
<programlisting>
|
|
lib l : l.cpp : <link>static ;
|
|
</programlisting>
|
|
|
|
</para>
|
|
|
|
<para>
|
|
If you need use a library defined in some other project
|
|
(one you can't change) but you still want static (or dynamic) linking
|
|
to that library in all cases, you
|
|
<emphasis>could</emphasis> use target references
|
|
everywhere:
|
|
|
|
<programlisting>
|
|
exe e1 : e1.cpp /other_project//bar/<link>static ;
|
|
exe e10 : e10.cpp /other_project//bar/<link>static ;
|
|
</programlisting>
|
|
|
|
but that's far from being convenient. A better approach is
|
|
to introduce a level of indirection. Create a local
|
|
<type>alias</type> target that refers to the static (or
|
|
dynamic) version of <filename>foo</filename>:
|
|
|
|
<programlisting>
|
|
alias foo : /other_project//bar/<link>static ;
|
|
exe e1 : e1.cpp foo ;
|
|
exe e10 : e10.cpp foo ;
|
|
</programlisting>
|
|
|
|
The <link linkend="bbv2.builtins.alias"><functionname>alias</functionname></link>
|
|
rule is specifically used to rename a reference to a target and possibly
|
|
change the properties.
|
|
|
|
<!-- You should introduce the alias rule in an earlier
|
|
section, before describing how it applies to this
|
|
specific use-case, and the foregoing sentence should
|
|
go there. -->
|
|
|
|
</para>
|
|
</section>
|
|
|
|
<section id="bbv2.tutorial.conditions">
|
|
<title>Conditions and alternatives</title>
|
|
|
|
<!-- We haven't "just figured out" anything. You didn't lead the
|
|
reader through a deductive process. -->
|
|
|
|
<para>As we've just seen, properties can significally affect the
|
|
way targets are built.
|
|
<!-- What is the point in saying that? Affecting the way
|
|
targets are built is the whole point of properties. The
|
|
previous sentence makes it sound like affecting the way
|
|
targets are built is just an incidental characteristic. -->
|
|
The processing of the <varname><link></varname> feature is
|
|
built in, and is quite complex, but
|
|
<!-- These two points don't make an appropriate "A but B"
|
|
clause, because <link> doesn't allow the system to "do
|
|
different things depending on properties. -->
|
|
there are a couple
|
|
of mechanisms that allow ordinary users to do different things
|
|
depending on properties.
|
|
<!-- They don't _allow users_ to do different things; it's the
|
|
build system that does different things. And "different
|
|
things" is too vague. -->
|
|
</para>
|
|
|
|
<!-- You could replace the foregoing paragraph with:
|
|
|
|
"Sometimes, particular relationships need to be maintained
|
|
among a target's build properties. In this section we'll
|
|
discuss two mechanisms for expressing those relationships."
|
|
|
|
It took me about five minutes to figure out how to say that,
|
|
and it still isn't perfect. But at least it says what we're
|
|
about to talk about with _some_ precision. Saying what you
|
|
mean is hard and requires an investment of effort and
|
|
attention.
|
|
-->
|
|
|
|
<para>The first mechanism is called a <firstterm>conditional
|
|
requirement</firstterm>. For example, you might want to set
|
|
specific <code>#defines</code> when a library is built as shared,
|
|
or when a target's <code>release</code> variant is built in
|
|
release mode.
|
|
<!-- "Here's a piece of Jamfile" adds nothing. -->
|
|
<programlisting>
|
|
lib network : network.cpp
|
|
: <strong><link>shared:<define>NEWORK_LIB_SHARED</strong>
|
|
<strong><variant>release:<define>EXTRA_FAST</strong>
|
|
;
|
|
</programlisting>
|
|
|
|
In the example above, whenever <filename>network</filename> is
|
|
built with <code><link>shared</code>,
|
|
<code><define>NEWORK_LIB_SHARED</code> will be in its
|
|
properties, too.
|
|
</para>
|
|
|
|
<para>
|
|
Sometimes the ways a target is built are so different that
|
|
describing them using conditional requirements would be
|
|
hard. For example, imagine that a library actually uses
|
|
different source files depending on the toolset used to build
|
|
it. We can express this situation using <firstterm>target
|
|
alternatives</firstterm>:
|
|
<programlisting>
|
|
lib demangler : dummy_demangler.cpp ; # alternative 1
|
|
lib demangler : demangler_gcc.cpp : <toolset>gcc ; # alternative 2
|
|
lib demangler : demangler_msvc.cpp : <toolset>msvc ; # alternative 3
|
|
</programlisting>
|
|
In the example above, when built with <literal>gcc</literal>
|
|
or <literal>msvc</literal>, <filename>demangler</filename>
|
|
will use a source file specific to the toolset. Otherwise, it
|
|
will use a generic source file,
|
|
<filename>dummy_demangler.cpp</filename>.
|
|
<!-- You can't say "The proper alternative will be automatically
|
|
selected" because it presumes the user understands what's
|
|
proper. You haven't even said what an alternative is! -->
|
|
</para>
|
|
|
|
</section>
|
|
|
|
|
|
<section id="bbv2.tutorial.prebuilt">
|
|
<title>Prebuilt targets</title>
|
|
|
|
<para>
|
|
We've just learned how to use libraries that are created by
|
|
Boost.Build. But some libraries are not.
|
|
<!-- You can't start a sentence with "But" -->
|
|
At the same time, those
|
|
libraries can have different versions (release and debug, for
|
|
example), that we
|
|
should select depending on build properties. Prebuilt targets
|
|
provide a mechanism for that. The Jamfile in util/lib2 can contain:
|
|
|
|
<!-- You should replace the above with:
|
|
|
|
To link to libraries whose build instructions
|
|
aren't given in a Jamfile, you just need to
|
|
create targets with an appropriate <file>
|
|
property. Target alternatives can be used to
|
|
associate multiple library files with a single
|
|
conceptual target.
|
|
-->
|
|
<programlisting>
|
|
# util/lib2/Jamfile
|
|
lib lib2
|
|
:
|
|
: <file>lib2_release.a <variant>release
|
|
;
|
|
|
|
lib lib2
|
|
:
|
|
: <file>lib2_debug.a <variant>debug
|
|
;
|
|
</programlisting>
|
|
|
|
This <!-- you can't say "this defines" without an antecedent for
|
|
"this", e.g. "this example defines..." --> code
|
|
defines two alternatives for <filename>lib2</filename>, and for each
|
|
one names a prebuilt file. Naturally, there are no sources.
|
|
Instead, the <varname><file></varname> feature is used to
|
|
specify the file name.
|
|
</para>
|
|
<para>
|
|
Once a prebuilt target has been declared, it can be used just like any other target:
|
|
|
|
<programlisting>
|
|
exe app : app.cpp ../util/lib2//lib2 ;
|
|
</programlisting>
|
|
|
|
As with any library target, the alternative selected depends on the
|
|
properties propagated from <filename>lib2</filename>'s dependents.
|
|
If we build the the release and debug versions of <filename>app</filename> will be linked
|
|
with <filename>lib2_release.a</filename> and <filename>lib2_debug.a</filename>, respectively.
|
|
|
|
</para>
|
|
|
|
<para>
|
|
System libraries—those that are automatically found by
|
|
the toolset by searching through some set of predetermined
|
|
paths—should be declared almost like regular ones:
|
|
|
|
<programlisting>
|
|
lib pythonlib : : <name>python22 ;
|
|
</programlisting>
|
|
|
|
We again don't specify any sources, but give a
|
|
<varname>name</varname> that should be passed to the
|
|
compiler. If the gcc toolset were used to link an executable
|
|
target to <filename>pythonlib</filename>, <option>-lpython22</option>
|
|
would appear in the command line (other compilers may use
|
|
different options).
|
|
</para>
|
|
|
|
<para>
|
|
We can also specify where the toolset should look for the library:
|
|
|
|
<programlisting>
|
|
lib pythonlib : : <name>python22 <search>/opt/lib ;
|
|
</programlisting>
|
|
|
|
And, of course, target alternatives can be used in the usual way:
|
|
|
|
<programlisting>
|
|
lib pythonlib : : <name>python22 <variant>release ;
|
|
lib pythonlib : : <name>python22_d <variant>debug ;
|
|
</programlisting>
|
|
|
|
</para>
|
|
|
|
<para>A more advanced use of prebuilt targets is described in <xref
|
|
linkend="bbv2.recipies.site-config"/>.
|
|
|
|
<!-- "xxx is described in a FAQ entry" is confusing for the person
|
|
who is working with a printed manual. -->
|
|
|
|
</para>
|
|
|
|
</section>
|
|
|
|
</chapter>
|
|
|
|
<!--
|
|
Local Variables:
|
|
mode: nxml
|
|
sgml-indent-data:t
|
|
sgml-parent-document:("userman.xml" "chapter")
|
|
sgml-set-face: t
|
|
sgml-omittag:nil
|
|
sgml-shorttag:nil
|
|
sgml-namecase-general:t
|
|
sgml-general-insert-case:lower
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:2
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
-->
|