From 1f41cd7eebc88f3374a88d21ad39644fa3589b5e Mon Sep 17 00:00:00 2001 From: Christopher Currie Date: Thu, 5 Feb 2004 04:09:47 +0000 Subject: [PATCH] Converting Boost.Build v2 User Manual to BoostBook * userman.xml - initial BoostBook version * Jamfile.v2 - build rules for user manual [SVN r22165] --- v2/doc/Jamfile.v2 | 3 + v2/doc/userman.xml | 2778 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2781 insertions(+) create mode 100644 v2/doc/Jamfile.v2 create mode 100644 v2/doc/userman.xml diff --git a/v2/doc/Jamfile.v2 b/v2/doc/Jamfile.v2 new file mode 100644 index 000000000..16c9efe48 --- /dev/null +++ b/v2/doc/Jamfile.v2 @@ -0,0 +1,3 @@ +project tools/build/v2/doc ; + +boostbook userman : userman.xml ; diff --git a/v2/doc/userman.xml b/v2/doc/userman.xml new file mode 100644 index 000000000..ef1e23210 --- /dev/null +++ b/v2/doc/userman.xml @@ -0,0 +1,2778 @@ + + + + + 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: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RuleSemantic
project + Define project attributes.
use-projectMake another project known.
build-projectBuild another project when this one is built.
explicitStates that the target should be built only by explicit + request.
globTakes a list of wildcards, and returns the list of files + which match any of the wildcards.
+ + Each project is also associated with project root. + That's a root for a tree of projects, which specifies some global + properties. + +
+ 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 + ; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeName for the 'project' ruleDefault valueHandling by the 'project' rule
Project idnonenoneAssigned from the first parameter of the 'project' rule. + It is assumed to denote absolute project id.
Source locationsource-locationThe location of jamfile for the projectSets to the passed value
RequirementsrequirementsThe parent's requirementsThe parent's requirements are refined with the passed + requirement and the result is used as the project + requirements.
Default builddefault-buildnoneSets to the passed value
Build directorybuild-dirIf parent has a build dir set, the value of it, joined + with the relative path from parent to the current project. + Otherwise, emptySets to the passed value, interpreted as relative to the + project's location.
+
+ +
+ 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.jamuser-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 +
OptionDescription
--versionPrints information on Boost.Build and Boost.Jam + versions.
--helpAccess to the online help system. This prints general + information on how to use the help system with additional + --help* options.
--cleanRemoves everything instead of building. Unlike + clean target in make, it is possible to clean only + some targets.
--debugEnables internal checks.
--dump-projectsCause the project structure to be output.
--no-error-backtraceDon't print backtrace on errors. Primary usefull for + testing.
--ignore-configDo 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 + + [ TODO ] + + + + + 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 + + +
+
+
+
+
+ +