diff --git a/v2/doc/Jamfile.v2 b/v2/doc/Jamfile.v2 index 16c9efe48..43adbdacf 100644 --- a/v2/doc/Jamfile.v2 +++ b/v2/doc/Jamfile.v2 @@ -1,3 +1,3 @@ project tools/build/v2/doc ; -boostbook userman : userman.xml ; +boostbook userman : src/userman.xml ; diff --git a/v2/doc/html/images/blank.png b/v2/doc/html/images/blank.png new file mode 100644 index 000000000..764bf4f0c Binary files /dev/null and b/v2/doc/html/images/blank.png differ diff --git a/v2/doc/html/images/caution.png b/v2/doc/html/images/caution.png new file mode 100644 index 000000000..5b7809ca4 Binary files /dev/null and b/v2/doc/html/images/caution.png differ diff --git a/v2/doc/html/images/draft.png b/v2/doc/html/images/draft.png new file mode 100644 index 000000000..0084708c9 Binary files /dev/null and b/v2/doc/html/images/draft.png differ diff --git a/v2/doc/html/images/home.png b/v2/doc/html/images/home.png new file mode 100644 index 000000000..cbb711de7 Binary files /dev/null and b/v2/doc/html/images/home.png differ diff --git a/v2/doc/html/images/important.png b/v2/doc/html/images/important.png new file mode 100644 index 000000000..12c90f607 Binary files /dev/null and b/v2/doc/html/images/important.png differ diff --git a/v2/doc/html/images/next.png b/v2/doc/html/images/next.png new file mode 100644 index 000000000..45835bf89 Binary files /dev/null and b/v2/doc/html/images/next.png differ diff --git a/v2/doc/html/images/note.png b/v2/doc/html/images/note.png new file mode 100644 index 000000000..d0c3c645a Binary files /dev/null and b/v2/doc/html/images/note.png differ diff --git a/v2/doc/html/images/prev.png b/v2/doc/html/images/prev.png new file mode 100644 index 000000000..cf24654f8 Binary files /dev/null and b/v2/doc/html/images/prev.png differ diff --git a/v2/doc/html/images/tip.png b/v2/doc/html/images/tip.png new file mode 100644 index 000000000..5c4aab3bb Binary files /dev/null and b/v2/doc/html/images/tip.png differ diff --git a/v2/doc/html/images/toc-blank.png b/v2/doc/html/images/toc-blank.png new file mode 100644 index 000000000..6ffad17a0 Binary files /dev/null and b/v2/doc/html/images/toc-blank.png differ diff --git a/v2/doc/html/images/toc-minus.png b/v2/doc/html/images/toc-minus.png new file mode 100644 index 000000000..abbb020c8 Binary files /dev/null and b/v2/doc/html/images/toc-minus.png differ diff --git a/v2/doc/html/images/toc-plus.png b/v2/doc/html/images/toc-plus.png new file mode 100644 index 000000000..941312ce0 Binary files /dev/null and b/v2/doc/html/images/toc-plus.png differ diff --git a/v2/doc/html/images/up.png b/v2/doc/html/images/up.png new file mode 100644 index 000000000..07634de26 Binary files /dev/null and b/v2/doc/html/images/up.png differ diff --git a/v2/doc/html/images/warning.png b/v2/doc/html/images/warning.png new file mode 100644 index 000000000..1c33db8f3 Binary files /dev/null and b/v2/doc/html/images/warning.png differ diff --git a/v2/doc/html/reference.css b/v2/doc/html/reference.css new file mode 100644 index 000000000..33ef65625 --- /dev/null +++ b/v2/doc/html/reference.css @@ -0,0 +1,76 @@ +th +{ + font-weight: bold; + text-align: center; +} + +.title +{ + font-weight: bold; + font-size: 2pc; + font-family: Times New Roman; + margin-bottom: 1pc; + text-align: center; +} + +.toc +{ + margin-left: 5%; + margin-right: 5%; + margin-bottom: 0pc; + width: 50%; +} + +.programlisting +{ + margin-left: 3pc; + width: 50%; +} + +.computeroutput +{ + font-family: Lucida Console; + font-size: 80%; +} + +.table +{ + text-align: center; + margin-bottom: 1pc; +} + +@media screen +{ + a{ color: blue; } + + th, .title + { + background-color: lightskyblue; + } + + .section-title + { + background-color: #EEE; + } + + .programlisting + { + background-color: #EED; + border: 0.1em ridge cyan; + padding: 1pc; + } + + .toc + { + border: 0.2em ridge lightcoral; + padding: 0.5pc; + background-color: #DDD; + } +} + +@media print +{ + a{ color: black; } +} + + diff --git a/v2/doc/src/advanced.xml b/v2/doc/src/advanced.xml new file mode 100644 index 000000000..d47216681 --- /dev/null +++ b/v2/doc/src/advanced.xml @@ -0,0 +1,831 @@ + + + + + Advanced + + This section will document + mostly high-level view of Boost.Build, mentioning appropriate + modules and rules. The on-line help system must be used to obtain + low-level documentation (see the help option). + +
+ Overview + + The most fundemental entity in Boost.Build is main + target. This is object that user want to construct from + sources and keep up to date with regard to those sources. Typical + examples of main targets are executable files and libraries. + + Main targets are grouped in projects. Their main + purpose is organization: related targets placed in one project, + can then be built together, or share some definitions. + + Main targets and projects are created as the result of reading + one or several Jamfiles. Each Jamfile is a file written in + Boost.Jam interpreted language, and typically contains calls to + functions provided by Boost.Build, which create main targets of + needed type, declare project attributes and access other + projects. The full list of functions provided by Boost.Build is + described below. + Of course, user can create his own functions, or it can directly + access Boost.Build internals from Jamfile, if builtin facilities are + not sufficient. + + Each main target, or project can be built in a number of ways, + say with optimization or without. We'll call such entities + "metatargets". To make Boost.Build produce any real targets, user + issues build request, + which specifies metatargets to be built, and properties to be + used. + + The properties are just (name,value) pairs that + describe various aspects of constructed objects, for example: + +<optimization>full <inlining>off + + + Given the built request, Boost.Build figures out the targets + needed for requested metatargets with requested properties, how + they can be created, and whether exising files can be reused. It + finally issues command to create needed files, automatically + converting properties into appropricate command line options. + +
+ +
+ Your first project and roadmap + + Creating your first project requires three steps: + + + Create an empty file called "Jamfile" + + + + Create an empty file called "project-root.jam" + + + + + Either set your BOOST_BUILD_PATH environment + variant to Boost.Build root, or create a "boost-build.jam" file + with the following content: + + +boost-build /path/to/boost.build ; + + + + + + + After that, you can run the "bjam" command in the directory + where you've created the files. Surely, it won't do anything, but + it will run without error, at least. Your next steps might + be: + + + + + Adding new main targets to the "Jamfile" file. The basic + syntax for declaring a main target is described below, and all builtin functions for + declaring main targets are listed. + + + + + + Creating subprojects. Create a directory, put new Jamfile + there, and move some main targets to that Jamfile, or declare + new ones. The projects + reference will help with this part. + + + + + + Customizing Boost.Build for your needs. You might have + additional tools you want to run, or just want different + extension for some file. The extender manual is waiting for + you. + + + + +
+ +
+ Main targets + + + Main target is a user-defined named + entity which can be build, for example a named executable file. + Declaring a main target is usually done using one of main target functions. + The user can also declare custom main target + function. + + Most main targets rules in Boost.Build use similiar + syntax: + + +function-name main-target-name + : sources + : requirements + : default-build + : usage-requirements + ; + + + + + + "main-target-name" is the name used to request the target + on command line and to use it from other main targets. Main + target name may contain alphanumeric characters and symbols '-' + and '_'; + + + + + + "sources" is the list of source files and other main + targets that must be combined. If source file is specified + using relative path, it's considered to be relative to the + source directory of the project where the path is used. See the + project rule + for information how to change source directory. + + + + + + "requirements" is the list of properties that must always + be present when this main target is built. + + + + + + "default-build" is the list of properties that will be used + unless some other value of the same feature is already + specified. + + + + + + "usage-requirements" is the list of properties that will be + propagated to all main targets that use this one, i.e. to all + dependedents. + + + + + Some main target rules have shorter list of parameters, and + you should consult their documentation for details. + + Building of the same main target can differ greatly from + platform to platform. For example, you might have different list + of sources for different compilers. Therefore it is possible to + invoke main target rules several times for a single main target. + For example: + + +exe a : a_gcc.cpp : <toolset>gcc ; +exe a : a.cpp ; + + + + Each call to the 'exe' rule defines a new main target + alternative for the main target a. + In this case, the first alternative will be used for the + gcc toolset, while the second alternative will + be used in other cases. See below for + details. + + + Sometime a main target is really needed only by some other + main target. E.g. a rule that declared test-suite uses a main + target that represent test, but those main targets are rarely + needed by themself. + + It possible to declare target inline, i.e. the "sources" + parameter may include call to other main rules. For example: + + +exe hello : hello.cpp + [ obj helpers : helpers.cpp : <optimization>off ] ; + + + +Will cause "helpers.cpp" to be always compiled without +optimization. It's possible to request main targets declared +inline, but since they are considered local, they are renamed to +"parent-main-target_name..main-target-name". In the example above, +to build only helpers, one should run "bjam hello..helpers". + + +
+ +
+ Projects + + Boost.Build considers every software it build as organized + into projects — modules which declare targets. + Projects are organized in a hierarchical structure, so each + project may have a single parent project and a number of + subprojects. + + Most often, projects are created as result of loading + Jamfile — files which are specially meant to + describe projects. Boost.Build will implicitly load Jamfile in + the invocation directory, and all Jamfiles referred by the first + one, creating the hierarchy of projects. + + The exact name of file that describes project is configurable. + By default, it's Jamfile, but can be changed by setting + global variables JAMFILE, for example in + boost-build.jam file. The value of the variable is a + list of regex patterns that are used when searching for Jamfile + in a directory. + + Every Boost.Build modules can decide to act as project and be + able to declare targets. For example, the + site-config.jam module can declare libraries + available on a given host, as described here. + + There are three things that can be put in Jamfile: + declarations of main targets, calls to a number of predefined + rules, and arbitrary user code. The predefined rules are listed + below: + + + + <tgroup cols="2"> + <thead> + <row> + <entry>Rule</entry> + + <entry>Semantic</entry> + </row> + </thead> + + <tbody> + <row> + <entry><link linkend= + "bbv2.advanced.projects.attributes.projectrule">project</link> + </entry> + + <entry>Define project attributes.</entry> + </row> + + <row> + <entry><link linkend= + "bbv2.advanced.projects.relationships.useprojectrule">use-project</link></entry> + + <entry>Make another project known.</entry> + </row> + + <row> + <entry><link linkend= + "bbv2.advanced.projects.relationships.buildprojectrule">build-project</link></entry> + + <entry>Build another project when this one is built.</entry> + </row> + + <row> + <entry><link linkend= + "bbv2.reference.buildprocess.explict">explicit</link></entry> + + <entry>States that the target should be built only by explicit + request.</entry> + </row> + + <row> + <entry>glob</entry> + + <entry>Takes a list of wildcards, and returns the list of files + which match any of the wildcards.</entry> + </row> + </tbody> + </tgroup> + </table> + + <para>Each project is also associated with <emphasis>project root</emphasis>. + That's a root for a tree of projects, which specifies some global + properties.</para> + + <section id="bbv2.advanced.projects.root"> + <title>Project root + + + Project root for a projects is the nearest parent directory + which contains a file called + project-root.jam. That file defines + certain properties which apply to all projects under project + root. It can: + + + + + configure toolsets, via call to toolset.using + + + + + + refer to other projects, via the use-project + rule + + + + + + declare constants, via the constant and + path-constant rules. + + + + + + + To facilitate declaration of simple projects, Jamfile and + project-root can be merged together. To achieve this effect, the + project root file should call the project rule. The + semantic is precisely the same as if the call was made in + Jamfile, except that project-root.jam will start serve as + Jamfile. The Jamfile in the directory of project-root.jam will be + ignored, and project-root.jam will be able to declare main + targets as usual. + + + +
+ Project attributes + + For each project, there are several attributes. + + Project id is a short way to denote a project, as + opposed to the Jamfile's pathname. It is a hierarchical path, + unrelated to filesystem, such as "boost/thread". Target references make use of project ids to + specify a target. + + Source location specifies the directory where sources + for the project are located. + + Project requirements are requirements that apply to + all the targets in the projects as well as all subprojects. + + Default build is the build request that should be + used when no build request is specified explicitly. + + + The default values for those attributes are + given in the table below. In order to affect them, Jamfile may + call the project rule. The rule has this + syntax: + + +project id : <attributes> ; + + + +Here, attributes is a sequence of (attribute-name, +attribute-value) pairs. The list of attribute names along with its +handling is also shown in the table below. For example, it it +possible to write: + + + +project tennis + : requirements <threading>multi + : default-build release + ; + + +
+ + <tgroup cols="4"> + <thead> + <row> + <entry>Attribute</entry> + + <entry>Name for the 'project' rule</entry> + + <entry>Default value</entry> + + <entry>Handling by the 'project' rule</entry> + </row> + </thead> + + <tbody> + + <row> + <entry>Project id</entry> + + <entry>none</entry> + + <entry>none</entry> + + <entry>Assigned from the first parameter of the 'project' rule. + It is assumed to denote absolute project id.</entry> + </row> + + <row> + <entry>Source location</entry> + + <entry><literal>source-location</literal></entry> + + <entry>The location of jamfile for the project</entry> + + <entry>Sets to the passed value</entry> + </row> + + <row> + <entry>Requirements</entry> + + <entry><literal>requirements</literal></entry> + + <entry>The parent's requirements</entry> + + <entry>The parent's requirements are refined with the passed + requirement and the result is used as the project + requirements.</entry> + </row> + + <row> + <entry>Default build</entry> + + <entry><literal>default-build</literal></entry> + + <entry>none</entry> + + <entry>Sets to the passed value</entry> + </row> + + <row> + <entry>Build directory</entry> + + <entry><literal>build-dir</literal></entry> + + <entry>If parent has a build dir set, the value of it, joined + with the relative path from parent to the current project. + Otherwise, empty</entry> + + <entry>Sets to the passed value, interpreted as relative to the + project's location.</entry> + </row> + </tbody> + </tgroup> + </table> + </section> + + <section id="bbv2.advanced.projects.relationships"> + <title>Project relationship + + There are three kinds of project relationships. + + First is parent-child. This relationship is established + implicitly: parent directories of a project are searched, and the + first found Jamfile is assumed to define the parent project. The + parent-child relationship affects only attribute values for the + child project. + + + Second is build relationship. Some + project may request to recursively build other projects. Those + project need not be child projects. The build-project + rule is used for that: + + build-project src ; + + + + The third kind is the 'use' + relationship. In means that one project uses targets from + another. It is possible to just refer to target in other projects + using target id. However, if target id uses project id, it is + required that the project id is known. The + use-project + rule is employed to guarantee that. + + + +use-project ( id : location ) + + + +It loads the project at the specified location, which makes +its project id available in the project which invokes the rule. It +is required that the id parameter passed to the +use-project rule be equal to the id that the loaded +project declared. At this moment, the id paremeter +should be absolute project id. + + + + +
+ Target identifiers and references + + Target identifier is used to denote a + target. The syntax is: + + +target-id -> (project-id | target-name | file-name ) + | (project-id | directory-name) "//" target-name +project-id -> path +target-name -> path +file-name -> path +directory-name -> path + + + +This grammar allows some elements to be recognized as either + + + + + project id (at this point, all project ids start with slash). + + + + + + name of target declared in current Jamfile (note that target + names may include slash). + + + + + + a regular file, denoted by absolute name or name relative to + project's sources location. + + + + + To determine the real meaning a check is made if project-id + by the specified name exists, and then if main target of that + name exists. For example, valid target ids might be: + + +a -- target in current project +lib/b.cpp -- regular file +/boost/thread -- project "/boost/thread" +/home/ghost/build/lr_library//parser -- target in specific project + + + + + Rationale:Target is separated from project by special + separator (not just slash), because: + + + + + It emphasises that projects and targets are different things. + + + + + + It allows to have main target names with slashes. + + + + + + + + Target reference is used to + specify a source target, and may additionally specify desired + properties for that target. It has this syntax: + + +target-reference -> target-id [ "/" requested-properties ] +requested-properties -> property-path + + + +For example, + + +exe compiler : compiler.cpp libs/cmdline/<optimization>space ; + + +would cause the version of cmdline library, +optimized for space, to be linked in even if the +compiler executable is build with optimization for +speed. + +
+
+ Builtin facilities + +
+ Main targets + + + exe + + + + Creates a regular executable file. Sources must be either + object files or libraries, and sources of different types + will be converted to accepted types automatically. + + + + + lib + + + Creates a library file. Depending on the value of + <link> feature the library will be either static or + shared. Like with "exe", sources will be converted either to + objects or libraries. + + The handling of libraries in sources depends on whether + linking is static or shared. For shared linking, libraries + will be linked in. For static linking the library sources + will not be linked in, since it's not possible, and will be + passed on. Other main target which depend on this one will + see those libraries and link to it. Therefore, putting + library in sources of other library works in all cases. + + + alias + + + + Builds all the source targets and returns them unmodified. + Please run "bjam --help alias" for more details. + + + + stage + + + + Copies a number of targets to a single directory. The + primary purpose is installing binaries. Please run "bjam --help + stage" for more details. + + + + unit-test (from module "testing") + + + + Creates an executable file and runs it. Build won't succeed + unless the executable runs successfully. The rule is usefull + for creating test program which should be rerun whenever any + dependency changes. + + + + +
+ +
+ Features + + + variant + + + + The feature which combines several low-level features in + order to make building most common variants simple. + + + Allowed values: debug, release, + profile + + The value debug expands to + + +<optimization>off <debug-symbols>on <inlining>off <runtime-debugging>on + + + The value release expands to + + +<optimization>speed <debug-symbols>off <inlining>full <runtime-debugging>off + + + The value profile expands to the same as + release, plus: + + +<profiling>on <debug-symbols>on + + + Rationale: Runtime debugging is on in debug build + so suit expectations of people used various IDEs. It's + assumed other folks don't have any specific expectation in + this point. + + + link + + + + Feature which controls how libraries are built. + + + Allowed values: shared, + static + + + library + + + + For exe and lib main targets, the <library>X feature + is equvivalent to putting X in the list of sources. The feature + is sometimes more convenient: you can put <library>X in + the requirements for a project and it will be linked to all + executables. + + + + + use + + + + Causes the target referenced by the value of this feature + to be constructed and adds it's usage requirements to build + properties. The constructed targets are not used in any other + way. The primary use case is when you use some library and want + it's usage requirements (such as include paths) to be applied, + but don't want to link to the library. + + + + + dll-path + + + + Specify a path where dynamic libraries should be found at + where executable or shared library is run. This feature + directly affects binaries with the gcc compiler, allowing them + to pick specific libraries, and ignoring all environment + settings. On other toolsets, the binary still requires proper + environment settings to be run. However, Boost.Build tools + which run executables will notice dll-path settings and create + this environment automatically. + + + + hardcode-dll-paths + + + + Controls automatic generation of dll-path properties. + + + Allowed values: off, on When this + property is on, usage requirements for each library will + include additional dll-path propertry, with the path the the + generated library file. This allows to run executables + without placing all the dependent libraries to a single + location. + + + +
+
+ + diff --git a/v2/doc/src/architecture.xml b/v2/doc/src/architecture.xml new file mode 100644 index 000000000..79bde6fed --- /dev/null +++ b/v2/doc/src/architecture.xml @@ -0,0 +1,434 @@ + + + + + Boost.Build v2 architecture + + + This document is work-in progress. Don't expect much from it + yet. + + +
+ Targets + + 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. + + 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 "next section". + [ link? ] Note:File targets are not + the same as targets in Jam sense; the latter are created from + file targets at the latest possible moment. Note:"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. + +
+ Dependency scanning + + Dependency scanning is the process of finding implicit + dependencies, like "#include" statements in C++. The requirements + for right dependency scanning mechanism are: + + + + + Support for different scanning algorithms. C++ and XML have + quite different syntax for includes and rules for looking up + included files. + + + + + + Ability to scan the same file several times. For example, + single C++ file can be compiled with different include + paths. + + + + + + Proper detection of dependencies on generated files. + + + + + + Proper detection of dependencies from generated file. + + + + +
+ Support for different scanning algorithms + + Different scanning algorithm are encapsulated by objects + called "scanners". Please see the documentation for "scanner" + module for more details. + +
+ +
+ Ability to scan the same file several times + + 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. + + The solution in Boost.Build is straigtforward. When a virtual + target is converted to bjam target (via + virtual-target.actualize method), we specify the scanner + object to be used. The actualize method will create different + bjam targets for different scanners. + + 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. + + 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: + + +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 --------------------------------+ + + +
+
+ Proper detection of dependencies on generated files. + + This requirement breaks down to the following ones. + + + + + 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". + + + + + + 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. + + + + + 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: + + + + + If there's file "a.h" in that directory, or + + + + + + If there's a target called "a.h", which will be generated + to that directory. + + + + + 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. + + 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: + + +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] + + + +In this case, Jam thinks all header.h target are not +realated. The right dependency graph might be: + + +a.cpp ---- + \ + \ + >----> <d2>header.h --------> header.y + / [generated in d2] + / +b.cpp ---- + + +or + + +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] + + + + +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. + + + 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: + + + + + The main target to which compiled file belongs is found. + + + + + + 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. + + + + + + All directories where files belonging to those main target + will be generated are added to the include path. + + + + + After this is done, dependencies are found by the approach + explained previously. + + 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. + + For target types other than C++, adding of include paths must + be implemented anew. + +
+
+ Proper detection of dependencies from generated files + + 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. + + 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. + + In order to understand the rest of this section, you better + read some details about jam dependency scanning, available + + at this link. + + Whenever a target is updated, Boost.Jam rescans it for + includes. Consider this graph, created before any actions are + run. + + +A -------> C ----> C.pro + / +B --/ C-includes ---> D + + + +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. + + + 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. + + 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. + + Note also that internal nodes are sometimes updated too. + Consider this dependency graph: + + +a.o ---> a.cpp + a.cpp-includes --> a.h (scanned) + a.h-includes ------> a.h (generated) + | + | + a.pro <-------------------------------------------+ + + + 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. + + 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. + + + + The remainder of this document is not indended to be read at + all. This will be rearranged in future. + + + +
+ File targets + + + 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 + virtual-target module. + + +
+ Types + + A file target can be given a file, which determines + what transformations can be applied to the file. The + type.register rule declares new types. File type can + also be assigned a scanner, which is used to find implicit + dependencies. See "dependency scanning" [ link? ] below. +
+
+ +
+ Target paths + + To distinguish targets build with different properties, they + are put in different directories. Rules for determining target + paths are given below: + + + + + All targets are placed under directory corresponding to the + project where they are defined. + + + + + + Each non free, non incidental property cause an additional + element to be added to the target path. That element has the + form <feature-name>-<feature-value> for + ordinary features and <feature-value> for + implicit ones. [Note about composite features]. + + + + + + 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 main_target-<name> is added to + the target path. Note:It would be nice to completely + track free features also, but this appears to be complex and + not extremely needed. + + + + + For example, we might have these paths: + + +debug/optimization-off +debug/main-target-a + + +
+
+
+
+
+ diff --git a/v2/doc/src/catalog.xml b/v2/doc/src/catalog.xml new file mode 100644 index 000000000..26e16145d --- /dev/null +++ b/v2/doc/src/catalog.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/v2/doc/src/extending.xml b/v2/doc/src/extending.xml new file mode 100644 index 000000000..eff223486 --- /dev/null +++ b/v2/doc/src/extending.xml @@ -0,0 +1,128 @@ + + + + + Extender Manual + +
+ Introduction + + This document explains how to extend Boost.Build to accomodate + your local requirements. Let's start with quite simple, but + realistic example. + + 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: + + + + + Write the template of the code to be generated, leaving + placeholders at the points which will change + + + + + + Access the template in your application and replace + placeholders with appropriate text. + + + + + Write the result. + + + + 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. + + Let's see what Boost.Build can do. + + First off, Boost.Build has no idea about "verbatim files". So, + you must register a new type. The following code does it: + + +import type ; +type.register VERBATIM : verbatim ; + + + 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 VERBATIM. + + 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 generator. + + First, you say that generator 'inline-file' is able to convert + VERBATIM type into C++: + + +import generators ; +generators.register-standard verbatim.inline-file : VERBATIM : CPP ; + + + Second, you must specify the commands to be run to actually + perform convertion: + + +actions inline-file +{ + "./inline-file.py" $(<) $(>) +} + + + + 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: + + +exe codegen : codegen.cpp class_template.verbatim usage.verbatim ; + + + +The verbatim files will be automatically converted into C++ +and linked it. + + + The complete code is available in example/customization + directory. + +
+
+ Target types + +
+ +
+ Tools + +
+ +
+ Main target rules + +
+ +
+ Scanners + +
+
diff --git a/v2/doc/src/faq.xml b/v2/doc/src/faq.xml new file mode 100644 index 000000000..5d7c5a1ca --- /dev/null +++ b/v2/doc/src/faq.xml @@ -0,0 +1,82 @@ + + + + + Frequently Asked Questions + +
+ + I'm getting "Duplicate name of actual target" error. What + does it mean? + + + + The most likely case is that you're trying to + compile the same file twice, with almost the same, + but differing properties. For example: + + +exe a : a.cpp : <include>/usr/local/include ; +exe b : a.cpp ; + + + + + + The above snippet requires two different compilations + of 'a.cpp', which differ only in 'include' property. + Since the 'include' property is free, Boost.Build + can't generate two ojects files into different directories. + On the other hand, it's dangerous to compile the file only + once -- maybe you really want to compile with different + includes. + + + + To solve this issue, you need to decide if file should + be compiled once or twice. + + + + Two compile file only once, make sure that properties + are the same: + + +exe a : a.cpp : <include>/usr/local/include ; +exe b : a.cpp : <include>/usr/local/include ; + + + + If changing the properties is not desirable, for example + if 'a' and 'b' target have other sources which need + specific properties, separate 'a.cpp' into it's own target: + + +obj a_obj : a.cpp : <include>/usr/local/include ; +exe a : a_obj ; + + + + To compile file twice, you can make the object file local + to the main target: + + + exe a : [ obj a_obj : a.cpp ] : <include>/usr/local/include ; + exe b : [ obj a_obj : a.cpp ] ; + + + + + + A good question is why Boost.Build can't use some of the above + approaches automatically. The problem is that such magic would + require additional implementation complexities and would only + help in half of the cases, while in other half we'd be silently + doing the wrong thing. It's simpler and safe to ask user to + clarify his intention in such cases. + + +
+ +
diff --git a/v2/doc/src/howto.xml b/v2/doc/src/howto.xml new file mode 100644 index 000000000..dcb44670f --- /dev/null +++ b/v2/doc/src/howto.xml @@ -0,0 +1,33 @@ + + + + + How to use this document + + + If you've just found out about Boost.Build V2 and want to know + if it will work for you, start with . You can continue with the . When you're ready to try Boost.Build + in practice, go to . + + + + If you are about to use Boost.Build on your project, or already + using it and have a problem, look at . + + + + If you're trying to build a project which uses Boost.Build, + look at and then read about + . + + + + Finally, if nothing applies to you, write to our mailing list, + telling what information you'd like to know. + + + diff --git a/v2/doc/src/install.xml b/v2/doc/src/install.xml new file mode 100644 index 000000000..d164a5907 --- /dev/null +++ b/v2/doc/src/install.xml @@ -0,0 +1,111 @@ + + + + + Installation + + + Assuming you're installing Boost.Build from released source + distribution, the following steps are needed. All paths are + given relatively to Boost.Build root directory, which is the + directory with the document you are reading. + + + + + + Go to "jam_src" directory and build Boost.Jam. Two convenient + scripts are provided, "build.sh" (for Unix systems) and + "build.bat" (for Windows). Run the appropriate one and + Boost.Jam will be built to directory + bin.{platform_name}.. The Boost.Jam documentation has + more details in case you need them. + + + + + + Place the Boost.Jam binary, called "bjam" or "bjam.exe", + somewhere in your PATH. Go to the root + directory of Boost.Build and run "bjam --version". You should + get + + Boost.Build V2 (Milestone N) + + (where N is the version you've downloaded). + + + + + + Configure toolsets to use. Open the + user-config.jam file and follow + instructions there to specify what compiles/libraries you + have and where they are located. + + + + + + You should now be able to go to + example/hello, and run + bjam there. A simple application will be + built. You can also play with other projects in + example. + + + + + + + If you use Boost distribution, or Boost CVS, the Boost.Build + root is located at $boost_root/tools/build/v2 + and the installation steps are the same. However, don't skip + the bjam rebuilding step, even if you have a previous version. + CVS version of Boost.Build requires CVS version of Boost.Jam. + + + + When starting a new project which uses Boost.Build, you need + to make sure that build system can be found. There are two + ways. + + + + + + Set enviromnetal variable BOOST_BUILD_PATH + to the absolute path to Boost.Build installation directory. + + + + + + Create, at the top of your project, a file called + boost-build.jam, with a single line: + + +boost-build /path/to/boost.build ; + + + + + + + If you're trying to use Boost.Build V2 on Boost itself, please + note that when building Boost, V1 is used by default. You'd have + to add command line option to all "bjam" + invocations. + + diff --git a/v2/doc/src/recipes.xml b/v2/doc/src/recipes.xml new file mode 100644 index 000000000..33aa1df6a --- /dev/null +++ b/v2/doc/src/recipes.xml @@ -0,0 +1,35 @@ + + + + + Boost Build System V2 recipes + +
+ Targets in site-config.jam + + It is desirable to declare standard libraries available on a + given system. Putting target declaration in Jamfile is not really + good, since locations of the libraries can vary. The solution is + to put the following to site-config.jam. + + +import project ; +project.initialize $(__name__) ; +project site-config ; +lib zlib : : <name>z ; + + + The second line allows this module to act as project. The + third line gives id to this project — it really has no location + and cannot be used otherwise. The fourth line just declares a + target. Now, one can write + + +exe hello : hello.cpp /site-config//zlib ; + + + in any Jamfile. + +
+
diff --git a/v2/doc/src/reference.xml b/v2/doc/src/reference.xml new file mode 100644 index 000000000..400cdbac5 --- /dev/null +++ b/v2/doc/src/reference.xml @@ -0,0 +1,1037 @@ + + + + + Detailed reference + +
+ Features and properties + +
+ Definitions + + A feature is a normalized (toolset-independent) + aspect of a build configuration, such as whether inlining is + enabled. Feature names may not contain the '>' + character. + + + + Each feature in a build configuration has one or more + associated values. Feature values for non-free features + may not contain the '<', ':', or + '=' characters. Feature values for free features may not + contain the '<' character. + + A property is a (feature,value) pair, expressed as + <feature>value. + + A subfeature is a feature which only exists in the + presence of its parent feature, and whose identity can be derived + (in the context of its parent) from its value. A subfeature's + parent can never be another subfeature. Thus, features and their + subfeatures form a two-level hierarchy. + + A value-string for a feature F is a string of + the form + value-subvalue1-subvalue2...-subvalueN, where + value is a legal value for F and + subvalue1...subvalueN are legal values of some + of F's subfeatures. For example, the properties + <toolset>gcc <toolset-version>3.0.1 can be + expressed more conscisely using a value-string, as + <toolset>gcc-3.0.1. + + A property set is a set of properties (i.e. a + collection without dublicates), for instance: + <toolset>gcc <runtime-link>static. + + A property path is a property set whose elements have + been joined into a single string separated by slashes. A property + path representation of the previous example would be + <toolset>gcc/<runtime-link>static. + + A build specification is a property set which fully + describes the set of features used to build a target. + +
+
+ Property Validity + + + For free + features, all values are valid. For all other features, + the valid values are explicitly specified, and the build + system will report an error for the use of an invalid + feature-value. Subproperty validity may be restricted so + that certain values are valid only in the presence of + certain other subproperties. For example, it is possible + to specify that the <gcc-target>mingw + property is only valid in the presence of + <gcc-version>2.95.2. + + +
+
+ Feature Attributes + + Each feature has a collection of zero or more of the following + attributes. Feature attributes are low-level descriptions of how + the build system should interpret a feature's values when they + appear in a build request. We also refer to the attributes of + properties, so that a incidental property, for example, is + one whose feature is has the incidental attribute. + + + + incidental + + Incidental features are assumed not to affect build + products at all. As a consequence, the build system may use + the same file for targets whose build specification differs + only in incidental features. A feature which controls a + compiler's warning level is one example of a likely + incidental feature. + + Non-incidental features are assumed to affect build + products, so the files for targets whose build specification + differs in non-incidental features are placed in different + directories as described in "target paths" below. [ where? ] + + + + + + + propagated + + + Features of this kind are + propagated to dependencies. That is, if a main target is built using a + propagated + property, the build systems attempts to use the same property + when building any of its dependencies as part of that main + target. For instance, when an optimized exectuable is + requested, one usually wants it to be linked with optimized + libraries. Thus, the <optimization> feature is + propagated. + + + + + + free + + + Most features have a finite set of allowed values, and can + only take on a single value from that set in a given build + specification. Free features, on the other hand, can have + several values at a time and each value can be an arbitrary + string. For example, it is possible to have several + preprocessor symbols defined simultaneously: + + +<define>NDEBUG=1 <define>HAS_CONFIG_H=1 + + + + + + optional + + An optional feature is a feature which is not required to + appear in a build specification. Every non-optional non-free + feature has a default value which is used when a value for + the feature is not otherwise specified, either in a target's + requirements or in the user's build request. [A feature's + default value is given by the first value listed in the + feature's declaration. -- move this elsewhere - dwa] + + + + symmetric + + A symmetric feature's default value is not automatically + included in build variants. Normally + a feature only generates a subvariant directory when its + value differs from the value specified by the build variant, + leading to an assymmetric subvariant directory structure for + certain values of the feature. A symmetric feature, when + relevant to the toolset, always generates a corresponding + subvariant directory. + + + + path + + The value of a path feature specifies a path. The path is + treated as relative to the directory of Jamfile where path + feature is used and is translated appropriately by the build + system when the build is invoked from a different + directory + + + + implicit + + Values of implicit features alone identify the feature. + For example, a user is not required to write + "<toolset>gcc", but can simply write "gcc". Implicit + feature names also don't appear in variant paths, although + the values do. Thus: bin/gcc/... as opposed to + bin/toolset-gcc/.... There should typically be only a few + such features, to avoid possible name clashes. + + + + composite + + Composite features actually correspond to groups of + properties. For example, a build variant is a composite + feature. When generating targets from a set of build + properties, composite features are recursively expanded and + added to the build property set, so rules can find + them if neccessary. Non-composite non-free features override + components of composite features in a build property set. + + + + link-incompatible + + See below. + + + + dependency + + The value of dependency feature if a target reference. + When used for building of a main target, the value of + dependency feature is treated as additional dependency. + + For example, dependency features allow to state that + library A depends on library B. As the result, whenever an + application will link to A, it will also link to B. + Specifying B as dependency of A is different from adding B to + the sources of A. + + + + Features which are neither free nor incidental are called + base features. + + TODO: document active features.. + +
+
+ Feature Declaration + + The low-level feature declaration interface is the + feature rule from the + feature module: + + +rule feature ( name : allowed-values * : attributes * ) + + + A feature's allowed-values may be extended wit The build +system will provide high-level rules which define features in terms +of valid and useful combinations of attributes. + + +
+
+ +
+ Build Variants + + +A build variant, or (simply variant) is a special kind of composite + feature which automatically incorporates the default values of + features that . Typically you'll want at least two separate + variants: one for debugging, and one for your release code. [ + Volodya says: "Yea, we'd need to mention that it's a composite + feature and describe how they are declared, in pacticular that + default values of non-optional features are incorporated into + build variant automagically. Also, do we wan't some variant + inheritance/extension/templates. I don't remember how it works in + V1, so can't document this for V2.". Will clean up soon -DWA ] + + +
+ Link compatible and incompatible properties + + When the build system tries to generate a target (such as + library dependency) matching a given build request, it may find + that an exact match isn't possible — for example, the + target may impose additonal build requirements. We need to + determine whether a buildable version of that target can actually + be used. + + The build request can originate in many ways: it may come + directly from the user's command-line, from a dependency of a + main target upon a library, or from a dependency of a target upon + an executable used to build that target, for example. For each + way, there are different rules whether we can use a given + subvariant or not. The current rules are described below. + + Two property sets are called link-compatible when + targets with those property sets can be used interchangably. In + turn, two property sets are link compatible when there's no + link-incompatible feature which has different values in those + property sets. + + When building of a main target is requested from a command + line or some project, link-compatibility is not considered. When + building is requested by other main target, via sources or + dependency properties, the requested and actual property sets + must be link-compatible, otherwise a warning is produced. + + Rationale:Link-compatibility is not considered when + main target is requested by a project, because it causes problems + in practice. For example, some parts of a project might be + single-threaded, while others — multi-threaded. They are + not link-compatible, but they are not linked, either. So, there's + no need to issue error or warning. The errors used to be + generated, and only caused problems. + +
+
+ Definition of property refinement + + When a target with certain properties is requested, and that + target requires some set of properties, it is needed to find the + set of properties to use for building. This process is called + property refinement and is performed by these rules + + + + + If original properties and required properties are not + link-compatible, refinement fails. + + + + + + Each property in the required set is added to the original + property set + + + + + + If the original property set includes property with a different + value of non free feature, that property is removed. + + + +
+ +
+ Conditional properties + + Sometime it's desirable to apply certain requirements only for + specific combination of other properties. For example, one of + compilers that you use issues a poinless warning that you want to + suppress by passing a command line option to it. You would not + want to pass that option to other compilers. Condititional + properties allow to do that. Their systax is: + + +property ( "," property ) * ":" property + + + +For example, the problem above would be solved by: + + +exe hello : hello.cpp : <toolset>yfc:<cxxflags>-disable-pointless-warning ; + + + +
+
+ +
+ Initialization + + bjam's first job upon startup is to load the Jam code which + implements the build system. To do this, it searches for a file + called "boost-build.jam", first in the invocation directory, then + in its parent and so forth up to the filesystem root, and finally + in the directories specified by the environment variable + BOOST_BUILD_PATH. When found, the file is interpreted, and should + specify the build system location by calling the boost-build + rule: + + +rule boost-build ( location ? ) + + + +If location is a relative path, it is treated as relative to +the directory of boost-build.jam. The directory specified by +location and directories in BOOST_BUILD_PATH are then searched for +a file called bootstrap.jam which is interpreted and is expected to +bootstrap the build system. This arrangement allows the build +system to work without any command-line or environment variable +settings. For example, if the build system files were located in a +directory "build-system/" at your project root, you might place a +boost-build.jam at the project root containing: + + +boost-build build-system ; + + +In this case, running bjam anywhere in the project tree will +automatically find the build system. + + The default "bootstrap.jam", after loading some standard + definitions, loads two files, which can be provided/customised by + user: "site-config.jam" and "user-config.jam". + + Locations where those files a search are summarized below: + +
+ Search paths for configuration files + + + + + + + + site-config.jam + + user-config.jam + + + + + + + Linux + + + /etc + $HOME + $BOOST_BUILD_PATH + + + + $HOME + $BOOST_BUILD_PATH + + + + + Windows + + + $SystemRoot + $HOME + $BOOST_BUILD_PATH + + + + $HOME + $BOOST_BUILD_PATH + + + + +
+ + +Boost.Build comes with default versions of those files, + which can serve as templates for customized versions. + + +
+
+ Command line + + The command line may contain: + + + Jam options, + + Boost.Build options, + + Command line arguments + + +
+ Command line arguments + + + Command line arguments specify targets and build + request using the following rules. + + + + + + An argument which does not contain slashes or the "=" + symbol is either a value of an implicit feature, or target to + be built. It is taken to be value of a feature if appropriate + feature exists. Otherwise, it is considered a target id. Special target name "clean" + has the same effect as "--clean" option. + + + + + + An argument with either slashes or the "=" symbol specifies + a number of build + request + elements. In the simplest form, it's just a set of properties, + separated by slashes, which become a single build request + element, for example: + + +borland/<runtime-link>static + + +More complex form is used to save typing. For example, +instead of + + +borland/runtime-link=static borland/runtime-link=dynamic + + +one can use + + +borland/runtime-link=static,dynamic + + +Exactly, the conversion from argument to build request +elements is performed by (1) splitting the argument at each slash, +(2) converting each split part into a set of properties and (3) +taking all possible combination of the property sets. Each split +part should have the either the form + + +feature-name=feature-value1[","feature-valueN]* + + +or, in case of implict feature + + +feature-value1[","feature-valueN;]* + + +and will be converted into property set + + +<feature-name>feature-value1 .... <feature-name>feature-valueN + + + + + + + +For example, the command line + + +target1 debug gcc/runtime-link=dynamic,static + + +would cause target called target1 to be rebuild in +debug mode, except that for gcc, both dynamically and statically +linked binaries would be created. + + +
+
+ Command line options + + All of the Boost.Build options start with the "--" prefix. + They are described in the following table. + + + Command line options + + + + + Option + + Description + + + + + + --version + + Prints information on Boost.Build and Boost.Jam + versions. + + + + --help + + Access to the online help system. This prints general + information on how to use the help system with additional + --help* options. + + + + --clean + + Removes everything instead of building. Unlike + clean target in make, it is possible to clean only + some targets. + + + + --debug + + Enables internal checks. + + + + --dump-projects + + Cause the project structure to be output. + + + + --no-error-backtrace + + Don't print backtrace on errors. Primary usefull for + testing. + + + + --ignore-config + + Do not load site-config.jam and + user-config.jam + + + +
+ +
+
+ +
+ Build request + + +
+ +
+ Build process + + Construction of each main target begins with finding + properties for this main target. They are found by + processing both build request, and target requirements, + which give properties needed for the target to build. For + example, a given main target might require certian defines, or + will not work unless compiled in multithreaded mode. The process + of finding properties for main target is described in property refinement. + + After that, dependencies (i.e. other main targets) are build + recursively. Build request for dependencies is not always equal + to those of dependent — certain properties are dropped and + user can explicitly specify desired properties for dependencies. + See + propagated features and for details. + + When dependencies are constructed, the dependency graph for + this main target and for this property set is created, which + describes which files need to be created, on which other files + they depend and what actions are needed to construct those files. + There's more that one method, and user can define new ones, but + usually, this involves generators and target + types. + + Target type is just a way to classify targets. For example, + there are builtin types EXE, OBJ and + CPP. Generators are objects + that know how to convert between different target type. When a + target of a given type must be created, all generators for that + type, which can handle needed properties, are found. Each is + passed the list of sources, and either fails, or returns a + dependency graph. If a generator cannot produce desired type from + given sources, it may try to recursively construct types that it + can handle from the types is was passed. This allows to try all + possible transformations. When all generators are tried, a + dependency graph is selected. + + Finally, the dependency graph is passed to underlying + Boost.Jam program, which runs all actions needed to bring all + main targets up-to date. At this step, implicit dependencies are + also scanned and accounted for, as described "here." [ link? ] + + Given a list of targets ids and a build request, building goes + this way. First, for each id we obtain the abstract targets + corresponding to it. This also loads all necessary projects. If + no target id is given, project in the current directory is used. + Build request is expanded, and for each resulting property set, + the generate method of all targets is called, which + yields a list of virtual targets. After that all virtual targets + are actualized, and target "all" is set to depend on all created + actual targets. Lastly, depending on whether --clean + option was given, either target "all" or target "clean" is + updated. Generation of virtual target from abstract one is + performed as follows: + + + + For project targets, all of main targets are generated + with the same properties. Then all projects referred via + "build-project" are generated as well. If it's not possible + to refine requested properties with project requirements, the + project is skipped. + + + It is possible to disable building of certain target using the + explicit rule, available in all project + modules. The syntax is + + +rule explicit ( target-name ) + + + If this rule is invoked on a target, it will be built only +when it's explicitly requested on the command line. + + + + + + For main target, with several alternatives, one of them is + selected as described below. + If there's only one + alternative, it's used unconditionally. + + + + + All main target alternatives which requirements are + satisfied by the build request are enumerated. + + + + + + If there are several such alternatives, the one which + longer requirements list is selected. + + + + + + + + + For the selected alternative + + + + + Each target reference in the source list are + recursively constructed. + + + + + + Properties are refined with alternative's requirements, + and active features in the resulting set are executed. + + + + + + Conditional properties are evaluated. + + + + + + The dependency graph for the target is constructed in a + way which depends on the kind of main target, typically + using generators. + + + + + + + + + If, when building sources, the properties on recursively + created targets are not link-compatibile with build properties, + a warning is issued. + + + + +
+ +
+ Alternative selection + + When there are several alternatives, one of them must be + selected. The process is as follows: + + + + + For each alternative condition is defined + as the set of base properies in requirements. [Note: it might be + better to explicitly specify the condition explicitly, as in + conditional requirements]. + + + + + + An alternative is viable only if all properties in condition + are present in build request. + + + + + + If there's one viable alternative, it's choosen. Otherwise, + an attempt is made to find one best alternative. An alternative + a is better than another alternative b, iff set of properties + in b's condition is stict subset of the set of properities of + 'a's condition. If there's one viable alternative, which is + better than all other, it's selected. Otherwise, an error is + reported. + + + + +
+ +
+ Generated headers + + Usually, Boost.Build handles implicit dependendies completely + automatically. For example, for C++ files, all #include + statements are found and handled. The only aspect where user help + might be needed is implicit dependency on generated files. + + By default, Boost.Build handles such dependencies within one + main target. For example, assume that main target "app" has two + sources, "app.cpp" and "parser.y". The latter source is converted + into "parser.c" and "parser.h". Then, if "app.cpp" includes + "parser.h", Boost.Build will detect this dependency. Moreover, + since "parser.h" will be generated into a build directory, the + path to that directory will automatically added to include + path. + + Making this mechanism work across main target boundaries is + possible, but imposes certain overhead. For that reason, if + there's implicit dependency on files from other main targets, the + <implicit-dependency> [ link ] feature must + be used, for example: + + +lib parser : parser.y ; +exe app : app.cpp : <implicit-dependency>parser ; + + + +The above example tells the build system that when scanning +all sources of "app" for implicit-dependencies, it should consider +targets from "parser" as potential dependencies. + + +
+
+ Generators + + To construct a main target with given properties from sources, + it is required to create a dependency graph for that main target, + which will also include actions to be run. The algorithm for + creating the dependency graph is described here. + + The fundamental concept is generator. If encapsulates + the notion of build tool and is capable to converting a set of + input targets into a set of output targets, with some properties. + Generator matches a build tool as closely as possible: it works + only when the tool can work with requested properties (for + example, msvc compiler can't work when requested toolset is gcc), + and should produce exactly the same targets as the tool (for + example, if Borland's linker produces additional files with debug + information, generator should also). + + Given a set of generators, the fundamental operation is to + construct a target of a given type, with given properties, from a + set of targets. That operation is performed by rule + generators.construct and the used algorithm is described + below. + +
+ Selecting and ranking viable generators + + Each generator, in addition to target types that it can + produce, have attribute that affects its applicability in + particular sitiation. Those attributes are: + + + + + Required properties, which are properties absolutely + necessary for the generator to work. For example, generator + encapsulating the gcc compiler would have <toolset>gcc as + required property. + + + + + + Optional properties, which increase the generators + suitability for a particual build. + + + + + + Generator's required and optional properties may not include + either free or incidental properties. (Allowing this would + greatly complicate caching targets). + + + When trying to construct a target, the first step is to select + all possible generators for the requested target type, which + required properties are a subset of requested properties. + Generators which were already selected up the call stack are + excluded. In addition, if any composing generators were selected + up the call stack, all other composing generators are ignored + (TODO: define composing generators). The found generators + assigned a rank, which is the number of optional properties + present in requested properties. Finally, generators with highest + rank are selected for futher processing. + +
+
+ Running generators + + When generators are selected, each is run to produce a list of + created targets. This list might include targets which are not of + requested types, because generators create the same targets as + some tool, and tool's behaviour is fixed. (Note: should specify + that in some cases we actually want extra targets). If generator + fails, it returns an empty list. Generator is free to call + 'construct' again, to convert sources to the types it can handle. + It also can pass modified properties to 'constuct'. However, a + generator is not allowed to modify any propagated properties, + otherwise when actually consuming properties we might discover + that the set of propagated properties is different from what was + used for building sources. + + For all targets which are not of requested types, we try to + convert them to requested type, using a second call to + construct. This is done in order to support + transformation sequences where single source file expands to + several later. See this + message for details. + +
+ +
+ Selecting dependency graph + + + After all generators are run, + it is necessary to decide which of successfull invocation will be + taken as final result. At the moment, this is not done. Instead, + it is checked whether all successfull generator invocation + returned the same target list. Error is issued otherwise. + + +
+ +
+ Property adjustment + + Because target location is determined by the build system, it + is sometimes necessary to adjust properties, in order to not + break actions. For example, if there's an action which generates + a header, say "a_parser.h", and a source file "a.cpp" which + includes that file, we must make everything work as if a_parser.h + is generated in the same directory where it would be generated + without any subvariants. + + Correct property adjustment can be done only after all targets + are created, so the approach taken is: + + + + + When dependency graph is constructed, each action can be + assigned a rule for property adjustment. + + + + + + When virtual target is actualized, that rule is run and + return the final set of properties. At this stage it can use + information of all created virtual targets. + + + + + In case of quoted includes, no adjustment can give 100% + correct results. If target dirs are not changed by build system, + quoted includes are searched in "." and then in include path, + while angle includes are searched only in include path. When + target dirs are changed, we'd want to make quoted includes to be + search in "." then in additional dirs and then in the include + path and make angle includes be searched in include path, + probably with additional paths added at some position. Unless, + include path already has "." as the first element, this is not + possible. So, either generated headers should not be included + with quotes, or first element of include path should be ".", + which essentially erases the difference between quoted and angle + includes. Note: there only way to get "." as include path + into compiler command line is via verbatim compiler option. In + all other case, Boost.Build will convert "." into directory where + it occurs. + +
+ +
+ Transformations cache + + + Under certain conditions, an + attempt is made to cache results of transformation search. First, + the sources are replaced with targets with special name and the + found target list is stored. Later, when properties, requested + type, and source type are the same, the store target list is + retrieved and cloned, with appropriate change in names. + + +
+
+ +
+ diff --git a/v2/doc/src/tutorial.xml b/v2/doc/src/tutorial.xml new file mode 100644 index 000000000..167ee4214 --- /dev/null +++ b/v2/doc/src/tutorial.xml @@ -0,0 +1,516 @@ + + + + + Tutorial + +
+ Hello, world + + The simplest project that Boost.Build can construct is + stored in example/hello directory. The targets are declared in + a file called Jamfile, which contains the + following: + + +exe hello : hello.cpp ; + + + Even with this simple setup, you can do some interesting + things. First of all, running "bjam" would build binary "hello" + from hello.cpp, in debug version. After that, you can run + + +bjam release + + + which would create release version of the 'hello' binary. + Note that debug and release version would be created in different + directories, so if you want to switch from debug to release + version and back, no recompilation is needed. Let's extend the + example by adding another line to Jamfile: + + +exe hello2 : hello.cpp ; + + + You can now rebuild both debug and release versions: + + +bjam debug release + + + You'll see that two versions of "hello2" binary are linked. + Of course, hello.cpp won't be recompiled. Now you decide to remove + all build products. You do that with the following command + + +bjam --clean debug release + + + It's also possible to create or clean only specific targets. + Both following commands are legal and create or clean only files + that belonging the the named binary: + + +bjam hello2 +bjam --clean hello2 + + + +
+
+ Properties + + Boost.Build attempts to allow building different variants of + projects, e.g. for debugging and release, or in single and + multithreaded mode. In order to stay portable, it uses the + concept of features, which is abstract aspect of + build configuration. Property is just a (feature, + value) pair. For example, there's a feature "debug-symbols", which can + have a value of "on" or "off". When users asks to build project is a + particual value, Boost.Build will automatically find the + appropriate flags to the used compiler. + + The "release" and "debug" in bjam invocation that we've seen + are just are short form of specifying values of feature + "variant". There is a lot of builtin features, and it's possible + to write something like: + + +bjam release inlining=off debug-symbols=on + + + + The first command line element specified the value of feature + "variant". The feature is very common and is therefore special + — it's possible to specify only value. Another feature, + "inlining" is not special, and you should use + + +feature-name=feature-value + + + syntax for it. Complete description of features can be found + here. The set of + properties specified in the command line constitute + build request — the desired properties + for requested targets, or for the project in the current + directory. The actual set of properties used for building is + often different. For example, when compiling a program you need + some include paths. It's not reasonable to ask the user to specify + those paths with each bjam invocation, so must be specified in + Jamfile and added to the build request. For another example, + certain application can only be linked in multithreaded mode. To + support such situations, every target is allowed to specify + requirements -- properties that are required + to its building. Consider this example: + + +exe hello + : hello.cpp + : <include>/home/ghost/Work/boost <threading>multi + + + In this case, when hello is build, the two specified properties will + always be present. This leads to a question: what if user explictly + requested single-threading. The answer is that requirement can + affect build properties only to a certain degree: the requested and + actual properties must be link-compatible. See below. If they are not link + compatible, the bulding of the target is skipped. Previously, we've + added "hello2" target. Seems like we have to specify the same + requirements for it, which results in duplication. But there's a + better way. Each project (i.e. each Jamfile), can specify a set of + attributes, including requirements: + + +project + : requirements <include>/home/ghost/Work/boost <threading>multi + ; + +exe hello : hello.cpp ; +exe hello2 : hello.cpp ; + + + The effect would be as if we specified this requirement for + both "hello" and "hello2". + +
+ +
+ Project hierarchy + + So far we only considered examples with one project (i.e. with + one Jamfile). Typically, you'd have a lot of projects organized + into a tree. At the top of the tree there's project + root. This is a directory which contains, besides Jamfile, a + file called "project-root.jam". Each other Jamfile has a single + parent, which is the Jamfile in the nearest parent directory. For + example, in the following directory layout: + + +[top] + | + |-- Jamfile + |-- project-root.jam + | + |-- src + | | + | |-- Jamfile + | \-- app.cpp + | + \-- lib + | + |-- lib1 + | | + | |-- Jamfile + |-- lib1.cpp + + + +project root is at top. Both src/Jamfile and lib/lib1/Jamfile +have [top]/Jamfile as parent project. Projects inherit all +attributes (such as requirements) from their parents. When the same +attributes are specified in the project, they are combined with +inherited ones. For example, if [top]/Jamfile has + + +<include>/home/ghost/local + + +in requirements, then all other projects will have that in +their requirements too. Of course, any project can add additional +includes. More details can be found in the section on projects. Projects are not automatically +built when +their parents are built. You should specify this explicitly. In our +example, [top]/Jamfile might contain: + + +build-project src ; + + + It will cause project in src to be built whenever project in +[top] is built. However, targets in lib/lib1 will be built only if +required. For example, there may be 10 targets, and two of them are +used by targets in src/Jamfile. Then, only those two targets will +be built. + +
+ +
+ Using libraries + + Let's continue the above example and see how src/Jamfile + can use libraries from + lib/lib1. (TODO: need to make this section consistent with + "examples-v2/libraries". Assume lib/lib1/Jamfile contains: + + +lib lib1 : lib1.cpp ; + + + Then, to use this library in src/Jamfile, we can write: + + +exe app : app.cpp ../lib/lib1//lib1 ; + + +While "app.cpp" is a regular source file, "../lib/lib1//lib1" +is a reference to another target, here, library "lib1" declared in +Jamfile at "../lib/lib1". When linking the "app" binary, the needed +version of the library will be built and linked in. But what is +meant by "needed"? For example, we can request to build "app" with +properties + + +<optimization>full <cxxflags>-w-8080 + + +Which properties must be used for "lib1"? The answer is that +some properties are propagated — Boost.Build attemps +to use dependencies with the same value of propagated features. The +<optimization> feature is propagated, so both "app" and +"lib1" will be compiled with full optimization. But +<cxxflags> feature is not propagated: its value will be added +as-is to compiler flags for "a.cpp", but won't affect "lib1". There +is still a couple of problems. First, the library probably has some +headers which must be used when compiling "app.cpp". We could use +requirements on "app" to add those includes, but then this work +will be repeated for all programs which use "lib1". A better +solution is to modify lib/lib1/Jamfilie in this way: + + +project + : usage-requirements <include>. + ; + +lib lib1 : lib1.cpp ; + + +Usage requirements are requirements which are applied to +dependents. In this case, <include> will be applied to all +targets which use "lib1" — i.e. targets which have "lib1" +either in sources or in dependency properties. You'd need to +specify usage requirements only once, and programs which use "lib1" +don't have to care about include paths any longer. Or course, the +path will be interpreted relatively to "lib/lib1" and will be +adjusted according to the bjams invocation +directory. For +example, if building from project root, the final compiler's +command line will contain . + + + The second problem 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 Jamfile in lib/lib1: + + +project lib1 + : usage-requirements <include>. + ; + + + +Second, we use the project id to refer to the library in +src/Jamfile: + + +exe app : app.cpp /lib1//lib1 ; + + +The "/lib1//lib1" syntax is used to refer to target "lib1" in +project with global id "/lib1" (the slash is used to specify global +id). This way, users of "lib1" do not depend on its location, only +on id, which is supposedly stable. The only thing left, it to make +sure that src/Jamfile knows the project id that it uses. We add to +[top]/Jamfile the following line: + + +use-project /lib1 : lib/lib1 ; + + +Now, all projects can refer to "lib1" using the symbolic +name. If the library is moved somewhere, only a single line in the +top-level Jamfile should be changed. + +
+ +
+ Library dependencies + + The previous example was simple. Often, there are long chains + of dependencies between libraries. The main application is a thin + wrapper on top of library with core logic, which uses library of + utility functions, which uses boost filesystem library. + Expressing these dependencies is straightforward: + + +lib utils : utils.cpp /boost/filesystem//fs ; +lib core : core.cpp utils ; +exe app : app.cpp core ; + + + 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 + which appear as sources for static libraries. In this case, if + everything is built statically, the "app" target will link not + only "core" library, but also "utils" and + "/boost/filesystem//fs". + + So, the net result is that the above code will work for both + static linking and for shared linking. + + Sometimes, you want all applications in some project to link + to a certain library. Putting the library in sources of all + targets is possible, but verbose. You can do better by using + <library> property. For example, if "/boost/filesystem//fs" + should be linked to all applications in your project, you can add + <library>/boost/filesystem//fs to requirements of the + project, like this: + + +project + : requirements <library>/boost/filesystem//fs + ; + +
+ +
+ Static and shared libaries + + While the + previous section explained how to create and use libraries, it + omitted one important detail. Libraries can be either + static, which means they are included in executable + files which use them, or shared (a.k.a. + dynamic), which are only referred to from executables, + and must be available at run time. Boost.Build can work with both + types. 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 is not always convenient, especially + for debug builds. Also, if the installed shared library changes, + all application which use it might start to behave differently. + + + Static libraries do not suffer from these problems, but + considerably increase the size of application. Before describing + static libraries, it's reasonable to give another, quite simple + approach. If your project is built with + <hardcode-dll-paths>true property, then the application + will include the full paths for all shared libraries, eliminating + the above problems. Unfortunately, you no longer can move shared + library to a different location, which makes this option suitable + only for debug builds. Further, only gcc compiler supports this + option. + + Building a library statically is easy. You'd need to change + the value of <link> feature from it's deafault value + shared, to static. So, to build everything as + static libraries, you'd say + + +bjam link=static + + + +on the command line. The linking mode can be fine-tuned on +per-target basis. + + + + + Suppose your library can be only build statically. This is + easily achieved using requirements: + + +lib l : l.cpp : <link>static ; + + + + + + + + What if library can be both static and shared, but when + using it in specific executable, you want it static? + Target + references are here to help: + + +exe important : main.cpp helpers/<link>static ; + + + + + + + + What if the library is defined in some other project, which + you cannot change. But still, you want static linking to that + library in all cases. You can use target references everywhere: + + +exe e1 : e1.cpp /other_project//lib1/<link>static ; +exe e10 : e10.cpp /other_project//lib1/<link>static ; + + +but that's far from being convenient. Another way is to +introduce a level of indirection: create a local target, which will +refer to static version of lib1. Here's the +solution: + + +alias lib1 : /other_project//lib1/<link>static ; +exe e1 : e1.cpp lib1 ; +exe e10 : e10.cpp lib1 ; + + +(Note, that the "alias" target type is not yet implemented, +but it's quite simple to do. I bet it's waiting for you to do it +;-)) + + + + +
+ +
+ Prebuilt targets + + + We've just learned how to use libraries which are created by + Boost.Build. But some libraries are not. 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. Jamfile in lib/lib2 can contain: + + +lib lib2 + : + : <file>lib2_release.a <variant>release + ; + +lib lib2 + : + : <file>lib2_debug.a <variant>debug + ; + + +This defines two alternatives for target "lib2", and for each +one names a prebuilt file. Naturally, there are no sources. +Instead, the <file> feature is used to specify the file name. +Which alternative is selected depends on properties of dependents. +If "app" binary should use "lib2", we can write: + + +exe app : app.cpp /lib/lib1//lib2 ../lib/lib2//lib2 ; + + +If we build release version of "app", then it will be linked +with "lib2_release.a", and debug version will use "lib2_debug.a". +Another important kind of prebuilt targets are system libraries +— more specifically, libraries which are automatically found +by the compiler. E.g. gcc uses "-l" switch for that. Such libraries +should be declared almost like regular ones: + + +lib zlib : : <name>z ; + + +We again don't specify any sources, but give a name which +should be passed to the compiler. In this example, and for gcc +compiler, the "-lz" option will be added. Paths where library +should be searched can also be specified: + + +lib zlib : : <name>z <search>/opt/lib ; + + +And, of course, two variants can be used: + + +lib zlib : : <name>z <variant>release ; +lib zlib : : <name>z_d <variant>debug ; + + +Of course, you'll probably never in your life need debug +version of zlib, but for other libraries this is quite reasonable. + + + More advanced use of prebuilt target is descibed in recipes. + +
+ +
+ diff --git a/v2/doc/src/userman.xml b/v2/doc/src/userman.xml new file mode 100644 index 000000000..9d69bcff6 --- /dev/null +++ b/v2/doc/src/userman.xml @@ -0,0 +1,23 @@ + + + + + + Boost.Build v2 User Manual + + + + + + + + + + + + + + + diff --git a/v2/doc/userman.xml b/v2/doc/userman.xml deleted file mode 100644 index 328ecb351..000000000 --- a/v2/doc/userman.xml +++ /dev/null @@ -1,3189 +0,0 @@ - - - - - Boost.Build v2 User Manual - - - How to use this document - - - If you've just found out about Boost.Build V2 and want to know - if it will work for you, start with . You can continue with the . When you're ready to try Boost.Build - in practice, go to . - - - - If you are about to use Boost.Build on your project, or already - using it and have a problem, look at . - - - - If you're trying to build a project which uses Boost.Build, - look at and then read about - . - - - - Finally, if nothing applies to you, write to our mailing list, - telling what information you'd like to know. - - - - - - Installation - - - Assuming you're installing Boost.Build from released source - distribution, the following steps are needed. All paths are - given relatively to Boost.Build root directory, which is the - directory with the document you are reading. - - - - - - Go to "jam_src" directory and build Boost.Jam. Two convenient - scripts are provided, "build.sh" (for Unix systems) and - "build.bat" (for Windows). Run the appropriate one and - Boost.Jam will be built to directory - bin.{platform_name}.. The Boost.Jam documentation has - more details in case you need them. - - - - - - Place the Boost.Jam binary, called "bjam" or "bjam.exe", - somewhere in your PATH. Go to the root - directory of Boost.Build and run "bjam --version". You should - get - - Boost.Build V2 (Milestone N) - - (where N is the version you've downloaded). - - - - - - Configure toolsets to use. Open the - user-config.jam file and follow - instructions there to specify what compiles/libraries you - have and where they are located. - - - - - - You should now be able to go to - example/hello, and run - bjam there. A simple application will be - built. You can also play with other projects in - example. - - - - - - - If you use Boost distribution, or Boost CVS, the Boost.Build - root is located at $boost_root/tools/build/v2 - and the installation steps are the same. However, don't skip - the bjam rebuilding step, even if you have a previous version. - CVS version of Boost.Build requires CVS version of Boost.Jam. - - - - When starting a new project which uses Boost.Build, you need - to make sure that build system can be found. There are two - ways. - - - - - - Set enviromnetal variable BOOST_BUILD_PATH - to the absolute path to Boost.Build installation directory. - - - - - - Create, at the top of your project, a file called - boost-build.jam, with a single line: - - -boost-build /path/to/boost.build ; - - - - - - - If you're trying to use Boost.Build V2 on Boost itself, please - note that when building Boost, V1 is used by default. You'd have - to add command line option to all "bjam" - invocations. - - - - - Tutorial - -
- Hello, world - - The simplest project that Boost.Build can construct is - stored in example/hello directory. The targets are declared in - a file called Jamfile, which contains the - following: - - -exe hello : hello.cpp ; - - - Even with this simple setup, you can do some interesting - things. First of all, running "bjam" would build binary "hello" - from hello.cpp, in debug version. After that, you can run - - -bjam release - - - which would create release version of the 'hello' binary. - Note that debug and release version would be created in different - directories, so if you want to switch from debug to release - version and back, no recompilation is needed. Let's extend the - example by adding another line to Jamfile: - - -exe hello2 : hello.cpp ; - - - You can now rebuild both debug and release versions: - - -bjam debug release - - - You'll see that two versions of "hello2" binary are linked. - Of course, hello.cpp won't be recompiled. Now you decide to remove - all build products. You do that with the following command - - -bjam --clean debug release - - - It's also possible to create or clean only specific targets. - Both following commands are legal and create or clean only files - that belonging the the named binary: - - -bjam hello2 -bjam --clean hello2 - - - -
-
- Properties - - Boost.Build attempts to allow building different variants of - projects, e.g. for debugging and release, or in single and - multithreaded mode. In order to stay portable, it uses the - concept of features, which is abstract aspect of - build configuration. Property is just a (feature, - value) pair. For example, there's a feature "debug-symbols", which can - have a value of "on" or "off". When users asks to build project is a - particual value, Boost.Build will automatically find the - appropriate flags to the used compiler. - - The "release" and "debug" in bjam invocation that we've seen - are just are short form of specifying values of feature - "variant". There is a lot of builtin features, and it's possible - to write something like: - - -bjam release inlining=off debug-symbols=on - - - - The first command line element specified the value of feature - "variant". The feature is very common and is therefore special - — it's possible to specify only value. Another feature, - "inlining" is not special, and you should use - - -feature-name=feature-value - - - syntax for it. Complete description of features can be found - here. The set of - properties specified in the command line constitute - build request — the desired properties - for requested targets, or for the project in the current - directory. The actual set of properties used for building is - often different. For example, when compiling a program you need - some include paths. It's not reasonable to ask the user to specify - those paths with each bjam invocation, so must be specified in - Jamfile and added to the build request. For another example, - certain application can only be linked in multithreaded mode. To - support such situations, every target is allowed to specify - requirements -- properties that are required - to its building. Consider this example: - - -exe hello - : hello.cpp - : <include>/home/ghost/Work/boost <threading>multi - - - In this case, when hello is build, the two specified properties will - always be present. This leads to a question: what if user explictly - requested single-threading. The answer is that requirement can - affect build properties only to a certain degree: the requested and - actual properties must be link-compatible. See below. If they are not link - compatible, the bulding of the target is skipped. Previously, we've - added "hello2" target. Seems like we have to specify the same - requirements for it, which results in duplication. But there's a - better way. Each project (i.e. each Jamfile), can specify a set of - attributes, including requirements: - - -project - : requirements <include>/home/ghost/Work/boost <threading>multi - ; - -exe hello : hello.cpp ; -exe hello2 : hello.cpp ; - - - The effect would be as if we specified this requirement for - both "hello" and "hello2". - -
- -
- Project hierarchy - - So far we only considered examples with one project (i.e. with - one Jamfile). Typically, you'd have a lot of projects organized - into a tree. At the top of the tree there's project - root. This is a directory which contains, besides Jamfile, a - file called "project-root.jam". Each other Jamfile has a single - parent, which is the Jamfile in the nearest parent directory. For - example, in the following directory layout: - - -[top] - | - |-- Jamfile - |-- project-root.jam - | - |-- src - | | - | |-- Jamfile - | \-- app.cpp - | - \-- lib - | - |-- lib1 - | | - | |-- Jamfile - |-- lib1.cpp - - - -project root is at top. Both src/Jamfile and lib/lib1/Jamfile -have [top]/Jamfile as parent project. Projects inherit all -attributes (such as requirements) from their parents. When the same -attributes are specified in the project, they are combined with -inherited ones. For example, if [top]/Jamfile has - - -<include>/home/ghost/local - - -in requirements, then all other projects will have that in -their requirements too. Of course, any project can add additional -includes. More details can be found in the section on projects. Projects are not automatically -built when -their parents are built. You should specify this explicitly. In our -example, [top]/Jamfile might contain: - - -build-project src ; - - - It will cause project in src to be built whenever project in -[top] is built. However, targets in lib/lib1 will be built only if -required. For example, there may be 10 targets, and two of them are -used by targets in src/Jamfile. Then, only those two targets will -be built. - -
- -
- Using libraries - - Let's continue the above example and see how src/Jamfile - can use libraries from - lib/lib1. (TODO: need to make this section consistent with - "examples-v2/libraries". Assume lib/lib1/Jamfile contains: - - -lib lib1 : lib1.cpp ; - - - Then, to use this library in src/Jamfile, we can write: - - -exe app : app.cpp ../lib/lib1//lib1 ; - - -While "app.cpp" is a regular source file, "../lib/lib1//lib1" -is a reference to another target, here, library "lib1" declared in -Jamfile at "../lib/lib1". When linking the "app" binary, the needed -version of the library will be built and linked in. But what is -meant by "needed"? For example, we can request to build "app" with -properties - - -<optimization>full <cxxflags>-w-8080 - - -Which properties must be used for "lib1"? The answer is that -some properties are propagated — Boost.Build attemps -to use dependencies with the same value of propagated features. The -<optimization> feature is propagated, so both "app" and -"lib1" will be compiled with full optimization. But -<cxxflags> feature is not propagated: its value will be added -as-is to compiler flags for "a.cpp", but won't affect "lib1". There -is still a couple of problems. First, the library probably has some -headers which must be used when compiling "app.cpp". We could use -requirements on "app" to add those includes, but then this work -will be repeated for all programs which use "lib1". A better -solution is to modify lib/lib1/Jamfilie in this way: - - -project - : usage-requirements <include>. - ; - -lib lib1 : lib1.cpp ; - - -Usage requirements are requirements which are applied to -dependents. In this case, <include> will be applied to all -targets which use "lib1" — i.e. targets which have "lib1" -either in sources or in dependency properties. You'd need to -specify usage requirements only once, and programs which use "lib1" -don't have to care about include paths any longer. Or course, the -path will be interpreted relatively to "lib/lib1" and will be -adjusted according to the bjams invocation -directory. For -example, if building from project root, the final compiler's -command line will contain . - - - The second problem 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 Jamfile in lib/lib1: - - -project lib1 - : usage-requirements <include>. - ; - - - -Second, we use the project id to refer to the library in -src/Jamfile: - - -exe app : app.cpp /lib1//lib1 ; - - -The "/lib1//lib1" syntax is used to refer to target "lib1" in -project with global id "/lib1" (the slash is used to specify global -id). This way, users of "lib1" do not depend on its location, only -on id, which is supposedly stable. The only thing left, it to make -sure that src/Jamfile knows the project id that it uses. We add to -[top]/Jamfile the following line: - - -use-project /lib1 : lib/lib1 ; - - -Now, all projects can refer to "lib1" using the symbolic -name. If the library is moved somewhere, only a single line in the -top-level Jamfile should be changed. - -
- -
- Library dependencies - - The previous example was simple. Often, there are long chains - of dependencies between libraries. The main application is a thin - wrapper on top of library with core logic, which uses library of - utility functions, which uses boost filesystem library. - Expressing these dependencies is straightforward: - - -lib utils : utils.cpp /boost/filesystem//fs ; -lib core : core.cpp utils ; -exe app : app.cpp core ; - - - 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 - which appear as sources for static libraries. In this case, if - everything is built statically, the "app" target will link not - only "core" library, but also "utils" and - "/boost/filesystem//fs". - - So, the net result is that the above code will work for both - static linking and for shared linking. - - Sometimes, you want all applications in some project to link - to a certain library. Putting the library in sources of all - targets is possible, but verbose. You can do better by using - <library> property. For example, if "/boost/filesystem//fs" - should be linked to all applications in your project, you can add - <library>/boost/filesystem//fs to requirements of the - project, like this: - - -project - : requirements <library>/boost/filesystem//fs - ; - -
- -
- Static and shared libaries - - While the - previous section explained how to create and use libraries, it - omitted one important detail. Libraries can be either - static, which means they are included in executable - files which use them, or shared (a.k.a. - dynamic), which are only referred to from executables, - and must be available at run time. Boost.Build can work with both - types. 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 is not always convenient, especially - for debug builds. Also, if the installed shared library changes, - all application which use it might start to behave differently. - - - Static libraries do not suffer from these problems, but - considerably increase the size of application. Before describing - static libraries, it's reasonable to give another, quite simple - approach. If your project is built with - <hardcode-dll-paths>true property, then the application - will include the full paths for all shared libraries, eliminating - the above problems. Unfortunately, you no longer can move shared - library to a different location, which makes this option suitable - only for debug builds. Further, only gcc compiler supports this - option. - - Building a library statically is easy. You'd need to change - the value of <link> feature from it's deafault value - shared, to static. So, to build everything as - static libraries, you'd say - - -bjam link=static - - - -on the command line. The linking mode can be fine-tuned on -per-target basis. - - - - - Suppose your library can be only build statically. This is - easily achieved using requirements: - - -lib l : l.cpp : <link>static ; - - - - - - - - What if library can be both static and shared, but when - using it in specific executable, you want it static? - Target - references are here to help: - - -exe important : main.cpp helpers/<link>static ; - - - - - - - - What if the library is defined in some other project, which - you cannot change. But still, you want static linking to that - library in all cases. You can use target references everywhere: - - -exe e1 : e1.cpp /other_project//lib1/<link>static ; -exe e10 : e10.cpp /other_project//lib1/<link>static ; - - -but that's far from being convenient. Another way is to -introduce a level of indirection: create a local target, which will -refer to static version of lib1. Here's the -solution: - - -alias lib1 : /other_project//lib1/<link>static ; -exe e1 : e1.cpp lib1 ; -exe e10 : e10.cpp lib1 ; - - -(Note, that the "alias" target type is not yet implemented, -but it's quite simple to do. I bet it's waiting for you to do it -;-)) - - - - -
- -
- Prebuilt targets - - - We've just learned how to use libraries which are created by - Boost.Build. But some libraries are not. 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. Jamfile in lib/lib2 can contain: - - -lib lib2 - : - : <file>lib2_release.a <variant>release - ; - -lib lib2 - : - : <file>lib2_debug.a <variant>debug - ; - - -This defines two alternatives for target "lib2", and for each -one names a prebuilt file. Naturally, there are no sources. -Instead, the <file> feature is used to specify the file name. -Which alternative is selected depends on properties of dependents. -If "app" binary should use "lib2", we can write: - - -exe app : app.cpp /lib/lib1//lib2 ../lib/lib2//lib2 ; - - -If we build release version of "app", then it will be linked -with "lib2_release.a", and debug version will use "lib2_debug.a". -Another important kind of prebuilt targets are system libraries -— more specifically, libraries which are automatically found -by the compiler. E.g. gcc uses "-l" switch for that. Such libraries -should be declared almost like regular ones: - - -lib zlib : : <name>z ; - - -We again don't specify any sources, but give a name which -should be passed to the compiler. In this example, and for gcc -compiler, the "-lz" option will be added. Paths where library -should be searched can also be specified: - - -lib zlib : : <name>z <search>/opt/lib ; - - -And, of course, two variants can be used: - - -lib zlib : : <name>z <variant>release ; -lib zlib : : <name>z_d <variant>debug ; - - -Of course, you'll probably never in your life need debug -version of zlib, but for other libraries this is quite reasonable. - - - More advanced use of prebuilt target is descibed in recipes. - -
- -
- - - Advanced - - This section will document - mostly high-level view of Boost.Build, mentioning appropriate - modules and rules. The on-line help system must be used to obtain - low-level documentation (see the help option). - -
- Overview - - The most fundemental entity in Boost.Build is main - target. This is object that user want to construct from - sources and keep up to date with regard to those sources. Typical - examples of main targets are executable files and libraries. - - Main targets are grouped in projects. Their main - purpose is organization: related targets placed in one project, - can then be built together, or share some definitions. - - Main targets and projects are created as the result of reading - one or several Jamfiles. Each Jamfile is a file written in - Boost.Jam interpreted language, and typically contains calls to - functions provided by Boost.Build, which create main targets of - needed type, declare project attributes and access other - projects. The full list of functions provided by Boost.Build is - described below. - Of course, user can create his own functions, or it can directly - access Boost.Build internals from Jamfile, if builtin facilities are - not sufficient. - - Each main target, or project can be built in a number of ways, - say with optimization or without. We'll call such entities - "metatargets". To make Boost.Build produce any real targets, user - issues build request, - which specifies metatargets to be built, and properties to be - used. - - The properties are just (name,value) pairs that - describe various aspects of constructed objects, for example: - -<optimization>full <inlining>off - - - Given the built request, Boost.Build figures out the targets - needed for requested metatargets with requested properties, how - they can be created, and whether exising files can be reused. It - finally issues command to create needed files, automatically - converting properties into appropricate command line options. - -
- -
- Your first project and roadmap - - Creating your first project requires three steps: - - - Create an empty file called "Jamfile" - - - - Create an empty file called "project-root.jam" - - - - - Either set your BOOST_BUILD_PATH environment - variant to Boost.Build root, or create a "boost-build.jam" file - with the following content: - - -boost-build /path/to/boost.build ; - - - - - - - After that, you can run the "bjam" command in the directory - where you've created the files. Surely, it won't do anything, but - it will run without error, at least. Your next steps might - be: - - - - - Adding new main targets to the "Jamfile" file. The basic - syntax for declaring a main target is described below, and all builtin functions for - declaring main targets are listed. - - - - - - Creating subprojects. Create a directory, put new Jamfile - there, and move some main targets to that Jamfile, or declare - new ones. The projects - reference will help with this part. - - - - - - Customizing Boost.Build for your needs. You might have - additional tools you want to run, or just want different - extension for some file. The extender manual is waiting for - you. - - - - -
- -
- Main targets - - - Main target is a user-defined named - entity which can be build, for example a named executable file. - Declaring a main target is usually done using one of main target functions. - The user can also declare custom main target - function. - - Most main targets rules in Boost.Build use similiar - syntax: - - -function-name main-target-name - : sources - : requirements - : default-build - : usage-requirements - ; - - - - - - "main-target-name" is the name used to request the target - on command line and to use it from other main targets. Main - target name may contain alphanumeric characters and symbols '-' - and '_'; - - - - - - "sources" is the list of source files and other main - targets that must be combined. If source file is specified - using relative path, it's considered to be relative to the - source directory of the project where the path is used. See the - project rule - for information how to change source directory. - - - - - - "requirements" is the list of properties that must always - be present when this main target is built. - - - - - - "default-build" is the list of properties that will be used - unless some other value of the same feature is already - specified. - - - - - - "usage-requirements" is the list of properties that will be - propagated to all main targets that use this one, i.e. to all - dependedents. - - - - - Some main target rules have shorter list of parameters, and - you should consult their documentation for details. - - Building of the same main target can differ greatly from - platform to platform. For example, you might have different list - of sources for different compilers. Therefore it is possible to - invoke main target rules several times for a single main target. - For example: - - -exe a : a_gcc.cpp : <toolset>gcc ; -exe a : a.cpp ; - - - - Each call to the 'exe' rule defines a new main target - alternative for the main target a. - In this case, the first alternative will be used for the - gcc toolset, while the second alternative will - be used in other cases. See below for - details. - - - Sometime a main target is really needed only by some other - main target. E.g. a rule that declared test-suite uses a main - target that represent test, but those main targets are rarely - needed by themself. - - It possible to declare target inline, i.e. the "sources" - parameter may include call to other main rules. For example: - - -exe hello : hello.cpp - [ obj helpers : helpers.cpp : <optimization>off ] ; - - - -Will cause "helpers.cpp" to be always compiled without -optimization. It's possible to request main targets declared -inline, but since they are considered local, they are renamed to -"parent-main-target_name..main-target-name". In the example above, -to build only helpers, one should run "bjam hello..helpers". - - -
- -
- Projects - - Boost.Build considers every software it build as organized - into projects — modules which declare targets. - Projects are organized in a hierarchical structure, so each - project may have a single parent project and a number of - subprojects. - - Most often, projects are created as result of loading - Jamfile — files which are specially meant to - describe projects. Boost.Build will implicitly load Jamfile in - the invocation directory, and all Jamfiles referred by the first - one, creating the hierarchy of projects. - - The exact name of file that describes project is configurable. - By default, it's Jamfile, but can be changed by setting - global variables JAMFILE, for example in - boost-build.jam file. The value of the variable is a - list of regex patterns that are used when searching for Jamfile - in a directory. - - Every Boost.Build modules can decide to act as project and be - able to declare targets. For example, the - site-config.jam module can declare libraries - available on a given host, as described here. - - There are three things that can be put in Jamfile: - declarations of main targets, calls to a number of predefined - rules, and arbitrary user code. The predefined rules are listed - below: - - - - <tgroup cols="2"> - <thead> - <row> - <entry>Rule</entry> - - <entry>Semantic</entry> - </row> - </thead> - - <tbody> - <row> - <entry><link linkend= - "bbv2.advanced.projects.attributes.projectrule">project</link> - </entry> - - <entry>Define project attributes.</entry> - </row> - - <row> - <entry><link linkend= - "bbv2.advanced.projects.relationships.useprojectrule">use-project</link></entry> - - <entry>Make another project known.</entry> - </row> - - <row> - <entry><link linkend= - "bbv2.advanced.projects.relationships.buildprojectrule">build-project</link></entry> - - <entry>Build another project when this one is built.</entry> - </row> - - <row> - <entry><link linkend= - "bbv2.reference.buildprocess.explict">explicit</link></entry> - - <entry>States that the target should be built only by explicit - request.</entry> - </row> - - <row> - <entry>glob</entry> - - <entry>Takes a list of wildcards, and returns the list of files - which match any of the wildcards.</entry> - </row> - </tbody> - </tgroup> - </table> - - <para>Each project is also associated with <emphasis>project root</emphasis>. - That's a root for a tree of projects, which specifies some global - properties.</para> - - <section id="bbv2.advanced.projects.root"> - <title>Project root - - - Project root for a projects is the nearest parent directory - which contains a file called - project-root.jam. That file defines - certain properties which apply to all projects under project - root. It can: - - - - - configure toolsets, via call to toolset.using - - - - - - refer to other projects, via the use-project - rule - - - - - - declare constants, via the constant and - path-constant rules. - - - - - - - To facilitate declaration of simple projects, Jamfile and - project-root can be merged together. To achieve this effect, the - project root file should call the project rule. The - semantic is precisely the same as if the call was made in - Jamfile, except that project-root.jam will start serve as - Jamfile. The Jamfile in the directory of project-root.jam will be - ignored, and project-root.jam will be able to declare main - targets as usual. - - - -
- Project attributes - - For each project, there are several attributes. - - Project id is a short way to denote a project, as - opposed to the Jamfile's pathname. It is a hierarchical path, - unrelated to filesystem, such as "boost/thread". Target references make use of project ids to - specify a target. - - Source location specifies the directory where sources - for the project are located. - - Project requirements are requirements that apply to - all the targets in the projects as well as all subprojects. - - Default build is the build request that should be - used when no build request is specified explicitly. - - - The default values for those attributes are - given in the table below. In order to affect them, Jamfile may - call the project rule. The rule has this - syntax: - - -project id : <attributes> ; - - - -Here, attributes is a sequence of (attribute-name, -attribute-value) pairs. The list of attribute names along with its -handling is also shown in the table below. For example, it it -possible to write: - - - -project tennis - : requirements <threading>multi - : default-build release - ; - - -
- - <tgroup cols="4"> - <thead> - <row> - <entry>Attribute</entry> - - <entry>Name for the 'project' rule</entry> - - <entry>Default value</entry> - - <entry>Handling by the 'project' rule</entry> - </row> - </thead> - - <tbody> - - <row> - <entry>Project id</entry> - - <entry>none</entry> - - <entry>none</entry> - - <entry>Assigned from the first parameter of the 'project' rule. - It is assumed to denote absolute project id.</entry> - </row> - - <row> - <entry>Source location</entry> - - <entry><literal>source-location</literal></entry> - - <entry>The location of jamfile for the project</entry> - - <entry>Sets to the passed value</entry> - </row> - - <row> - <entry>Requirements</entry> - - <entry><literal>requirements</literal></entry> - - <entry>The parent's requirements</entry> - - <entry>The parent's requirements are refined with the passed - requirement and the result is used as the project - requirements.</entry> - </row> - - <row> - <entry>Default build</entry> - - <entry><literal>default-build</literal></entry> - - <entry>none</entry> - - <entry>Sets to the passed value</entry> - </row> - - <row> - <entry>Build directory</entry> - - <entry><literal>build-dir</literal></entry> - - <entry>If parent has a build dir set, the value of it, joined - with the relative path from parent to the current project. - Otherwise, empty</entry> - - <entry>Sets to the passed value, interpreted as relative to the - project's location.</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - - <section id="bbv2.advanced.projects.relationships"> - <title>Project relationship - - There are three kinds of project relationships. - - First is parent-child. This relationship is established - implicitly: parent directories of a project are searched, and the - first found Jamfile is assumed to define the parent project. The - parent-child relationship affects only attribute values for the - child project. - - - Second is build relationship. Some - project may request to recursively build other projects. Those - project need not be child projects. The build-project - rule is used for that: - - build-project src ; - - - - The third kind is the 'use' - relationship. In means that one project uses targets from - another. It is possible to just refer to target in other projects - using target id. However, if target id uses project id, it is - required that the project id is known. The - use-project - rule is employed to guarantee that. - - - -use-project ( id : location ) - - - -It loads the project at the specified location, which makes -its project id available in the project which invokes the rule. It -is required that the id parameter passed to the -use-project rule be equal to the id that the loaded -project declared. At this moment, the id paremeter -should be absolute project id. - - - - -
- Target identifiers and references - - Target identifier is used to denote a - target. The syntax is: - - -target-id -> (project-id | target-name | file-name ) - | (project-id | directory-name) "//" target-name -project-id -> path -target-name -> path -file-name -> path -directory-name -> path - - - -This grammar allows some elements to be recognized as either - - - - - project id (at this point, all project ids start with slash). - - - - - - name of target declared in current Jamfile (note that target - names may include slash). - - - - - - a regular file, denoted by absolute name or name relative to - project's sources location. - - - - - To determine the real meaning a check is made if project-id - by the specified name exists, and then if main target of that - name exists. For example, valid target ids might be: - - -a -- target in current project -lib/b.cpp -- regular file -/boost/thread -- project "/boost/thread" -/home/ghost/build/lr_library//parser -- target in specific project - - - - - Rationale:Target is separated from project by special - separator (not just slash), because: - - - - - It emphasises that projects and targets are different things. - - - - - - It allows to have main target names with slashes. - - - - - - - - Target reference is used to - specify a source target, and may additionally specify desired - properties for that target. It has this syntax: - - -target-reference -> target-id [ "/" requested-properties ] -requested-properties -> property-path - - - -For example, - - -exe compiler : compiler.cpp libs/cmdline/<optimization>space ; - - -would cause the version of cmdline library, -optimized for space, to be linked in even if the -compiler executable is build with optimization for -speed. - -
-
- Builtin facilities - -
- Main targets - - - exe - - - - Creates a regular executable file. Sources must be either - object files or libraries, and sources of different types - will be converted to accepted types automatically. - - - - - lib - - - Creates a library file. Depending on the value of - <link> feature the library will be either static or - shared. Like with "exe", sources will be converted either to - objects or libraries. - - The handling of libraries in sources depends on whether - linking is static or shared. For shared linking, libraries - will be linked in. For static linking the library sources - will not be linked in, since it's not possible, and will be - passed on. Other main target which depend on this one will - see those libraries and link to it. Therefore, putting - library in sources of other library works in all cases. - - - alias - - - - Builds all the source targets and returns them unmodified. - Please run "bjam --help alias" for more details. - - - - stage - - - - Copies a number of targets to a single directory. The - primary purpose is installing binaries. Please run "bjam --help - stage" for more details. - - - - unit-test (from module "testing") - - - - Creates an executable file and runs it. Build won't succeed - unless the executable runs successfully. The rule is usefull - for creating test program which should be rerun whenever any - dependency changes. - - - - -
- -
- Features - - - variant - - - - The feature which combines several low-level features in - order to make building most common variants simple. - - - Allowed values: debug, release, - profile - - The value debug expands to - - -<optimization>off <debug-symbols>on <inlining>off <runtime-debugging>on - - - The value release expands to - - -<optimization>speed <debug-symbols>off <inlining>full <runtime-debugging>off - - - The value profile expands to the same as - release, plus: - - -<profiling>on <debug-symbols>on - - - Rationale: Runtime debugging is on in debug build - so suit expectations of people used various IDEs. It's - assumed other folks don't have any specific expectation in - this point. - - - link - - - - Feature which controls how libraries are built. - - - Allowed values: shared, - static - - - library - - - - For exe and lib main targets, the <library>X feature - is equvivalent to putting X in the list of sources. The feature - is sometimes more convenient: you can put <library>X in - the requirements for a project and it will be linked to all - executables. - - - - - use - - - - Causes the target referenced by the value of this feature - to be constructed and adds it's usage requirements to build - properties. The constructed targets are not used in any other - way. The primary use case is when you use some library and want - it's usage requirements (such as include paths) to be applied, - but don't want to link to the library. - - - - - dll-path - - - - Specify a path where dynamic libraries should be found at - where executable or shared library is run. This feature - directly affects binaries with the gcc compiler, allowing them - to pick specific libraries, and ignoring all environment - settings. On other toolsets, the binary still requires proper - environment settings to be run. However, Boost.Build tools - which run executables will notice dll-path settings and create - this environment automatically. - - - - hardcode-dll-paths - - - - Controls automatic generation of dll-path properties. - - - Allowed values: off, on When this - property is on, usage requirements for each library will - include additional dll-path propertry, with the path the the - generated library file. This allows to run executables - without placing all the dependent libraries to a single - location. - - - -
-
- - - - Detailed reference - -
- Features and properties - -
- Definitions - - A feature is a normalized (toolset-independent) - aspect of a build configuration, such as whether inlining is - enabled. Feature names may not contain the '>' - character. - - - - Each feature in a build configuration has one or more - associated values. Feature values for non-free features - may not contain the '<', ':', or - '=' characters. Feature values for free features may not - contain the '<' character. - - A property is a (feature,value) pair, expressed as - <feature>value. - - A subfeature is a feature which only exists in the - presence of its parent feature, and whose identity can be derived - (in the context of its parent) from its value. A subfeature's - parent can never be another subfeature. Thus, features and their - subfeatures form a two-level hierarchy. - - A value-string for a feature F is a string of - the form - value-subvalue1-subvalue2...-subvalueN, where - value is a legal value for F and - subvalue1...subvalueN are legal values of some - of F's subfeatures. For example, the properties - <toolset>gcc <toolset-version>3.0.1 can be - expressed more conscisely using a value-string, as - <toolset>gcc-3.0.1. - - A property set is a set of properties (i.e. a - collection without dublicates), for instance: - <toolset>gcc <runtime-link>static. - - A property path is a property set whose elements have - been joined into a single string separated by slashes. A property - path representation of the previous example would be - <toolset>gcc/<runtime-link>static. - - A build specification is a property set which fully - describes the set of features used to build a target. - -
-
- Property Validity - - - For free - features, all values are valid. For all other features, - the valid values are explicitly specified, and the build - system will report an error for the use of an invalid - feature-value. Subproperty validity may be restricted so - that certain values are valid only in the presence of - certain other subproperties. For example, it is possible - to specify that the <gcc-target>mingw - property is only valid in the presence of - <gcc-version>2.95.2. - - -
-
- Feature Attributes - - Each feature has a collection of zero or more of the following - attributes. Feature attributes are low-level descriptions of how - the build system should interpret a feature's values when they - appear in a build request. We also refer to the attributes of - properties, so that a incidental property, for example, is - one whose feature is has the incidental attribute. - - - - incidental - - Incidental features are assumed not to affect build - products at all. As a consequence, the build system may use - the same file for targets whose build specification differs - only in incidental features. A feature which controls a - compiler's warning level is one example of a likely - incidental feature. - - Non-incidental features are assumed to affect build - products, so the files for targets whose build specification - differs in non-incidental features are placed in different - directories as described in "target paths" below. [ where? ] - - - - - - - propagated - - - Features of this kind are - propagated to dependencies. That is, if a main target is built using a - propagated - property, the build systems attempts to use the same property - when building any of its dependencies as part of that main - target. For instance, when an optimized exectuable is - requested, one usually wants it to be linked with optimized - libraries. Thus, the <optimization> feature is - propagated. - - - - - - free - - - Most features have a finite set of allowed values, and can - only take on a single value from that set in a given build - specification. Free features, on the other hand, can have - several values at a time and each value can be an arbitrary - string. For example, it is possible to have several - preprocessor symbols defined simultaneously: - - -<define>NDEBUG=1 <define>HAS_CONFIG_H=1 - - - - - - optional - - An optional feature is a feature which is not required to - appear in a build specification. Every non-optional non-free - feature has a default value which is used when a value for - the feature is not otherwise specified, either in a target's - requirements or in the user's build request. [A feature's - default value is given by the first value listed in the - feature's declaration. -- move this elsewhere - dwa] - - - - symmetric - - A symmetric feature's default value is not automatically - included in build variants. Normally - a feature only generates a subvariant directory when its - value differs from the value specified by the build variant, - leading to an assymmetric subvariant directory structure for - certain values of the feature. A symmetric feature, when - relevant to the toolset, always generates a corresponding - subvariant directory. - - - - path - - The value of a path feature specifies a path. The path is - treated as relative to the directory of Jamfile where path - feature is used and is translated appropriately by the build - system when the build is invoked from a different - directory - - - - implicit - - Values of implicit features alone identify the feature. - For example, a user is not required to write - "<toolset>gcc", but can simply write "gcc". Implicit - feature names also don't appear in variant paths, although - the values do. Thus: bin/gcc/... as opposed to - bin/toolset-gcc/.... There should typically be only a few - such features, to avoid possible name clashes. - - - - composite - - Composite features actually correspond to groups of - properties. For example, a build variant is a composite - feature. When generating targets from a set of build - properties, composite features are recursively expanded and - added to the build property set, so rules can find - them if neccessary. Non-composite non-free features override - components of composite features in a build property set. - - - - link-incompatible - - See below. - - - - dependency - - The value of dependency feature if a target reference. - When used for building of a main target, the value of - dependency feature is treated as additional dependency. - - For example, dependency features allow to state that - library A depends on library B. As the result, whenever an - application will link to A, it will also link to B. - Specifying B as dependency of A is different from adding B to - the sources of A. - - - - Features which are neither free nor incidental are called - base features. - - TODO: document active features.. - -
-
- Feature Declaration - - The low-level feature declaration interface is the - feature rule from the - feature module: - - -rule feature ( name : allowed-values * : attributes * ) - - - A feature's allowed-values may be extended wit The build -system will provide high-level rules which define features in terms -of valid and useful combinations of attributes. - - -
-
- -
- Build Variants - - -A build variant, or (simply variant) is a special kind of composite - feature which automatically incorporates the default values of - features that . Typically you'll want at least two separate - variants: one for debugging, and one for your release code. [ - Volodya says: "Yea, we'd need to mention that it's a composite - feature and describe how they are declared, in pacticular that - default values of non-optional features are incorporated into - build variant automagically. Also, do we wan't some variant - inheritance/extension/templates. I don't remember how it works in - V1, so can't document this for V2.". Will clean up soon -DWA ] - - -
- Link compatible and incompatible properties - - When the build system tries to generate a target (such as - library dependency) matching a given build request, it may find - that an exact match isn't possible — for example, the - target may impose additonal build requirements. We need to - determine whether a buildable version of that target can actually - be used. - - The build request can originate in many ways: it may come - directly from the user's command-line, from a dependency of a - main target upon a library, or from a dependency of a target upon - an executable used to build that target, for example. For each - way, there are different rules whether we can use a given - subvariant or not. The current rules are described below. - - Two property sets are called link-compatible when - targets with those property sets can be used interchangably. In - turn, two property sets are link compatible when there's no - link-incompatible feature which has different values in those - property sets. - - When building of a main target is requested from a command - line or some project, link-compatibility is not considered. When - building is requested by other main target, via sources or - dependency properties, the requested and actual property sets - must be link-compatible, otherwise a warning is produced. - - Rationale:Link-compatibility is not considered when - main target is requested by a project, because it causes problems - in practice. For example, some parts of a project might be - single-threaded, while others — multi-threaded. They are - not link-compatible, but they are not linked, either. So, there's - no need to issue error or warning. The errors used to be - generated, and only caused problems. - -
-
- Definition of property refinement - - When a target with certain properties is requested, and that - target requires some set of properties, it is needed to find the - set of properties to use for building. This process is called - property refinement and is performed by these rules - - - - - If original properties and required properties are not - link-compatible, refinement fails. - - - - - - Each property in the required set is added to the original - property set - - - - - - If the original property set includes property with a different - value of non free feature, that property is removed. - - - -
- -
- Conditional properties - - Sometime it's desirable to apply certain requirements only for - specific combination of other properties. For example, one of - compilers that you use issues a poinless warning that you want to - suppress by passing a command line option to it. You would not - want to pass that option to other compilers. Condititional - properties allow to do that. Their systax is: - - -property ( "," property ) * ":" property - - - -For example, the problem above would be solved by: - - -exe hello : hello.cpp : <toolset>yfc:<cxxflags>-disable-pointless-warning ; - - - -
-
- -
- Initialization - - bjam's first job upon startup is to load the Jam code which - implements the build system. To do this, it searches for a file - called "boost-build.jam", first in the invocation directory, then - in its parent and so forth up to the filesystem root, and finally - in the directories specified by the environment variable - BOOST_BUILD_PATH. When found, the file is interpreted, and should - specify the build system location by calling the boost-build - rule: - - -rule boost-build ( location ? ) - - - -If location is a relative path, it is treated as relative to -the directory of boost-build.jam. The directory specified by -location and directories in BOOST_BUILD_PATH are then searched for -a file called bootstrap.jam which is interpreted and is expected to -bootstrap the build system. This arrangement allows the build -system to work without any command-line or environment variable -settings. For example, if the build system files were located in a -directory "build-system/" at your project root, you might place a -boost-build.jam at the project root containing: - - -boost-build build-system ; - - -In this case, running bjam anywhere in the project tree will -automatically find the build system. - - The default "bootstrap.jam", after loading some standard - definitions, loads two files, which can be provided/customised by - user: "site-config.jam" and "user-config.jam". - - Locations where those files a search are summarized below: - -
- Search paths for configuration files - - - - - - - - site-config.jam - - user-config.jam - - - - - - - Linux - - - /etc - $HOME - $BOOST_BUILD_PATH - - - - $HOME - $BOOST_BUILD_PATH - - - - - Windows - - - $SystemRoot - $HOME - $BOOST_BUILD_PATH - - - - $HOME - $BOOST_BUILD_PATH - - - - -
- - -Boost.Build comes with default versions of those files, - which can serve as templates for customized versions. - - -
-
- Command line - - The command line may contain: - - - Jam options, - - Boost.Build options, - - Command line arguments - - -
- Command line arguments - - - Command line arguments specify targets and build - request using the following rules. - - - - - - An argument which does not contain slashes or the "=" - symbol is either a value of an implicit feature, or target to - be built. It is taken to be value of a feature if appropriate - feature exists. Otherwise, it is considered a target id. Special target name "clean" - has the same effect as "--clean" option. - - - - - - An argument with either slashes or the "=" symbol specifies - a number of build - request - elements. In the simplest form, it's just a set of properties, - separated by slashes, which become a single build request - element, for example: - - -borland/<runtime-link>static - - -More complex form is used to save typing. For example, -instead of - - -borland/runtime-link=static borland/runtime-link=dynamic - - -one can use - - -borland/runtime-link=static,dynamic - - -Exactly, the conversion from argument to build request -elements is performed by (1) splitting the argument at each slash, -(2) converting each split part into a set of properties and (3) -taking all possible combination of the property sets. Each split -part should have the either the form - - -feature-name=feature-value1[","feature-valueN]* - - -or, in case of implict feature - - -feature-value1[","feature-valueN;]* - - -and will be converted into property set - - -<feature-name>feature-value1 .... <feature-name>feature-valueN - - - - - - - -For example, the command line - - -target1 debug gcc/runtime-link=dynamic,static - - -would cause target called target1 to be rebuild in -debug mode, except that for gcc, both dynamically and statically -linked binaries would be created. - - -
-
- Command line options - - All of the Boost.Build options start with the "--" prefix. - They are described in the following table. - - - Command line options - - - - - Option - - Description - - - - - - --version - - Prints information on Boost.Build and Boost.Jam - versions. - - - - --help - - Access to the online help system. This prints general - information on how to use the help system with additional - --help* options. - - - - --clean - - Removes everything instead of building. Unlike - clean target in make, it is possible to clean only - some targets. - - - - --debug - - Enables internal checks. - - - - --dump-projects - - Cause the project structure to be output. - - - - --no-error-backtrace - - Don't print backtrace on errors. Primary usefull for - testing. - - - - --ignore-config - - Do not load site-config.jam and - user-config.jam - - - -
- -
-
- -
- Build request - - -
- -
- Build process - - Construction of each main target begins with finding - properties for this main target. They are found by - processing both build request, and target requirements, - which give properties needed for the target to build. For - example, a given main target might require certian defines, or - will not work unless compiled in multithreaded mode. The process - of finding properties for main target is described in property refinement. - - After that, dependencies (i.e. other main targets) are build - recursively. Build request for dependencies is not always equal - to those of dependent — certain properties are dropped and - user can explicitly specify desired properties for dependencies. - See - propagated features and for details. - - When dependencies are constructed, the dependency graph for - this main target and for this property set is created, which - describes which files need to be created, on which other files - they depend and what actions are needed to construct those files. - There's more that one method, and user can define new ones, but - usually, this involves generators and target - types. - - Target type is just a way to classify targets. For example, - there are builtin types EXE, OBJ and - CPP. Generators are objects - that know how to convert between different target type. When a - target of a given type must be created, all generators for that - type, which can handle needed properties, are found. Each is - passed the list of sources, and either fails, or returns a - dependency graph. If a generator cannot produce desired type from - given sources, it may try to recursively construct types that it - can handle from the types is was passed. This allows to try all - possible transformations. When all generators are tried, a - dependency graph is selected. - - Finally, the dependency graph is passed to underlying - Boost.Jam program, which runs all actions needed to bring all - main targets up-to date. At this step, implicit dependencies are - also scanned and accounted for, as described "here." [ link? ] - - Given a list of targets ids and a build request, building goes - this way. First, for each id we obtain the abstract targets - corresponding to it. This also loads all necessary projects. If - no target id is given, project in the current directory is used. - Build request is expanded, and for each resulting property set, - the generate method of all targets is called, which - yields a list of virtual targets. After that all virtual targets - are actualized, and target "all" is set to depend on all created - actual targets. Lastly, depending on whether --clean - option was given, either target "all" or target "clean" is - updated. Generation of virtual target from abstract one is - performed as follows: - - - - For project targets, all of main targets are generated - with the same properties. Then all projects referred via - "build-project" are generated as well. If it's not possible - to refine requested properties with project requirements, the - project is skipped. - - - It is possible to disable building of certain target using the - explicit rule, available in all project - modules. The syntax is - - -rule explicit ( target-name ) - - - If this rule is invoked on a target, it will be built only -when it's explicitly requested on the command line. - - - - - - For main target, with several alternatives, one of them is - selected as described below. - If there's only one - alternative, it's used unconditionally. - - - - - All main target alternatives which requirements are - satisfied by the build request are enumerated. - - - - - - If there are several such alternatives, the one which - longer requirements list is selected. - - - - - - - - - For the selected alternative - - - - - Each target reference in the source list are - recursively constructed. - - - - - - Properties are refined with alternative's requirements, - and active features in the resulting set are executed. - - - - - - Conditional properties are evaluated. - - - - - - The dependency graph for the target is constructed in a - way which depends on the kind of main target, typically - using generators. - - - - - - - - - If, when building sources, the properties on recursively - created targets are not link-compatibile with build properties, - a warning is issued. - - - - -
- -
- Alternative selection - - When there are several alternatives, one of them must be - selected. The process is as follows: - - - - - For each alternative condition is defined - as the set of base properies in requirements. [Note: it might be - better to explicitly specify the condition explicitly, as in - conditional requirements]. - - - - - - An alternative is viable only if all properties in condition - are present in build request. - - - - - - If there's one viable alternative, it's choosen. Otherwise, - an attempt is made to find one best alternative. An alternative - a is better than another alternative b, iff set of properties - in b's condition is stict subset of the set of properities of - 'a's condition. If there's one viable alternative, which is - better than all other, it's selected. Otherwise, an error is - reported. - - - - -
- -
- Generated headers - - Usually, Boost.Build handles implicit dependendies completely - automatically. For example, for C++ files, all #include - statements are found and handled. The only aspect where user help - might be needed is implicit dependency on generated files. - - By default, Boost.Build handles such dependencies within one - main target. For example, assume that main target "app" has two - sources, "app.cpp" and "parser.y". The latter source is converted - into "parser.c" and "parser.h". Then, if "app.cpp" includes - "parser.h", Boost.Build will detect this dependency. Moreover, - since "parser.h" will be generated into a build directory, the - path to that directory will automatically added to include - path. - - Making this mechanism work across main target boundaries is - possible, but imposes certain overhead. For that reason, if - there's implicit dependency on files from other main targets, the - <implicit-dependency> [ link ] feature must - be used, for example: - - -lib parser : parser.y ; -exe app : app.cpp : <implicit-dependency>parser ; - - - -The above example tells the build system that when scanning -all sources of "app" for implicit-dependencies, it should consider -targets from "parser" as potential dependencies. - - -
-
- Generators - - To construct a main target with given properties from sources, - it is required to create a dependency graph for that main target, - which will also include actions to be run. The algorithm for - creating the dependency graph is described here. - - The fundamental concept is generator. If encapsulates - the notion of build tool and is capable to converting a set of - input targets into a set of output targets, with some properties. - Generator matches a build tool as closely as possible: it works - only when the tool can work with requested properties (for - example, msvc compiler can't work when requested toolset is gcc), - and should produce exactly the same targets as the tool (for - example, if Borland's linker produces additional files with debug - information, generator should also). - - Given a set of generators, the fundamental operation is to - construct a target of a given type, with given properties, from a - set of targets. That operation is performed by rule - generators.construct and the used algorithm is described - below. - -
- Selecting and ranking viable generators - - Each generator, in addition to target types that it can - produce, have attribute that affects its applicability in - particular sitiation. Those attributes are: - - - - - Required properties, which are properties absolutely - necessary for the generator to work. For example, generator - encapsulating the gcc compiler would have <toolset>gcc as - required property. - - - - - - Optional properties, which increase the generators - suitability for a particual build. - - - - - - Generator's required and optional properties may not include - either free or incidental properties. (Allowing this would - greatly complicate caching targets). - - - When trying to construct a target, the first step is to select - all possible generators for the requested target type, which - required properties are a subset of requested properties. - Generators which were already selected up the call stack are - excluded. In addition, if any composing generators were selected - up the call stack, all other composing generators are ignored - (TODO: define composing generators). The found generators - assigned a rank, which is the number of optional properties - present in requested properties. Finally, generators with highest - rank are selected for futher processing. - -
-
- Running generators - - When generators are selected, each is run to produce a list of - created targets. This list might include targets which are not of - requested types, because generators create the same targets as - some tool, and tool's behaviour is fixed. (Note: should specify - that in some cases we actually want extra targets). If generator - fails, it returns an empty list. Generator is free to call - 'construct' again, to convert sources to the types it can handle. - It also can pass modified properties to 'constuct'. However, a - generator is not allowed to modify any propagated properties, - otherwise when actually consuming properties we might discover - that the set of propagated properties is different from what was - used for building sources. - - For all targets which are not of requested types, we try to - convert them to requested type, using a second call to - construct. This is done in order to support - transformation sequences where single source file expands to - several later. See this - message for details. - -
- -
- Selecting dependency graph - - - After all generators are run, - it is necessary to decide which of successfull invocation will be - taken as final result. At the moment, this is not done. Instead, - it is checked whether all successfull generator invocation - returned the same target list. Error is issued otherwise. - - -
- -
- Property adjustment - - Because target location is determined by the build system, it - is sometimes necessary to adjust properties, in order to not - break actions. For example, if there's an action which generates - a header, say "a_parser.h", and a source file "a.cpp" which - includes that file, we must make everything work as if a_parser.h - is generated in the same directory where it would be generated - without any subvariants. - - Correct property adjustment can be done only after all targets - are created, so the approach taken is: - - - - - When dependency graph is constructed, each action can be - assigned a rule for property adjustment. - - - - - - When virtual target is actualized, that rule is run and - return the final set of properties. At this stage it can use - information of all created virtual targets. - - - - - In case of quoted includes, no adjustment can give 100% - correct results. If target dirs are not changed by build system, - quoted includes are searched in "." and then in include path, - while angle includes are searched only in include path. When - target dirs are changed, we'd want to make quoted includes to be - search in "." then in additional dirs and then in the include - path and make angle includes be searched in include path, - probably with additional paths added at some position. Unless, - include path already has "." as the first element, this is not - possible. So, either generated headers should not be included - with quotes, or first element of include path should be ".", - which essentially erases the difference between quoted and angle - includes. Note: there only way to get "." as include path - into compiler command line is via verbatim compiler option. In - all other case, Boost.Build will convert "." into directory where - it occurs. - -
- -
- Transformations cache - - - Under certain conditions, an - attempt is made to cache results of transformation search. First, - the sources are replaced with targets with special name and the - found target list is stored. Later, when properties, requested - type, and source type are the same, the store target list is - retrieved and cloned, with appropriate change in names. - - -
-
- -
- - - Boost.Build development - - [ TODO ] - - - - Frequently Asked Questions - -
- I'm getting "Duplicate name of actual target" error. - What does it mean? - - - - The most likely case is that you're trying to - compile the same file twice, with almost the same, - but differing properties. For example: - - -exe a : a.cpp : <include>/usr/local/include ; -exe b : a.cpp ; - - - - - - The above snippet requires two different compilations - of 'a.cpp', which differ only in 'include' property. - Since the 'include' property is free, Boost.Build - can't generate two ojects files into different directories. - On the other hand, it's dangerous to compile the file only - once -- maybe you really want to compile with different - includes. - - - - To solve this issue, you need to decide if file should - be compiled once or twice. - - - - Two compile file only once, make sure that properties - are the same: - - -exe a : a.cpp : <include>/usr/local/include ; -exe b : a.cpp : <include>/usr/local/include ; - - - - If changing the properties is not desirable, for example - if 'a' and 'b' target have other sources which need - specific properties, separate 'a.cpp' into it's own target: - - -obj a_obj : a.cpp : <include>/usr/local/include ; -exe a : a_obj ; - - - - To compile file twice, you can make the object file local - to the main target: - - - exe a : [ obj a_obj : a.cpp ] : <include>/usr/local/include ; - exe b : [ obj a_obj : a.cpp ] ; - - - - - A good question is why Boost.Build can't use some of the above - approaches automatically. The problem is that such magic would - require additional implementation complexities and would only - help in half of the cases, while in other half we'd be silently - doing the wrong thing. It's simpler and safe to ask user to - clarify his intention in such cases. - -
- - -
- - - - Extender Manual - -
- Introduction - - This document explains how to extend Boost.Build to accomodate - your local requirements. Let's start with quite simple, but - realistic example. - - 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: - - - - - Write the template of the code to be generated, leaving - placeholders at the points which will change - - - - - - Access the template in your application and replace - placeholders with appropriate text. - - - - - Write the result. - - - - 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. - - Let's see what Boost.Build can do. - - First off, Boost.Build has no idea about "verbatim files". So, - you must register a new type. The following code does it: - - -import type ; -type.register VERBATIM : verbatim ; - - - 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 VERBATIM. - - 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 generator. - - First, you say that generator 'inline-file' is able to convert - VERBATIM type into C++: - - -import generators ; -generators.register-standard verbatim.inline-file : VERBATIM : CPP ; - - - Second, you must specify the commands to be run to actually - perform convertion: - - -actions inline-file -{ - "./inline-file.py" $(<) $(>) -} - - - - 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: - - -exe codegen : codegen.cpp class_template.verbatim usage.verbatim ; - - - -The verbatim files will be automatically converted into C++ -and linked it. - - - The complete code is available in example/customization - directory. - -
-
- Target types - -
- -
- Tools - -
- -
- Main target rules - -
- -
- Scanners - -
-
- - - Boost Build System V2 recipes - -
- Targets in site-config.jam - - It is desirable to declare standard libraries available on a - given system. Putting target declaration in Jamfile is not really - good, since locations of the libraries can vary. The solution is - to put the following to site-config.jam. - - -import project ; -project.initialize $(__name__) ; -project site-config ; -lib zlib : : <name>z ; - - - The second line allows this module to act as project. The - third line gives id to this project — it really has no location - and cannot be used otherwise. The fourth line just declares a - target. Now, one can write - - -exe hello : hello.cpp /site-config//zlib ; - - - in any Jamfile. - -
-
- - - Boost.Build v2 architecture - - - This document is work-in progress. Don't expect much from it - yet. - - -
- Targets - - 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. - - 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 "next section". - [ link? ] Note:File targets are not - the same as targets in Jam sense; the latter are created from - file targets at the latest possible moment. Note:"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. - -
- Dependency scanning - - Dependency scanning is the process of finding implicit - dependencies, like "#include" statements in C++. The requirements - for right dependency scanning mechanism are: - - - - - Support for different scanning algorithms. C++ and XML have - quite different syntax for includes and rules for looking up - included files. - - - - - - Ability to scan the same file several times. For example, - single C++ file can be compiled with different include - paths. - - - - - - Proper detection of dependencies on generated files. - - - - - - Proper detection of dependencies from generated file. - - - - -
- Support for different scanning algorithms - - Different scanning algorithm are encapsulated by objects - called "scanners". Please see the documentation for "scanner" - module for more details. - -
- -
- Ability to scan the same file several times - - 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. - - The solution in Boost.Build is straigtforward. When a virtual - target is converted to bjam target (via - virtual-target.actualize method), we specify the scanner - object to be used. The actualize method will create different - bjam targets for different scanners. - - 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. - - 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: - - -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 --------------------------------+ - - -
-
- Proper detection of dependencies on generated files. - - This requirement breaks down to the following ones. - - - - - 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". - - - - - - 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. - - - - - 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: - - - - - If there's file "a.h" in that directory, or - - - - - - If there's a target called "a.h", which will be generated - to that directory. - - - - - 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. - - 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: - - -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] - - - -In this case, Jam thinks all header.h target are not -realated. The right dependency graph might be: - - -a.cpp ---- - \ - \ - >----> <d2>header.h --------> header.y - / [generated in d2] - / -b.cpp ---- - - -or - - -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] - - - - -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. - - - 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: - - - - - The main target to which compiled file belongs is found. - - - - - - 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. - - - - - - All directories where files belonging to those main target - will be generated are added to the include path. - - - - - After this is done, dependencies are found by the approach - explained previously. - - 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. - - For target types other than C++, adding of include paths must - be implemented anew. - -
-
- Proper detection of dependencies from generated files - - 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. - - 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. - - In order to understand the rest of this section, you better - read some details about jam dependency scanning, available - - at this link. - - Whenever a target is updated, Boost.Jam rescans it for - includes. Consider this graph, created before any actions are - run. - - -A -------> C ----> C.pro - / -B --/ C-includes ---> D - - - -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. - - - 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. - - 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. - - Note also that internal nodes are sometimes updated too. - Consider this dependency graph: - - -a.o ---> a.cpp - a.cpp-includes --> a.h (scanned) - a.h-includes ------> a.h (generated) - | - | - a.pro <-------------------------------------------+ - - - 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. - - 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. - - - - The remainder of this document is not indended to be read at - all. This will be rearranged in future. - - - -
- File targets - - - 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 - virtual-target module. - - -
- Types - - A file target can be given a file, which determines - what transformations can be applied to the file. The - type.register rule declares new types. File type can - also be assigned a scanner, which is used to find implicit - dependencies. See "dependency scanning" [ link? ] below. -
-
- -
- Target paths - - To distinguish targets build with different properties, they - are put in different directories. Rules for determining target - paths are given below: - - - - - All targets are placed under directory corresponding to the - project where they are defined. - - - - - - Each non free, non incidental property cause an additional - element to be added to the target path. That element has the - form <feature-name>-<feature-value> for - ordinary features and <feature-value> for - implicit ones. [Note about composite features]. - - - - - - 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 main_target-<name> is added to - the target path. Note:It would be nice to completely - track free features also, but this appears to be complex and - not extremely needed. - - - - - For example, we might have these paths: - - -debug/optimization-off -debug/main-target-a - - -
-
-
-
-
- -