diff --git a/boost_build_v2.html b/boost_build_v2.html index b4878d3ce..0230df7c7 100644 --- a/boost_build_v2.html +++ b/boost_build_v2.html @@ -22,12 +22,12 @@ div.alert { color: red } table { align: center; border: thin; } - + + - build request, build request expansion and directly requested targets + - conditional properties + -->

bjam there. A simple application will be built. You can also play with other projects in examples-v2. + it somewhere. + +

It is slighly better way is to copy new/user-config.jam + into one of the locations where it can be found (given in this table). This prevent you from + accidentally overwriting your config when updating.

--> @@ -1461,17 +1461,17 @@ borland/runtime-link=static,dynamic
  • It allows to have main target names with slashes. + That makes good rationale for why main target must contain names. + -->
  • @@ -1708,104 +1708,6 @@ borland/runtime-link=static,dynamic 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:

    - - - -

    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: June 16, 2003

    diff --git a/doc/architecture.html b/doc/architecture.html new file mode 100644 index 000000000..4a32a6f66 --- /dev/null +++ b/doc/architecture.html @@ -0,0 +1,223 @@ + + + + + + + + + + Boost.Build v2 user manual + + + + + + +

    + +

    Boost.Build v2 architecture
    +

    +
    + +
    +
    Dependency scanning
    +
    +
    + +

    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:

    + + + +

    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 sources

    + 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 + variable.
    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 builtin support. + +

    There are two design choices. Suppose we have files a.cpp and b.cpp, + and each one includes header.h, generated by some action. Dependency + graph created by classic jam would look like:

    +
    +    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 use for some time. The problem however is: what + include paths should be used when scanning header.h? Originally, two + different sets of include paths were used. The second alternative does + not have this problem, so it's implemented now. + +

    Includes between generated sources

    + +

    Suppose file "a.cpp" includes "a.h" and both are generated by some + action. Initially, neither file exists, so when classic jam constructs + dependency graph, the include is not found. As the result, jam might + attempt to compile a.cpp before creating a.h, and compilation will + fail.

    + +

    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 is not + shown). Say during building we've tried to create A, then tried to create + C and successfully created C. The B node wasn't seen yet. The C target is + rescanned, which creates new internal node. If we had those includes from + the start, we'd add this node to the list of A dependencies and B + dependencies. As it stands, we need to add it now. + +

    We determine what should be done with C-includes-2, add C-includes-2 + to A's dependencies, and build the target. Unfortunately, we cannot do + the same with B, since we don't know that B is parent of C until we visit + B. So we add a special flag to C telling that it was rescanned. When we + process B, we'll add new dependency node to B's dependencies. this point + of time the target is requested by some parents. So parents were not yet + visited. Both visited and unvisited parents have What shall we do when + using subvariants. For user, subvariants must be more or less + transparent. If without subvariant a header was generated to a certain + directory, everything must work. Suppose that file a.cpp belongs to a + dependency graph of main target a. Include paths are

    + +
    +
    +     "/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: June 30, 2003

    + +

    © Copyright Vladimir Prus 2002-2003. Permission to copy, use, + modify, sell and distribute this document is granted provided this + copyright notice appears in all copies. This document is provided ``as + is'' without express or implied warranty, and with no claim as to its + suitability for any purpose.

    + + + +