mirror of
https://github.com/boostorg/build.git
synced 2026-02-16 13:22:11 +00:00
tools/build/v2/doc/architecture.html
File removed. It's pretty old and will only confuse users. tools/build/v2/doc/extending.html File removed, all content is in BoostBook already. [SVN r25609]
This commit is contained in:
@@ -1,366 +0,0 @@
|
||||
<!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 architecture</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="../../../../boost.png"></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,
|
||||
like "#include" statements in C++. The requirements for right dependency
|
||||
scanning mechanism are:</p>
|
||||
|
||||
<ul>
|
||||
<li>Support for different scanning algorithms. C++ and XML have quite
|
||||
different syntax for includes and rules for looking up included
|
||||
files.</li>
|
||||
|
||||
<li>Ability to scan the same file several times. For example, single
|
||||
C++ file can be compiled with different include paths.</li>
|
||||
|
||||
<li>Proper detection of dependencies on generated files.</li>
|
||||
|
||||
<li>Proper detection of dependencies from generated file.</li>
|
||||
</ul>
|
||||
|
||||
<h3>Support for different scanning algorithms</h3>
|
||||
|
||||
<p>Different scanning algorithm are encapsulated by objects called
|
||||
"scanners". Please see the documentation for "scanner" module for more
|
||||
details.</p>
|
||||
|
||||
<h3>Ability to scan the same file several times</h3>
|
||||
|
||||
<p>As said above, it's possible to compile a C++ file twice, with
|
||||
different include paths. Therefore, include dependencies for those
|
||||
compilations can be different. The problem is that bjam does not allow
|
||||
several scans of the same target.</p>
|
||||
|
||||
<p>The solution in Boost.Build is straigtforward. When a virtual target
|
||||
is converted to bjam target (via <tt>virtual-target.actualize</tt>
|
||||
method), we specify the scanner object to be used. The actualize method
|
||||
will create different bjam targets for different scanners.</p>
|
||||
|
||||
<p>All targets with specific scanner are made dependent on target without
|
||||
scanner, which target is always created. This is done in case the target
|
||||
is updated. The updating action will be associated with target without
|
||||
scanner, but if sources for that action are touched, all targets —
|
||||
with scanner and without should be considered outdated.</p>
|
||||
|
||||
<p>For example, assume that "a.cpp" is compiled by two compilers with
|
||||
different include path. It's also copied into some install location. In
|
||||
turn, it's produced from "a.verbatim". The dependency graph will look
|
||||
like:</p>
|
||||
<pre>
|
||||
a.o (<toolset>gcc) <--(compile)-- a.cpp (scanner1) ----+
|
||||
a.o (<toolset>msvc) <--(compile)-- a.cpp (scanner2) ----|
|
||||
a.cpp (installed copy) <--(copy) ----------------------- a.cpp (no scanner)
|
||||
^
|
||||
|
|
||||
a.verbose --------------------------------+
|
||||
|
||||
</pre>
|
||||
|
||||
<h3>Proper detection of dependencies on generated files.</h3>
|
||||
|
||||
<p>This requirement breaks down to the following ones.</p>
|
||||
|
||||
<ol>
|
||||
<li>If when compiling "a.cpp" there's include of "a.h", the "dir"
|
||||
directory is in include path, and a target called "a.h" will be
|
||||
generated to "dir", then bjam should discover the include, and create
|
||||
"a.h" before compiling "a.cpp".</li>
|
||||
|
||||
<li>Since almost always Boost.Build generates targets to a "bin"
|
||||
directory, it should be supported as well. I.e. in the scanario above,
|
||||
Jamfile in "dir" might create a main target, which generates "a.h". The
|
||||
file will be generated to "dir/bin" directory, but we still have to
|
||||
recornize the dependency.</li>
|
||||
</ol>
|
||||
|
||||
<p>The first requirement means that when determining what "a.h" means,
|
||||
when found in "a.cpp", we have to iterate over all directories in include
|
||||
paths, checking for each one:</p>
|
||||
|
||||
<ol>
|
||||
<li>If there's file "a.h" in that directory, or</li>
|
||||
|
||||
<li>If there's a target called "a.h", which will be generated to that
|
||||
directory.</li>
|
||||
</ol>
|
||||
|
||||
<p>Classic Jam has built-in facilities for point (1) above, but that's
|
||||
not enough. It's hard to implement the right semantic without builtin
|
||||
support. For example, we could try to check if there's targer called
|
||||
"a.h" somewhere in dependency graph, and add a dependency to it. The
|
||||
problem is that without search in include path, the semantic may be
|
||||
incorrect. 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 header on platforms where native
|
||||
one is included.</p>
|
||||
|
||||
<p>There are two design choices for builtin support. 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 used for some time. The problem however is:
|
||||
what include paths should be used when scanning header.h? The second
|
||||
alternative was suggested by Matt Armstrong. It has similiar effect: add
|
||||
targets which depend on <scanner1>header.h will also depend on
|
||||
<d2>header.h. But now we have two different target with two
|
||||
different scanners, and those targets can be scanned independently. The
|
||||
problem of first alternative is avoided, so the second alternative is
|
||||
implemented now.
|
||||
|
||||
<p>The second sub-requirements is that targets generated to "bin"
|
||||
directory are handled as well. Boost.Build implements semi-automatic
|
||||
approach. When compiling C++ files the process is:</p>
|
||||
|
||||
<ol>
|
||||
<li>The main target to which compiled file belongs is found.</li>
|
||||
|
||||
<li>All other main targets that the found one depends on are found.
|
||||
Those include main target which are used as sources, or present as
|
||||
values of "dependency" features.</li>
|
||||
|
||||
<li>All directories where files belonging to those main target will be
|
||||
generated are added to the include path.</li>
|
||||
</ol>
|
||||
|
||||
<p>After this is done, dependencies are found by the approach explained
|
||||
previously.</p>
|
||||
|
||||
<p>Note that if a target uses generated headers from other main target,
|
||||
that main target should be explicitly specified as dependency property.
|
||||
It would be better to lift this requirement, but it seems not very
|
||||
problematic in practice.</p>
|
||||
|
||||
<p>For target types other than C++, adding of include paths must be
|
||||
implemented anew.</p>
|
||||
|
||||
<h3>Proper detection of dependencies from generated files</h3>
|
||||
|
||||
<p>Suppose file "a.cpp" includes "a.h" and both are generated by some
|
||||
action. Note that classic jam has two stages. In first stage dependency
|
||||
graph graph is build and actions which should be run are determined. In
|
||||
second stage the actions are executed. Initially, neither file exists, so
|
||||
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 dependency
|
||||
is not shown). Say during building we've tried to create A, then tried to
|
||||
create C and successfully created C.
|
||||
|
||||
<p>In that case, the set of includes in C might well have changed. We do
|
||||
not bother to detect precisely which includes were added or removed.
|
||||
Instead we create another internal node C-includes-2. Then we determine
|
||||
what actions should be run to update the target. In fact this mean that
|
||||
we perform logic of first stage while already executing stage.</p>
|
||||
|
||||
<p>After actions for C-includes-2 are determined, we add C-includes-2 to
|
||||
the list of A's dependents, and stage 2 proceeds as usual. Unfortunately,
|
||||
we can't do the same with target B, since when it's not visited, C target
|
||||
does not know B depends on it. So, we add a flag to C which tells and it
|
||||
was rescanned. When visiting B target, the flag is notices and
|
||||
C-includes-2 will be added to the list of B's dependencies.</p>
|
||||
|
||||
<p>Note also that internal nodes are sometimes updated too. Consider this
|
||||
dependency graph:</p>
|
||||
<pre>
|
||||
a.o ---> a.cpp
|
||||
a.cpp-includes --> a.h (scanned)
|
||||
a.h-includes ------> a.h (generated)
|
||||
|
|
||||
|
|
||||
a.pro <-------------------------------------------+
|
||||
</pre>
|
||||
|
||||
<p>Here, out handling of generated headers come into play. Say that a.h
|
||||
exists but is out of date with respect to "a.pro", then "a.h (generated)"
|
||||
and "a.h-includes" will be marking for updating, but "a.h (scanned)"
|
||||
won't be marked. We have to rescan "a.h" file after it's created, but
|
||||
since "a.h (generated)" has no scanner associated with it, it's only
|
||||
possible to rescan "a.h" after "a.h-includes" target was updated.</p>
|
||||
|
||||
<p>Tbe above consideration lead to decision that we'll rescan a target
|
||||
whenever it's updated, no matter if this target is internal or not.</p>
|
||||
|
||||
<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>
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
<!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 extender 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="../../../../boost.png"></a></p>
|
||||
|
||||
<h1>Boost.Build v2 extender manual<br class="clear">
|
||||
</h1>
|
||||
<hr>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#introduction">Introduction</a></dt>
|
||||
|
||||
<dt><a href="#target_types">Target types</a></dt>
|
||||
|
||||
<dt><a href="#tools">Tools</a></dt>
|
||||
|
||||
<dt><a href="#main_target_rules">Main target rules</a></dt>
|
||||
|
||||
<dt><a href="#scanners">Scanners</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2 id="introduction">Introduction</h2>
|
||||
|
||||
<p>This document explains how to extend Boost.Build to accomodate your
|
||||
local requirements. Let's start with quite simple, but realistic
|
||||
example.</p>
|
||||
|
||||
<p>Say you're writing an application which generates C++ code. If you
|
||||
ever did this, you know that it's not nice. Embedding large portions of
|
||||
C++ code in string literals is very awkward. A much better solution
|
||||
is:</p>
|
||||
|
||||
<ol>
|
||||
<li>Write the template of the code to be generated, leaving
|
||||
placeholders at the points which will change</li>
|
||||
|
||||
<li>Access the template in your application and replace placeholders
|
||||
with appropriate text.</li>
|
||||
|
||||
<li>Write the result.</li>
|
||||
</ol>
|
||||
|
||||
<p>It's quite easy to archive. You write special verbatim files, which
|
||||
are just C++, except that the very first line of the file gives a name of
|
||||
variable that should be generated. A simple tool is created which takes
|
||||
verbatim file and creates a cpp file with a single char* variable, which
|
||||
name is taken from the first line of verbatim file, and which value is
|
||||
properly quoted content of the verbatim file.</p>
|
||||
|
||||
<p>Let's see what Boost.Build can do.</p>
|
||||
|
||||
<p>First off, Boost.Build has no idea about "verbatim files". So, you
|
||||
must register a new type. The following code does it:</p>
|
||||
<pre>
|
||||
import type ;
|
||||
type.register VERBATIM : verbatim ;
|
||||
|
||||
</pre>
|
||||
|
||||
<p>The first parameter to 'type.register' gives the name of declared
|
||||
type. By convention, it's uppercase. The second parameter is suffix for
|
||||
this type. So, if Boost.Build sees "code.verbatim" in the list of
|
||||
sources, it knows that it's of type <tt>VERBATIM</tt>.</p>
|
||||
|
||||
<p>Lastly, you need a tool to convert verbatim files to C++. Say you've
|
||||
sketched such a tool in Python. Then, you have to inform Boost.Build
|
||||
about the tool. The Boost.Build concept which represents a tool is
|
||||
<em>generator</em>.</p>
|
||||
|
||||
<p>First, you say that generator 'inline-file' is able to convert
|
||||
VERBATIM type into C++:</p>
|
||||
<pre>
|
||||
import generators ;
|
||||
generators.register-standard verbatim.inline-file : VERBATIM : CPP ;
|
||||
|
||||
</pre>
|
||||
|
||||
<p>Second, you must specify the commands to be run to actually perform
|
||||
convertion:</p>
|
||||
<pre>
|
||||
actions inline-file
|
||||
{
|
||||
"./inline-file.py" $(<) $(>)
|
||||
}
|
||||
|
||||
</pre>
|
||||
<!-- We use verbatim.inline-file in one place and just inline-file in
|
||||
another. Is this confusing for user?
|
||||
-->
|
||||
|
||||
<p>Now, we're ready to tie it all together. Put all the code above in
|
||||
file "verbatim.jam", add "import verbatim ;" to "project-root.jam", and
|
||||
it's possible to write the following in Jamfile:</p>
|
||||
<pre>
|
||||
exe codegen : codegen.cpp class_template.verbatim usage.verbatim ;
|
||||
|
||||
</pre>
|
||||
The verbatim files will be automatically converted into C++ and linked
|
||||
it.
|
||||
|
||||
<p>The complete code is available in <a href=
|
||||
"../example/customization">example/customization</a>
|
||||
directory.</p>
|
||||
|
||||
<h2 id="target_types">Target types</h2>
|
||||
|
||||
<h2 id="tools">Tools</h2>
|
||||
|
||||
<h2 id="main_target_rules">Main target rules</h2>
|
||||
|
||||
<h2 id="scanners">Scanners</h2>
|
||||
<hr>
|
||||
|
||||
<p class="revision">Last modified: Jule 3, 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>
|
||||
|
||||
Reference in New Issue
Block a user