From a281ef28ff13135b9a8a85b30844bb553596f7bb Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Thu, 10 Oct 2002 13:47:30 +0000 Subject: [PATCH] Flush all of documentation changes. [SVN r15860] --- boost_build_v2.html | 636 ++++++++++++++++++++++++++++++++--------- v2/boost_build_v2.html | 636 ++++++++++++++++++++++++++++++++--------- 2 files changed, 1004 insertions(+), 268 deletions(-) diff --git a/boost_build_v2.html b/boost_build_v2.html index 6711fb773..68d1d650b 100644 --- a/boost_build_v2.html +++ b/boost_build_v2.html @@ -22,6 +22,10 @@ table { align: center; border: thin; } +

- This preliminary reference is intended to document everything - currently implemeneted, but is not yet ready for any practical - use. + This preliminary reference is intended to document everything currently + implemeneted, but is not yet ready for any practical use.


@@ -46,15 +49,20 @@
+
Overview
+
Features and properties
-
-
Defintions -
Feature Attributes -
Feature Declaration -
- +
+
Defintions
+ +
Feature Attributes
+ +
Feature Declaration
+
+
+
Build Variants
Subfeatures
@@ -73,85 +81,161 @@

+

Installation

+ When using package management or installers, Boost.Build is ready to work + instantly. In other case, two steps are required: + +
    +
  1. Place the Boost.Jam binary, called "bjam", somewhere in your + PATH.
  2. + +
  3. + Specify the location of Boost.Build files. You can either set + environmental variable BOOST_BUILD_PATH, or create, at the + top of your project, a file called boost-build.jam, with a + single line: +
    +boost-build /path/to/boost.build ;
    +
    + The directory "examples" in the distribution already has this file, + so you can build projects there and add new without doing anything. +
  4. +
+ +

To verify your installation, you can use bjam --version at + the command line.

+

Reference

+ 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. They main purpose is organization: related targets can + be places in one project, then can be build together, or share some + definitions. Main targets and project are described mostly in declarative + fashion. To make some use of them, user issues build request, which specifies what targets user + wants to build, and what properties are desirable. Build request is not + necessary explicit. Invoking the build system without parameters will + build the project in current directory with defauly properties. The + properties describe various aspects of constructed objects. For + portability, they are specified in a normalized form, for example +
+<optimization>full <inlining>off
+
+ Depending on used compiler, this will be translated into appropriate + flags. 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 then, + 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 target reference 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 type. + 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 main 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 type 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.

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.

+

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 may not contain the - '<', ':', or '=' characters.

+

Each feature in a build configuration has one or more associated + values. Feature values may not contain the '<', + ':', or '=' characters.

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 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 value-string is a string of the form - value-subvalue1-subvalue2...-subvalueN, where value is - a feature value and subvalue1...subvalueN are values of related - 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.

+ value-subvalue1-subvalue2...-subvalueN, where + value is a feature value and + subvalue1...subvalueN are values of related + 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 where no property appears twice, for - instance: <toolset>gcc <runtime-link>static. +

A property set is a set of properties where no property + appears twice, 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 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. +

A build specification is a property set which fully describes + the set of features used to build a target.

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. - + 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.

+ - +

TODO: document active features..

Feature Declaration

- - The low-level feature declaration interface is the - feature rule from the feature module: - + 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. + 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 ] - + 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 ] @@ -302,7 +378,7 @@ it works in V1, so can't document this for V2.". Will clean up soon -DWA ] requested and actual properties are link-compatible, it's OK. Otherwise, it's an error.

-

Definition of property refinement

+

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 @@ -320,6 +396,22 @@ it works in V1, so can't document this for V2.". Will clean up soon -DWA ] 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 @@ -366,7 +458,9 @@ it works in V1, so can't document this for V2.". Will clean up soon -DWA ]

  • 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.
  • + 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 @@ -430,6 +524,27 @@ borland/runtime-link=static,dynamic + + --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 one some targets. + + --debug @@ -441,14 +556,6 @@ borland/runtime-link=static,dynamic Cause the project structure to be output. - - - --help - - Access to the online help system. This prints general - information on how to use the help system with additional --help* - options. - @@ -590,12 +697,33 @@ borland/runtime-link=static,dynamic

    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. 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.

    +

    Main targets and main target alternatives

    Main target is a named entity which can be build, for example a named executable file. To declare a main target, user invokes some of the main target - rules, passing it things like list of source and requirement.

    + rules, passing it things like list of sources and requirements.

    It is possible to have different list of sources for different toolsets, therefore it is possible to invoke main target rules several @@ -645,9 +773,9 @@ borland/runtime-link=static,dynamic After that, the target given by local-target-name in the found project is used. -

    Target reference is used to specify a source target, and may - additionally specify desired properties for that target. It has this - syntax:

    +

    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
    @@ -669,6 +797,22 @@ borland/runtime-link=static,dynamic
         that project it is used. Otherwise, we just treat the target reference as
         a file name.

    +

    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 below. +

    Target paths

    To distinguish targets build with different properties, they are put @@ -700,24 +844,30 @@ borland/runtime-link=static,dynamic

    +

    Build request

    +

    Build process

    -

    The build works in this way. On startup, the project in the current - directory is read. In turn, it may request building of other projects, - which will be loaded recursively. Parent projects are also loaded to - inherit some of their properties. As the result, a tree of projects is - constructed. After that, the build request is constructed from the - command line. Then, the steps are:

    +

    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:

    -
      -
    1. All of the projects to be build are passed the build request. If - the build request does not satisfy the project's requirements, a - warning is issued and the build of the project is skipped. Projects - mentioned in build-project rule will still be build.
    2. +
        +
      • 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.
      • - An attempts to make all the main targets in the project is performed. - For each main target: + For main target, steps are:
        1. All main target alternatives which requirements are satisfied @@ -735,16 +885,234 @@ borland/runtime-link=static,dynamic
        2. Each target reference in the source list are recursively constructed.
        3. -
        4. The dependency graph for the target is constructed by running - so called matching process, using generated source targets and - ordinary sources.
        5. +
        6. Properties are refined with alternative's requirements, and + active features in the resulting set are executed.
        7. + +
        8. Conditional properties are evaluated.
        9. + +
        10. The dependency graph for the target is constructed in a way + which depends on the kind of main target, typically using + generators.
      • +
      + +

      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:

      + +
        +
      1. 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.
      2. + +
      3. Optional properties, which increase the generators suitability for + a particual build.
      4. +
      + 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:

      + +
        +
      1. When dependency graph is constructed, each action can be assigned a + rule for property adjustment.
      2. + +
      3. 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.
      -

      The dependency graph constructed for each target is build of so called - "virtual targets", which do not yet correspond to jam's targets. It is - therefore converted to jam's dependency graph which is then build.

      +

      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. + +

      Dependency scanning

      + +

      Dependency scanning is the process of finding implicit dependencies + due to "include" statements and similar things. It has to take into + account two things:

      + +
        +
      • Whether includes in a particular file need to be taken into account + depends on actions that use that file. For example, if the action is + "copy file", then includes should be ignored. Another example is when a + file is compiled with two different include paths on different + toolsets.
      • + +
      • It is possible to include generated header. In which case, it may + not yet exist at the time when we scan dependencies.
      • +
      + +

      Dependency scanning is implemented by objects called scanners. See + documentation for the "scanner" module to detail.

      + +

      Regarding the first problem, we really have no choice. We can't treat + the same actual target differently depending on from where it is used. + Therefore, when handling of includes differers depending on actions, we + have to duplicate targets and assign different properties to it.

      + +

      For the reason, when actualizing a virtual target we optionally pass + the needed scanner to the "virtual-target.actualize" method. When no + scanner is passed, a new actual target is created, with it's dependencies + and updating actions set accordingly. When a particular scanner is + specified, a new actual target is created. That target will depend on + target created without scanner. In effect, this will allow to use + different scanners for the same file.

      + +
      Generated headers
      + Let me explain what I find the right semantic, first without any + subvariants. We have a target "a.cpp" which includes "a_parser.h", we + have to search through all include directories, checking: + +
        +
      1. If there's such file there, or
      2. + +
      3. If there's a target of the same name, bound to that dir via + LOCATE_TARGET.
      4. +
      + Jam allows to do 1 via SEARCH variable, but that's not enough. Why can't + we do simpler: first check if there's target of the same name? I.e. + including of "a_parser.h" will already pick generated "a_parser.h", + regardless of search paths? Hmm... just because there's no reason to + assume that. For example, one can have an action which generated some + "dummy" header, for system which don't have the native one. Naturally, we + don't want to depend on that generated headers. To implement proposed + semantic we'd need a new builtin. We can do this in Jam code, but really, + this belongs to core. Using GLOB and jam code would just duplicate + existing binding functionality and be inefficient. New builtin will + accept a name of new target and a list of directories. It will perform + the search as explained above and return either the name of exising + target that it found, or create a new target with that name that it was + passed. So, we'd write something like + +
      +
      +    INCLUDES $(<) : [ SEARCH_FOR_TARGET $(>) : $(SEARCH_PATH) ] ;
      +
      +
      + What shall we do when using subvariants. For user, subvariants must be + more or less transparent. If without subvariant a header was generated to + a certain directory, everything must work. Suppose that file a.cpp + belongs to a dependency graph of main target a. Include paths are + +
      +
      +     "/usr/include" "/home/t" "."
      +
      +
      + We start by finding all places where headers that are part of a's + dependency graph are generated. We insert those places to the include + paths, immediately after ".". For example, we might end with: + +
      +
      +     "/usr/include" "/home/t" "." "build"
      +
      +
      + As a result: + +
        +
      1. File "a.cpp" will be correctly compiled. Note that it's already + necessary to adjust paths to ensure this. We'll have to add target + paths for all generated headers, because determining the exact set of + additional include path for each source -- i.e the set of headers that + it uses --- will be hard.
      2. + +
      3. With the proposed SEARCH_FOR_TARGET rule, dependency on generated + header will work magically --- it would find the "a_parser.h" target + bound via LOCATE_TARGET to "build" and we'll call INCLUDE on that found + target, instread of creating a completely unrelated one.
      4. +

      Last modified: Aug 15, 2002

      diff --git a/v2/boost_build_v2.html b/v2/boost_build_v2.html index 6711fb773..68d1d650b 100644 --- a/v2/boost_build_v2.html +++ b/v2/boost_build_v2.html @@ -22,6 +22,10 @@ table { align: center; border: thin; } +



      @@ -46,15 +49,20 @@
      +
      Overview
      +
      Features and properties
      -
      -
      Defintions -
      Feature Attributes -
      Feature Declaration -
      - +
      +
      Defintions
      + +
      Feature Attributes
      + +
      Feature Declaration
      +
      +
      +
      Build Variants
      Subfeatures
      @@ -73,85 +81,161 @@

      +

      Installation

      + When using package management or installers, Boost.Build is ready to work + instantly. In other case, two steps are required: + +
        +
      1. Place the Boost.Jam binary, called "bjam", somewhere in your + PATH.
      2. + +
      3. + Specify the location of Boost.Build files. You can either set + environmental variable BOOST_BUILD_PATH, or create, at the + top of your project, a file called boost-build.jam, with a + single line: +
        +boost-build /path/to/boost.build ;
        +
        + The directory "examples" in the distribution already has this file, + so you can build projects there and add new without doing anything. +
      4. +
      + +

      To verify your installation, you can use bjam --version at + the command line.

      +

      Reference

      + 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. They main purpose is organization: related targets can + be places in one project, then can be build together, or share some + definitions. Main targets and project are described mostly in declarative + fashion. To make some use of them, user issues build request, which specifies what targets user + wants to build, and what properties are desirable. Build request is not + necessary explicit. Invoking the build system without parameters will + build the project in current directory with defauly properties. The + properties describe various aspects of constructed objects. For + portability, they are specified in a normalized form, for example +
      +<optimization>full <inlining>off
      +
      + Depending on used compiler, this will be translated into appropriate + flags. 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 then, + 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 target reference 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 type. + 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 main 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 type 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.

      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.

      +

      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 may not contain the - '<', ':', or '=' characters.

      +

      Each feature in a build configuration has one or more associated + values. Feature values may not contain the '<', + ':', or '=' characters.

      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 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 value-string is a string of the form - value-subvalue1-subvalue2...-subvalueN, where value is - a feature value and subvalue1...subvalueN are values of related - 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.

      + value-subvalue1-subvalue2...-subvalueN, where + value is a feature value and + subvalue1...subvalueN are values of related + 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 where no property appears twice, for - instance: <toolset>gcc <runtime-link>static. +

      A property set is a set of properties where no property + appears twice, 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 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. +

      A build specification is a property set which fully describes + the set of features used to build a target.

      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. - + 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.

        +

        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.

        +

        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.

      • 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 +

        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.

      • @@ -159,12 +243,12 @@
      • 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:

        +

        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
         
        @@ -174,26 +258,25 @@
      • 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]

        +

        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.

        +

        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.

      • @@ -242,36 +325,29 @@
      - +

      TODO: document active features..

      Feature Declaration

      - - The low-level feature declaration interface is the - feature rule from the feature module: - + 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. + 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 ] - + 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 ] @@ -302,7 +378,7 @@ it works in V1, so can't document this for V2.". Will clean up soon -DWA ] requested and actual properties are link-compatible, it's OK. Otherwise, it's an error.

      -

      Definition of property refinement

      +

      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 @@ -320,6 +396,22 @@ it works in V1, so can't document this for V2.". Will clean up soon -DWA ] 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 @@ -366,7 +458,9 @@ it works in V1, so can't document this for V2.". Will clean up soon -DWA ]

  • 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.
  • + 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 @@ -430,6 +524,27 @@ borland/runtime-link=static,dynamic + + --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 one some targets. + + --debug @@ -441,14 +556,6 @@ borland/runtime-link=static,dynamic Cause the project structure to be output. - - - --help - - Access to the online help system. This prints general - information on how to use the help system with additional --help* - options. - @@ -590,12 +697,33 @@ borland/runtime-link=static,dynamic

    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. 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.

    +

    Main targets and main target alternatives

    Main target is a named entity which can be build, for example a named executable file. To declare a main target, user invokes some of the main target - rules, passing it things like list of source and requirement.

    + rules, passing it things like list of sources and requirements.

    It is possible to have different list of sources for different toolsets, therefore it is possible to invoke main target rules several @@ -645,9 +773,9 @@ borland/runtime-link=static,dynamic After that, the target given by local-target-name in the found project is used. -

    Target reference is used to specify a source target, and may - additionally specify desired properties for that target. It has this - syntax:

    +

    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
    @@ -669,6 +797,22 @@ borland/runtime-link=static,dynamic
         that project it is used. Otherwise, we just treat the target reference as
         a file name.

    +

    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 below. +

    Target paths

    To distinguish targets build with different properties, they are put @@ -700,24 +844,30 @@ borland/runtime-link=static,dynamic

    +

    Build request

    +

    Build process

    -

    The build works in this way. On startup, the project in the current - directory is read. In turn, it may request building of other projects, - which will be loaded recursively. Parent projects are also loaded to - inherit some of their properties. As the result, a tree of projects is - constructed. After that, the build request is constructed from the - command line. Then, the steps are:

    +

    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:

    -
      -
    1. All of the projects to be build are passed the build request. If - the build request does not satisfy the project's requirements, a - warning is issued and the build of the project is skipped. Projects - mentioned in build-project rule will still be build.
    2. +
        +
      • 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.
      • - An attempts to make all the main targets in the project is performed. - For each main target: + For main target, steps are:
        1. All main target alternatives which requirements are satisfied @@ -735,16 +885,234 @@ borland/runtime-link=static,dynamic
        2. Each target reference in the source list are recursively constructed.
        3. -
        4. The dependency graph for the target is constructed by running - so called matching process, using generated source targets and - ordinary sources.
        5. +
        6. Properties are refined with alternative's requirements, and + active features in the resulting set are executed.
        7. + +
        8. Conditional properties are evaluated.
        9. + +
        10. The dependency graph for the target is constructed in a way + which depends on the kind of main target, typically using + generators.
      • +
      + +

      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:

      + +
        +
      1. 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.
      2. + +
      3. Optional properties, which increase the generators suitability for + a particual build.
      4. +
      + 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:

      + +
        +
      1. When dependency graph is constructed, each action can be assigned a + rule for property adjustment.
      2. + +
      3. 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.
      -

      The dependency graph constructed for each target is build of so called - "virtual targets", which do not yet correspond to jam's targets. It is - therefore converted to jam's dependency graph which is then build.

      +

      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. + +

      Dependency scanning

      + +

      Dependency scanning is the process of finding implicit dependencies + due to "include" statements and similar things. It has to take into + account two things:

      + +
        +
      • Whether includes in a particular file need to be taken into account + depends on actions that use that file. For example, if the action is + "copy file", then includes should be ignored. Another example is when a + file is compiled with two different include paths on different + toolsets.
      • + +
      • It is possible to include generated header. In which case, it may + not yet exist at the time when we scan dependencies.
      • +
      + +

      Dependency scanning is implemented by objects called scanners. See + documentation for the "scanner" module to detail.

      + +

      Regarding the first problem, we really have no choice. We can't treat + the same actual target differently depending on from where it is used. + Therefore, when handling of includes differers depending on actions, we + have to duplicate targets and assign different properties to it.

      + +

      For the reason, when actualizing a virtual target we optionally pass + the needed scanner to the "virtual-target.actualize" method. When no + scanner is passed, a new actual target is created, with it's dependencies + and updating actions set accordingly. When a particular scanner is + specified, a new actual target is created. That target will depend on + target created without scanner. In effect, this will allow to use + different scanners for the same file.

      + +
      Generated headers
      + Let me explain what I find the right semantic, first without any + subvariants. We have a target "a.cpp" which includes "a_parser.h", we + have to search through all include directories, checking: + +
        +
      1. If there's such file there, or
      2. + +
      3. If there's a target of the same name, bound to that dir via + LOCATE_TARGET.
      4. +
      + Jam allows to do 1 via SEARCH variable, but that's not enough. Why can't + we do simpler: first check if there's target of the same name? I.e. + including of "a_parser.h" will already pick generated "a_parser.h", + regardless of search paths? Hmm... just because there's no reason to + assume that. For example, one can have an action which generated some + "dummy" header, for system which don't have the native one. Naturally, we + don't want to depend on that generated headers. To implement proposed + semantic we'd need a new builtin. We can do this in Jam code, but really, + this belongs to core. Using GLOB and jam code would just duplicate + existing binding functionality and be inefficient. New builtin will + accept a name of new target and a list of directories. It will perform + the search as explained above and return either the name of exising + target that it found, or create a new target with that name that it was + passed. So, we'd write something like + +
      +
      +    INCLUDES $(<) : [ SEARCH_FOR_TARGET $(>) : $(SEARCH_PATH) ] ;
      +
      +
      + What shall we do when using subvariants. For user, subvariants must be + more or less transparent. If without subvariant a header was generated to + a certain directory, everything must work. Suppose that file a.cpp + belongs to a dependency graph of main target a. Include paths are + +
      +
      +     "/usr/include" "/home/t" "."
      +
      +
      + We start by finding all places where headers that are part of a's + dependency graph are generated. We insert those places to the include + paths, immediately after ".". For example, we might end with: + +
      +
      +     "/usr/include" "/home/t" "." "build"
      +
      +
      + As a result: + +
        +
      1. File "a.cpp" will be correctly compiled. Note that it's already + necessary to adjust paths to ensure this. We'll have to add target + paths for all generated headers, because determining the exact set of + additional include path for each source -- i.e the set of headers that + it uses --- will be hard.
      2. + +
      3. With the proposed SEARCH_FOR_TARGET rule, dependency on generated + header will work magically --- it would find the "a_parser.h" target + bound via LOCATE_TARGET to "build" and we'll call INCLUDE on that found + target, instread of creating a completely unrelated one.
      4. +

      Last modified: Aug 15, 2002