mirror of
https://github.com/boostorg/build.git
synced 2026-02-12 12:02:24 +00:00
304 lines
13 KiB
HTML
304 lines
13 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
|
"http://www.w3.org/TR/html4/strict.dtd">
|
|
|
|
<html>
|
|
<head>
|
|
<meta name="generator" content=
|
|
"HTML Tidy for Linux/x86 (vers 1st April 2002), see www.w3.org">
|
|
<!--tidy options: -i -wrap 78 -->
|
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
|
<link rel="stylesheet" type="text/css" href="../../boost.css">
|
|
|
|
<title>Boost.Build v2 user manual</title>
|
|
|
|
<style type="text/css">
|
|
hr { color: black }
|
|
p.revision { text-align: right; font-style: italic }
|
|
pre.code { margin-left: 2em }
|
|
pre.output { margin-left: 2em }
|
|
img.banner { border: 0; float: left }
|
|
h1 { text-align: right }
|
|
br.clear { clear: left }
|
|
div.alert { color: red }
|
|
table { align: center; border: thin; }
|
|
</style>
|
|
</head>
|
|
<!-- Things yet to document:
|
|
- build request, build request expansion and directly requested targets
|
|
- conditional properties
|
|
-->
|
|
|
|
<body>
|
|
<p><a href="../../index.htm"><img class="banner" height="86" width="277"
|
|
alt="C++ Boost" src="c++boost.gif"></a></p>
|
|
|
|
<h1>Boost.Build v2 architecture<br class="clear">
|
|
</h1>
|
|
<hr>
|
|
|
|
<div class="alert">
|
|
<p>This document is work-in progress. Don't expect much from it
|
|
yet.</p>
|
|
</div>
|
|
|
|
<dl class="page-index">
|
|
<dt><a href="#dependencies">Dependency scanning</a></dt>
|
|
</dl>
|
|
<hr>
|
|
|
|
<h2><a name="targets">Targets</a></h2>
|
|
|
|
<p>There are two user-visible kinds of targets in Boost.Build. First are
|
|
"abstract" — they correspond to things declared by user, for
|
|
example, projects and executable files. The primary thing about abstract
|
|
target is that it's possible to request them to be build with a
|
|
particular values of some properties. Each combination of properties may
|
|
possible yield different set of real file, so abstract target do not have
|
|
a direct correspondence with files.</p>
|
|
|
|
<p>File targets, on the contary, are associated with concrete files.
|
|
Dependency graphs for abstract targets with specific properties are
|
|
constructed from file targets. User has no was to create file targets,
|
|
however it can specify rules that detect file type for sources, and also
|
|
rules for transforming between file targets of different types. That
|
|
information is used in constructing dependency graph, as desribed in the
|
|
<a href="#generators">next section</a>. <b>Note:</b>File targets are not
|
|
the same as targets in Jam sense; the latter are created from file
|
|
targets at the latest possible moment. <b>Note:</b>"File target" is a
|
|
proposed name for what we call virtual targets. It it more understandable
|
|
by users, but has one problem: virtual targets can potentially be
|
|
"phony", and not correspond to any file.</p>
|
|
|
|
<h2 id="dependency_scanning">Dependency scanning</h2>
|
|
|
|
<p>Dependency scanning is the process of finding implicit dependencies
|
|
due to "include" statements and similar things. It has to take into
|
|
account two things:</p>
|
|
|
|
<ul>
|
|
<li>Whether includes in a particular file need to be taken into account
|
|
depends on actions that use that file. For example, if the action is
|
|
"copy file", then includes should be ignored. Another example is when a
|
|
file is compiled with two different include paths on different
|
|
toolsets.</li>
|
|
|
|
<li>It is possible to include generated header. In which case, it may
|
|
not yet exist at the time when we scan dependencies.</li>
|
|
</ul>
|
|
|
|
<p>Dependency scanning is implemented by objects called scanners. See
|
|
documentation for the "scanner" module to detail.</p>
|
|
|
|
<p>Regarding the first problem, we really have no choice. We can't treat
|
|
the same actual target differently depending on from where it is used.
|
|
Therefore, when handling of includes differers depending on actions, we
|
|
have to duplicate targets and assign different properties to it.</p>
|
|
|
|
<p>For the reason, when actualizing a virtual target we optionally pass
|
|
the needed scanner to the "virtual-target.actualize" method. When no
|
|
scanner is passed, a new actual target is created, with it's dependencies
|
|
and updating actions set accordingly. When a particular scanner is
|
|
specified, a new actual target is created. That target will depend on
|
|
target created without scanner. In effect, this will allow to use
|
|
different scanners for the same file.</p>
|
|
|
|
<h3>Generated sources</h3>
|
|
Let me explain what I find the right semantic, first without any
|
|
subvariants. We have a target "a.cpp" which includes "a_parser.h", we
|
|
have to search through all include directories, checking:
|
|
|
|
<ol>
|
|
<li>If there's such file there, or</li>
|
|
|
|
<li>If there's a target of the same name, bound to that dir via LOCATE
|
|
variable.</li>
|
|
</ol>
|
|
Jam allows to do 1 via SEARCH variable, but that's not enough. Why can't
|
|
we do simpler: first check if there's target of the same name? I.e.
|
|
including of "a_parser.h" will already pick generated "a_parser.h",
|
|
regardless of search paths? Hmm... just because there's no reason to
|
|
assume that. For example, one can have an action which generated some
|
|
"dummy" header, for system which don't have the native one. Naturally, we
|
|
don't want to depend on that generated headers. To implement proposed
|
|
semantic we'd need builtin support.
|
|
|
|
<p>There are two design choices. Suppose we have files a.cpp and b.cpp,
|
|
and each one includes header.h, generated by some action. Dependency
|
|
graph created by classic jam would look like:</p>
|
|
<pre>
|
|
a.cpp -----> <scanner1>header.h [search path: d1, d2, d3]
|
|
|
|
|
|
<d2>header.h --------> header.y
|
|
[generated in d2]
|
|
|
|
b.cpp -----> <scanner2>header.h [ search path: d1, d2, d4]
|
|
</pre>
|
|
In this case, Jam thinks all header.h target are not realated. The right
|
|
dependency graph might be:
|
|
<pre>
|
|
a.cpp ----
|
|
\
|
|
\
|
|
>----> <d2>header.h --------> header.y
|
|
/ [generated in d2]
|
|
/
|
|
b.cpp ----
|
|
</pre>
|
|
or
|
|
<pre>
|
|
a.cpp -----> <scanner1>header.h [search path: d1, d2, d3]
|
|
|
|
|
(includes)
|
|
V
|
|
<d2>header.h --------> header.y
|
|
[generated in d2]
|
|
^
|
|
(includes)
|
|
|
|
|
b.cpp -----> <scanner2>header.h [ search path: d1, d2, d4]
|
|
</pre>
|
|
The first alternative was use for some time. The problem however is: what
|
|
include paths should be used when scanning header.h? Originally, two
|
|
different sets of include paths were used. The second alternative does
|
|
not have this problem, so it's implemented now.
|
|
|
|
<h3>Includes between generated sources</h3>
|
|
|
|
<p>Suppose file "a.cpp" includes "a.h" and both are generated by some
|
|
action. Initially, neither file exists, so when classic jam constructs
|
|
dependency graph, the include is not found. As the result, jam might
|
|
attempt to compile a.cpp before creating a.h, and compilation will
|
|
fail.</p>
|
|
|
|
<p>The solution in Boost.Jam is to perform additional dependency scans
|
|
after targets are updated. This break separation between build stages in
|
|
jam — which some people consider a good thing — but I'm not
|
|
aware of any better solution.</p>
|
|
|
|
<p>In order to understand the rest of this section, you better read some
|
|
details about jam dependency scanning, available <a href=
|
|
"http://public.perforce.com:8080/@md=d&cd=//public/jam/src/&ra=s&c=kVu@//2614?ac=10">
|
|
at this link</a>.</p>
|
|
|
|
<p>Whenever a target is updated, Boost.Jam rescans it for includes.
|
|
Consider this graph, created before any actions are run.</p>
|
|
<pre>
|
|
A -------> C ----> C.pro
|
|
/
|
|
B --/ C-includes ---> D
|
|
|
|
</pre>
|
|
Both A and B have dependency on C and C-includes (the latter is not
|
|
shown). Say during building we've tried to create A, then tried to create
|
|
C and successfully created C. The B node wasn't seen yet. The C target is
|
|
rescanned, which creates new internal node. If we had those includes from
|
|
the start, we'd add this node to the list of A dependencies and B
|
|
dependencies. As it stands, we need to add it now.
|
|
|
|
<p>We determine what should be done with C-includes-2, add C-includes-2
|
|
to A's dependencies, and build the target. Unfortunately, we cannot do
|
|
the same with B, since we don't know that B is parent of C until we visit
|
|
B. So we add a special flag to C telling that it was rescanned. When we
|
|
process B, we'll add new dependency node to B's dependencies. this point
|
|
of time the target is requested by some parents. So parents were not yet
|
|
visited. Both visited and unvisited parents have What shall we do when
|
|
using subvariants. For user, subvariants must be more or less
|
|
transparent. If without subvariant a header was generated to a certain
|
|
directory, everything must work. Suppose that file a.cpp belongs to a
|
|
dependency graph of main target a. Include paths are</p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
"/usr/include" "/home/t" "."
|
|
</pre>
|
|
</blockquote>
|
|
We start by finding all places where headers that are part of a's
|
|
dependency graph are generated. We insert those places to the include
|
|
paths, immediately after ".". For example, we might end with:
|
|
|
|
<blockquote>
|
|
<pre>
|
|
"/usr/include" "/home/t" "." "build"
|
|
</pre>
|
|
</blockquote>
|
|
As a result:
|
|
|
|
<ol>
|
|
<li>File "a.cpp" will be correctly compiled. Note that it's already
|
|
necessary to adjust paths to ensure this. We'll have to add target
|
|
paths for all generated headers, because determining the exact set of
|
|
additional include path for each source -- i.e the set of headers that
|
|
it uses --- will be hard.</li>
|
|
|
|
<li>With the proposed SEARCH_FOR_TARGET rule, dependency on generated
|
|
header will work magically --- it would find the "a_parser.h" target
|
|
bound via LOCATE_TARGET to "build" and we'll call INCLUDE on that found
|
|
target, instread of creating a completely unrelated one.</li>
|
|
</ol>
|
|
|
|
<div class="alert">
|
|
The remainder of this document is not indended to be read at all. This
|
|
will be rearranged in future.
|
|
</div>
|
|
|
|
<h4>File targets</h4>
|
|
As described above, file targets corresponds to files that Boost.Build
|
|
manages. User's may be concerned about file targets in three ways: when
|
|
declaring file target types, when declaring transformations between
|
|
types, and when determining where file target will be placed. File
|
|
targets can also be connected with actions, that determine how the target
|
|
is created. Both file targets and actions are implemented in the
|
|
<tt>virtual-target</tt> module.
|
|
|
|
<h5>Types</h5>
|
|
A file target can be given a file, which determines what transformations
|
|
can be applied to the file. The <tt>type.register</tt> rule declares new
|
|
types. File type can also be assigned a scanner, which is used to find
|
|
implicit dependencies. See <a href="#dependency_scanning">dependency
|
|
scanning</a> below.
|
|
|
|
<h4>Target paths</h4>
|
|
|
|
<p>To distinguish targets build with different properties, they are put
|
|
in different directories. Rules for determining target paths are given
|
|
below:</p>
|
|
|
|
<ol>
|
|
<li>All targets are placed under directory corresponding to the project
|
|
where they are defined.</li>
|
|
|
|
<li>Each non free, non incidental property cause an additional element
|
|
to be added to the target path. That element has the form
|
|
<tt><feature-name>-<feature-value></tt> for ordinary
|
|
features and <tt><feature-value></tt> for implicit ones. [Note
|
|
about composite features].</li>
|
|
|
|
<li>If the set of free, non incidental properties is different from the
|
|
set of free, non incidental properties for the project in which the
|
|
main target that uses the target is defined, a part of the form
|
|
<tt>main_target-<name></tt> is added to the target path.
|
|
<b>Note:</b>It would be nice to completely track free features also,
|
|
but this appears to be complex and not extremely needed.</li>
|
|
</ol>
|
|
|
|
<p>For example, we might have these paths:</p>
|
|
<pre>
|
|
debug/optimization-off
|
|
debug/main-target-a
|
|
|
|
</pre>
|
|
<hr>
|
|
|
|
<p class="revision">Last modified: June 30, 2003</p>
|
|
|
|
<p>© Copyright Vladimir Prus 2002-2003. Permission to copy, use,
|
|
modify, sell and distribute this document is granted provided this
|
|
copyright notice appears in all copies. This document is provided ``as
|
|
is'' without express or implied warranty, and with no claim as to its
|
|
suitability for any purpose.</p>
|
|
<!-- sf logo -->
|
|
</body>
|
|
</html>
|
|
|