diff options
| author | Chris Dyer <cdyer@cs.cmu.edu> | 2012-10-11 14:06:32 -0400 | 
|---|---|---|
| committer | Chris Dyer <cdyer@cs.cmu.edu> | 2012-10-11 14:06:32 -0400 | 
| commit | 07ea7b64b6f85e5798a8068453ed9fd2b97396db (patch) | |
| tree | 644496a1690d84d82a396bbc1e39160788beb2cd /jam-files/boost-build/build | |
| parent | 37b9e45e5cb29d708f7249dbe0b0fb27685282a0 (diff) | |
| parent | a36fcc5d55c1de84ae68c1091ebff2b1c32dc3b7 (diff) | |
Merge branch 'master' of https://github.com/redpony/cdec
Diffstat (limited to 'jam-files/boost-build/build')
34 files changed, 0 insertions, 19696 deletions
diff --git a/jam-files/boost-build/build/__init__.py b/jam-files/boost-build/build/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/jam-files/boost-build/build/__init__.py +++ /dev/null diff --git a/jam-files/boost-build/build/ac.jam b/jam-files/boost-build/build/ac.jam deleted file mode 100644 index 6768f358..00000000 --- a/jam-files/boost-build/build/ac.jam +++ /dev/null @@ -1,198 +0,0 @@ -# Copyright (c) 2010 Vladimir Prus. -# -# Use, modification and distribution is subject to the Boost Software -# License Version 1.0. (See accompanying file LICENSE_1_0.txt or -# http://www.boost.org/LICENSE_1_0.txt) - -import property-set ; -import path ; -import modules ; -import "class" ;  -import errors ; -import configure ; - -rule find-include-path ( variable : properties : header  -    : provided-path ? ) -{ -    # FIXME: document which properties affect this function by -    # default. -    local target-os = [ $(properties).get <target-os> ] ; -    properties = [ property-set.create <target-os>$(toolset) ] ;     -    if $($(variable)-$(properties)) -    { -        return $($(variable)-$(properties)) ; -    } -    else -    { -        provided-path ?= [ modules.peek : $(variable) ] ; -        includes = $(provided-path) ; -        includes += [ $(properties).get <include> ] ; -        if [ $(properties).get <target-os> ] != windows -        { -            # FIXME: use sysroot -            includes += /usr/include ; -        } -         -        local result ; -        while ! $(result) && $(includes) -        {             -            local f = [ path.root $(header) $(includes[1]) ] ; -            ECHO "Checking " $(f) ; -            if [ path.exists $(f) ] -            { -                result = $(includes[1]) ; -            } -            else if $(provided-path) -            { -                errors.user-error "Could not find header" $(header) -                  : "in the user-specified directory" $(provided-path) ; -            }             -            includes = $(includes[2-]) ;                 -        }         -        $(variable)-$(properties) = $(result) ; -        return $(result) ; -    }         -} - -rule find-library ( variable : properties : names + : provided-path ? ) -{ -    local target-os = [ $(properties).get <target-os> ] ; -    properties = [ property-set.create <target-os>$(toolset) ] ; -    if $($(variable)-$(properties)) -    { -        return $($(variable)-$(properties)) ; -    } -    else -    { -        provided-path ?= [ modules.peek : $(variable) ] ; -        paths = $(provided-path) ; -        paths += [ $(properties).get <library-path> ] ; -        if [ $(properties).get <target-os> ] != windows -        { -            paths += /usr/lib /usr/lib32 /usr/lib64 ; -        } -         -        local result ;                -        while ! $(result) && $(paths) -        {    -            while ! $(result) && $(names) -            { -                local f ; -                if $(target-os) = windows -                {          -                    f = $(paths[1])/$(names[1]).lib ;                 -                    if [ path.exists $(f) ]  -                    { -                        result = $(f) ; -                    } -                } -                else -                { -                    # FIXME: check for .a as well, depending on -                    # the 'link' feature. -                    f = $(paths[1])/lib$(names[1]).so ;                 -                    ECHO "CHECKING $(f) " ; -                    if [ path.exists $(f) ]  -                    { -                        result = $(f) ; -                    } -                } -                if ! $(result) && $(provided-path) -                { -                    errors.user-error "Could not find either of: " $(names) -                      : "in the user-specified directory" $(provided-path) ; -                     -                }                 -                names = $(names[2-]) ; -            } -            paths = $(paths[2-]) ; -        }         -        $(variable)-$(properties) = $(result) ; -        return $(result) ; -    } -} - -class ac-library : basic-target -{ -    import errors ; -    import indirect ; -    import virtual-target ; -    import ac ; -    import configure ; - -    rule __init__ ( name : project : * : * ) -    { -        basic-target.__init__ $(name) : $(project) : $(sources) -          : $(requirements) ; -         -        reconfigure $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;  -    } -     -    rule set-header ( header ) -    { -        self.header = $(header) ;  -    } -         -    rule set-default-names ( names + ) -    { -        self.default-names = $(names) ; -    } -         -    rule reconfigure ( * : * ) -    { -        ECHO "XXX" $(1) ; -        if ! $(1) -        { -            # This is 'using xxx ;'. Nothing to configure, really. -        } -        else -        { -            for i in 1 2 3 4 5 6 7 8 9              -            { -                # FIXME: this naming is inconsistent with XXX_INCLUDE/XXX_LIBRARY -                if ! ( $($(i)[1]) in root include-path library-path library-name condition ) -                { -                    errors.user-error "Invalid named parameter" $($(i)[1]) ; -                }    -                local name = $($(i)[1]) ; -                local value = $($(i)[2-]) ; -                if $($(name)) && $($(name)) != $(value) -                { -                    errors.user-error "Attempt to change value of '$(name)'" ; -                } -                $(name) = $(value) ; -            } -             -            include-path ?= $(root)/include ; -            library-path ?= $(root)/lib ;             -        }         -    } -     -    rule construct ( name : sources * : property-set ) -    { -        # FIXME: log results. -        local libnames = $(library-name) ; -        if ! $(libnames) && ! $(include-path) && ! $(library-path) -        { -            libnames = [ modules.peek : $(name:U)_NAME ] ; -            # Backward compatibility only. -            libnames ?= [ modules.peek : $(name:U)_BINARY ] ; -        } -        libnames ?= $(self.default-names) ; -                         -        local includes = [  -          ac.find-include-path $(name:U)_INCLUDE : $(property-set) : $(self.header) : $(include-path) ] ; -        local library = [ ac.find-library $(name:U)_LIBRARY : $(property-set) : $(libnames) : $(library-path) ] ; -        if $(includes) && $(library) -        { -            library = [ virtual-target.from-file $(library) : . : $(self.project) ] ; -            configure.log-library-search-result $(name) : "found" ; -            return [ property-set.create <include>$(includes) <source>$(library) ] ; -        } -        else -        { -            configure.log-library-search-result $(name) : "no found" ; -        }         -    } -} - diff --git a/jam-files/boost-build/build/alias.jam b/jam-files/boost-build/build/alias.jam deleted file mode 100644 index 48019cb9..00000000 --- a/jam-files/boost-build/build/alias.jam +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2003, 2004, 2006 Vladimir Prus -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - -# This module defines the 'alias' rule and the associated target class. -# -# Alias is just a main target which returns its source targets without any -# processing. For example: -# -#   alias bin : hello test_hello ; -#   alias lib : helpers xml_parser ; -# -# Another important use of 'alias' is to conveniently group source files: -# -#   alias platform-src : win.cpp : <os>NT ; -#   alias platform-src : linux.cpp : <os>LINUX ; -#   exe main : main.cpp platform-src ; -# -# Lastly, it is possible to create a local alias for some target, with different -# properties: -# -#   alias big_lib : : @/external_project/big_lib/<link>static ; -# - -import "class" : new ; -import project ; -import property-set ; -import targets ; - - -class alias-target-class : basic-target -{ -    rule __init__ ( name : project : sources * : requirements * -        : default-build * : usage-requirements * ) -    { -        basic-target.__init__ $(name) : $(project) : $(sources) : -            $(requirements) : $(default-build) : $(usage-requirements) ; -    } - -    rule construct ( name : source-targets * : property-set ) -    { -        return [ property-set.empty ] $(source-targets) ; -    } - -    rule compute-usage-requirements ( subvariant ) -    { -        local base = [ basic-target.compute-usage-requirements $(subvariant) ] ; -        return [ $(base).add [ $(subvariant).sources-usage-requirements ] ] ; -    } -} - - -# Declares the 'alias' target. It will process its sources virtual-targets by -# returning them unaltered as its own constructed virtual-targets. -# -rule alias ( name : sources * : requirements * : default-build * : -    usage-requirements * ) -{ -    local project = [ project.current ] ; - -    targets.main-target-alternative -        [ new alias-target-class $(name) : $(project) -            : [ targets.main-target-sources $(sources) : $(name) : no-renaming ] -            : [ targets.main-target-requirements $(requirements) : $(project) ] -            : [ targets.main-target-default-build $(default-build) : $(project) -                ] -            : [ targets.main-target-usage-requirements $(usage-requirements) : -                $(project) ] -        ] ; -} - - -IMPORT $(__name__) : alias : : alias ; diff --git a/jam-files/boost-build/build/alias.py b/jam-files/boost-build/build/alias.py deleted file mode 100644 index 575e5360..00000000 --- a/jam-files/boost-build/build/alias.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright 2003, 2004, 2006 Vladimir Prus  -# Distributed under the Boost Software License, Version 1.0.  -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)  - -# Status: ported (danielw) -# Base revision: 56043 - -#  This module defines the 'alias' rule and associated class. -# -#  Alias is just a main target which returns its source targets without any  -#  processing. For example:: -# -#    alias bin : hello test_hello ; -#    alias lib : helpers xml_parser ; -# -#  Another important use of 'alias' is to conveniently group source files:: -# -#    alias platform-src : win.cpp : <os>NT ; -#    alias platform-src : linux.cpp : <os>LINUX ; -#    exe main : main.cpp platform-src ; -#  -#  Lastly, it's possible to create local alias for some target, with different -#  properties:: -# -#    alias big_lib : : @/external_project/big_lib/<link>static ; -# - -import targets -import property_set -from b2.manager import get_manager - -from b2.util import metatarget - -class AliasTarget(targets.BasicTarget): - -    def __init__(self, *args): -        targets.BasicTarget.__init__(self, *args) - -    def construct(self, name, source_targets, properties): -        return [property_set.empty(), source_targets] - -    def compute_usage_requirements(self, subvariant): -        base = targets.BasicTarget.compute_usage_requirements(self, subvariant) -        # Add source's usage requirement. If we don't do this, "alias" does not -        # look like 100% alias. -        return base.add(subvariant.sources_usage_requirements()) - -@metatarget -def alias(name, sources=[], requirements=[], default_build=[], usage_requirements=[]): - -    project = get_manager().projects().current() -    targets = get_manager().targets() - -    targets.main_target_alternative(AliasTarget( -        name, project, -        targets.main_target_sources(sources, name, no_renaming=True), -        targets.main_target_requirements(requirements or [], project), -        targets.main_target_default_build(default_build, project), -        targets.main_target_usage_requirements(usage_requirements or [], project))) - -# Declares the 'alias' target. It will build sources, and return them unaltered. -get_manager().projects().add_rule("alias", alias) - diff --git a/jam-files/boost-build/build/build-request.jam b/jam-files/boost-build/build/build-request.jam deleted file mode 100644 index 8a1f7b0e..00000000 --- a/jam-files/boost-build/build/build-request.jam +++ /dev/null @@ -1,322 +0,0 @@ -# Copyright 2002 Dave Abrahams -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - -import "class" : new ; -import sequence ; -import set ; -import regex ; -import feature ; -import property ; -import container ; -import string ; - - -# Transform property-set by applying f to each component property. -# -local rule apply-to-property-set ( f property-set ) -{ -    local properties = [ feature.split $(property-set) ] ; -    return [ string.join [ $(f) $(properties) ] : / ] ; -} - - -# Expand the given build request by combining all property-sets which do not -# specify conflicting non-free features. Expects all the project files to -# already be loaded. -# -rule expand-no-defaults ( property-sets * ) -{ -    # First make all features and subfeatures explicit. -    local expanded-property-sets = [ sequence.transform apply-to-property-set -        feature.expand-subfeatures : $(property-sets) ] ; - -    # Now combine all of the expanded property-sets -    local product = [ x-product $(expanded-property-sets) : $(feature-space) ] ; - -    return $(product) ; -} - - -# Implementation of x-product, below. Expects all the project files to already -# be loaded. -# -local rule x-product-aux ( property-sets + ) -{ -    local result ; -    local p = [ feature.split $(property-sets[1]) ] ; -    local f = [ set.difference $(p:G) : [ feature.free-features ] ] ; -    local seen ; -    # No conflict with things used at a higher level? -    if ! [ set.intersection $(f) : $(x-product-used) ] -    { -        local x-product-seen ; -        { -            # Do not mix in any conflicting features. -            local x-product-used = $(x-product-used) $(f) ; - -            if $(property-sets[2]) -            { -                local rest = [ x-product-aux $(property-sets[2-]) : $(feature-space) ] ; -                result = $(property-sets[1])/$(rest) ; -            } - -            result ?= $(property-sets[1]) ; -        } - -        # If we did not encounter a conflicting feature lower down, do not -        # recurse again. -        if ! [ set.intersection $(f) : $(x-product-seen) ] -        { -            property-sets = ; -        } - -        seen = $(x-product-seen) ; -    } - -    if $(property-sets[2]) -    { -        result += [ x-product-aux $(property-sets[2-]) : $(feature-space) ] ; -    } - -    # Note that we have seen these features so that higher levels will recurse -    # again without them set. -    x-product-seen += $(f) $(seen) ; -    return $(result) ; -} - - -# Return the cross-product of all elements of property-sets, less any that would -# contain conflicting values for single-valued features. Expects all the project -# files to already be loaded. -# -local rule x-product ( property-sets * ) -{ -    if $(property-sets).non-empty -    { -        # Prepare some "scoped globals" that can be used by the implementation -        # function, x-product-aux. -        local x-product-seen x-product-used ; -        return [ x-product-aux $(property-sets) : $(feature-space) ] ; -    } -    # Otherwise return empty. -} - - -# Returns true if either 'v' or the part of 'v' before the first '-' symbol is -# an implicit value. Expects all the project files to already be loaded. -# -local rule looks-like-implicit-value ( v ) -{ -    if [ feature.is-implicit-value $(v) ] -    { -        return true ; -    } -    else -    { -        local split = [ regex.split $(v) - ] ; -        if [ feature.is-implicit-value $(split[1]) ] -        { -            return true ; -        } -    } -} - - -# Takes the command line tokens (such as taken from the ARGV rule) and -# constructs a build request from them. Returns a vector of two vectors (where -# "vector" means container.jam's "vector"). First is the set of targets -# specified in the command line, and second is the set of requested build -# properties. Expects all the project files to already be loaded. -# -rule from-command-line ( command-line * ) -{ -    local targets ; -    local properties ; - -    command-line = $(command-line[2-]) ; -    local skip-next = ; -    for local e in $(command-line) -    { -        if $(skip-next) -        { -            skip-next = ; -        } -        else if ! [ MATCH "^(-).*" : $(e) ] -        { -            # Build request spec either has "=" in it or completely consists of -            # implicit feature values. -            local fs = feature-space ; -            if [ MATCH "(.*=.*)" : $(e) ] -                || [ looks-like-implicit-value $(e:D=) : $(feature-space) ] -            { -                properties += [ convert-command-line-element $(e) : -                    $(feature-space) ] ; -            } -            else -            { -                targets += $(e) ; -            } -        } -        else if [ MATCH "^(-[-ldjfsto])$" : $(e) ] -        { -            skip-next = true ; -        } -    } -    return [ new vector -        [ new vector $(targets) ] -        [ new vector $(properties) ] ] ; -} - - -# Converts one element of command line build request specification into internal -# form. Expects all the project files to already be loaded. -# -local rule convert-command-line-element ( e ) -{ -    local result ; -    local parts = [ regex.split $(e) "/" ] ; -    while $(parts) -    { -        local p = $(parts[1]) ; -        local m = [ MATCH "([^=]*)=(.*)" : $(p) ] ; -        local lresult ; -        local feature ; -        local values ; -        if $(m) -        { -            feature = $(m[1]) ; -            values = [ regex.split $(m[2]) "," ] ; -            lresult = <$(feature)>$(values) ; -        } -        else -        { -            lresult = [ regex.split $(p) "," ] ; -        } -         -        if $(feature) && free in [ feature.attributes $(feature) ] -        { -            # If we have free feature, then the value is everything -            # until the end of the command line token. Slashes in -            # the following string are not taked to mean separation -            # of properties. Commas are also not interpreted specially. -            values = $(values:J=,) ; -            values = $(values) $(parts[2-]) ; -            values = $(values:J=/) ; -            lresult = <$(feature)>$(values) ; -            parts = ; -        } -         -        if ! [ MATCH (.*-.*) : $(p) ] -        { -            # property.validate cannot handle subfeatures, so we avoid the check -            # here. -            for local p in $(lresult) -            { -                property.validate $(p) : $(feature-space) ; -            } -        } - -        if ! $(result) -        { -            result = $(lresult) ; -        } -        else -        { -            result = $(result)/$(lresult) ; -        } -         -        parts = $(parts[2-]) ; -    } - -    return $(result) ; -} - - -rule __test__ ( ) -{ -    import assert ; -    import feature ; - -    feature.prepare-test build-request-test-temp ; - -    import build-request ; -    import build-request : expand-no-defaults : build-request.expand-no-defaults ; -    import errors : try catch ; -    import feature : feature subfeature ; - -    feature toolset : gcc msvc borland : implicit ; -    subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4 -      3.0 3.0.1 3.0.2 : optional ; - -    feature variant : debug release : implicit composite ; -    feature inlining : on off ; -    feature "include" : : free ; - -    feature stdlib : native stlport : implicit ; - -    feature runtime-link : dynamic static : symmetric ; - -    # Empty build requests should expand to empty. -    assert.result -        : build-request.expand-no-defaults ; - -    assert.result -        <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug -        <toolset>msvc/<stdlib>stlport/<variant>debug -        <toolset>msvc/<variant>debug -        : build-request.expand-no-defaults gcc-3.0.1/stlport msvc/stlport msvc debug ; - -    assert.result -        <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug -        <toolset>msvc/<variant>debug -        <variant>debug/<toolset>msvc/<stdlib>stlport -        : build-request.expand-no-defaults gcc-3.0.1/stlport msvc debug msvc/stlport ; - -    assert.result -        <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug/<inlining>off -        <toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>release/<inlining>off -        : build-request.expand-no-defaults gcc-3.0.1/stlport debug release <inlining>off ; - -    assert.result -        <include>a/b/c/<toolset>gcc/<toolset-gcc:version>3.0.1/<stdlib>stlport/<variant>debug/<include>x/y/z -        <include>a/b/c/<toolset>msvc/<stdlib>stlport/<variant>debug/<include>x/y/z -        <include>a/b/c/<toolset>msvc/<variant>debug/<include>x/y/z -        : build-request.expand-no-defaults <include>a/b/c gcc-3.0.1/stlport msvc/stlport msvc debug  <include>x/y/z ; - -    local r ; - -    r = [ build-request.from-command-line bjam debug runtime-link=dynamic ] ; -    assert.equal [ $(r).get-at 1 ] : ; -    assert.equal [ $(r).get-at 2 ] : debug <runtime-link>dynamic ; - -    try ; -    { -        build-request.from-command-line bjam gcc/debug runtime-link=dynamic/static ; -    } -    catch \"static\" is not a value of an implicit feature ; - -    r = [ build-request.from-command-line bjam -d2 --debug debug target runtime-link=dynamic ] ; -    assert.equal [ $(r).get-at 1 ] : target ; -    assert.equal [ $(r).get-at 2 ] : debug <runtime-link>dynamic ; - -    r = [ build-request.from-command-line bjam debug runtime-link=dynamic,static ] ; -    assert.equal [ $(r).get-at 1 ] : ; -    assert.equal [ $(r).get-at 2 ] : debug <runtime-link>dynamic <runtime-link>static ; - -    r = [ build-request.from-command-line bjam debug gcc/runtime-link=dynamic,static ] ; -    assert.equal [ $(r).get-at 1 ] : ; -    assert.equal [ $(r).get-at 2 ] : debug gcc/<runtime-link>dynamic -        gcc/<runtime-link>static ; - -    r = [ build-request.from-command-line bjam msvc gcc,borland/runtime-link=static ] ; -    assert.equal [ $(r).get-at 1 ] : ; -    assert.equal [ $(r).get-at 2 ] : msvc gcc/<runtime-link>static -        borland/<runtime-link>static ; - -    r = [ build-request.from-command-line bjam gcc-3.0 ] ; -    assert.equal [ $(r).get-at 1 ] : ; -    assert.equal [ $(r).get-at 2 ] : gcc-3.0 ; - -    feature.finish-test build-request-test-temp ; -} diff --git a/jam-files/boost-build/build/build_request.py b/jam-files/boost-build/build/build_request.py deleted file mode 100644 index cc9f2400..00000000 --- a/jam-files/boost-build/build/build_request.py +++ /dev/null @@ -1,216 +0,0 @@ -# Status: being ported by Vladimir Prus -# TODO: need to re-compare with mainline of .jam -# Base revision: 40480 -# -#  (C) Copyright David Abrahams 2002. Permission to copy, use, modify, sell and -#  distribute this software is granted provided this copyright notice appears in -#  all copies. This software is provided "as is" without express or implied -#  warranty, and with no claim as to its suitability for any purpose. - -import b2.build.feature -feature = b2.build.feature - -from b2.util.utility import * -import b2.build.property_set as property_set - -def expand_no_defaults (property_sets): -    """ Expand the given build request by combining all property_sets which don't -        specify conflicting non-free features. -    """ -    # First make all features and subfeatures explicit -    expanded_property_sets = [ps.expand_subfeatures() for ps in property_sets] -     -    # Now combine all of the expanded property_sets -    product = __x_product (expanded_property_sets) -     -    return [property_set.create(p) for p in product] - - -def __x_product (property_sets): -    """ Return the cross-product of all elements of property_sets, less any -        that would contain conflicting values for single-valued features. -    """ -    x_product_seen = set() -    return __x_product_aux (property_sets, x_product_seen)[0] - -def __x_product_aux (property_sets, seen_features): -    """Returns non-conflicting combinations of property sets. - -    property_sets is a list of PropertySet instances. seen_features is a set of Property -    instances. - -    Returns a tuple of: -    - list of lists of Property instances, such that within each list, no two Property instance -    have the same feature, and no Property is for feature in seen_features. -    - set of features we saw in property_sets       -    """ -    if not property_sets: -        return ([], set()) - -    properties = property_sets[0].all() - -    these_features = set() -    for p in property_sets[0].non_free(): -        these_features.add(p.feature()) - -    # Note: the algorithm as implemented here, as in original Jam code, appears to -    # detect conflicts based on features, not properties. For example, if command -    # line build request say: -    # -    # <a>1/<b>1 c<1>/<b>1 -    # -    # It will decide that those two property sets conflict, because they both specify -    # a value for 'b' and will not try building "<a>1 <c1> <b1>", but rather two -    # different property sets. This is a topic for future fixing, maybe. -    if these_features & seen_features: - -        (inner_result, inner_seen) = __x_product_aux(property_sets[1:], seen_features) -        return (inner_result, inner_seen | these_features) - -    else: - -        result = [] -        (inner_result, inner_seen) = __x_product_aux(property_sets[1:], seen_features | these_features) -        if inner_result: -            for inner in inner_result: -                result.append(properties + inner) -        else: -            result.append(properties) -         -        if inner_seen & these_features: -            # Some of elements in property_sets[1:] conflict with elements of property_sets[0], -            # Try again, this time omitting elements of property_sets[0] -            (inner_result2, inner_seen2) = __x_product_aux(property_sets[1:], seen_features) -            result.extend(inner_result2) - -        return (result, inner_seen | these_features) - -     - -def looks_like_implicit_value(v): -    """Returns true if 'v' is either implicit value, or -    the part before the first '-' symbol is implicit value.""" -    if feature.is_implicit_value(v): -        return 1 -    else: -        split = v.split("-") -        if feature.is_implicit_value(split[0]): -            return 1 - -    return 0 - -def from_command_line(command_line): -    """Takes the command line tokens (such as taken from ARGV rule) -    and constructs build request from it. Returns a list of two -    lists. First is the set of targets specified in the command line, -    and second is the set of requested build properties.""" - -    targets = [] -    properties = [] - -    for e in command_line: -        if e[0] != "-": -            # Build request spec either has "=" in it, or completely -            # consists of implicit feature values. -            if e.find("=") != -1 or looks_like_implicit_value(e.split("/")[0]):                 -                properties += convert_command_line_element(e) -            else: -                targets.append(e) - -    return [targets, properties] -  -# Converts one element of command line build request specification into -# internal form. -def convert_command_line_element(e): - -    result = None -    parts = e.split("/") -    for p in parts: -        m = p.split("=") -        if len(m) > 1: -            feature = m[0] -            values = m[1].split(",") -            lresult = [("<%s>%s" % (feature, v)) for v in values] -        else: -            lresult = p.split(",") -             -        if p.find('-') == -1: -            # FIXME: first port property.validate -            # property.validate cannot handle subfeatures, -            # so we avoid the check here. -            #for p in lresult: -            #    property.validate(p) -            pass - -        if not result: -            result = lresult -        else: -            result = [e1 + "/" + e2 for e1 in result for e2 in lresult] - -    return [property_set.create(b2.build.feature.split(r)) for r in result] - -###  -### rule __test__ ( ) -### { -###     import assert feature ; -###      -###     feature.prepare-test build-request-test-temp ; -###      -###     import build-request ; -###     import build-request : expand_no_defaults : build-request.expand_no_defaults ; -###     import errors : try catch ; -###     import feature : feature subfeature ; -###  -###     feature toolset : gcc msvc borland : implicit ; -###     subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4 -###       3.0 3.0.1 3.0.2 : optional ; -###  -###     feature variant : debug release : implicit composite ; -###     feature inlining : on off ; -###     feature "include" : : free ; -###  -###     feature stdlib : native stlport : implicit ; -###  -###     feature runtime-link : dynamic static : symmetric ; -###  -###  -###     local r ; -###  -###     r = [ build-request.from-command-line bjam debug runtime-link=dynamic ] ;               -###     assert.equal [ $(r).get-at 1 ] : ; -###     assert.equal [ $(r).get-at 2 ] : debug <runtime-link>dynamic ; -###  -###     try ; -###     { -###  -###         build-request.from-command-line bjam gcc/debug runtime-link=dynamic/static ; -###     } -###     catch \"static\" is not a value of an implicit feature ; -###  -###  -###     r = [ build-request.from-command-line bjam -d2 --debug debug target runtime-link=dynamic ] ; -###     assert.equal [ $(r).get-at 1 ] : target ; -###     assert.equal [ $(r).get-at 2 ] : debug <runtime-link>dynamic ; -###  -###     r = [ build-request.from-command-line bjam debug runtime-link=dynamic,static ] ; -###     assert.equal [ $(r).get-at 1 ] : ; -###     assert.equal [ $(r).get-at 2 ] : debug <runtime-link>dynamic <runtime-link>static ; -###  -###     r = [ build-request.from-command-line bjam debug gcc/runtime-link=dynamic,static ] ; -###     assert.equal [ $(r).get-at 1 ] : ; -###     assert.equal [ $(r).get-at 2 ] : debug gcc/<runtime-link>dynamic  -###                  gcc/<runtime-link>static ; -###  -###     r = [ build-request.from-command-line bjam msvc gcc,borland/runtime-link=static ] ; -###     assert.equal [ $(r).get-at 1 ] : ; -###     assert.equal [ $(r).get-at 2 ] : msvc gcc/<runtime-link>static  -###                     borland/<runtime-link>static ; -###  -###     r = [ build-request.from-command-line bjam gcc-3.0 ] ; -###     assert.equal [ $(r).get-at 1 ] : ; -###     assert.equal [ $(r).get-at 2 ] : gcc-3.0 ; -###  -###     feature.finish-test build-request-test-temp ; -### } -###  -###  diff --git a/jam-files/boost-build/build/configure.jam b/jam-files/boost-build/build/configure.jam deleted file mode 100644 index 14c1328a..00000000 --- a/jam-files/boost-build/build/configure.jam +++ /dev/null @@ -1,237 +0,0 @@ -# Copyright (c) 2010 Vladimir Prus. -# -# Use, modification and distribution is subject to the Boost Software -# License Version 1.0. (See accompanying file LICENSE_1_0.txt or -# http://www.boost.org/LICENSE_1_0.txt) - -# This module defines function to help with two main tasks: -# -# - Discovering build-time configuration for the purposes of adjusting -#   build process.   -# - Reporting what is built, and how it is configured. - -import targets ;  -import errors ; -import targets ; -import sequence ; -import property ; -import property-set ; -import "class" : new ; -import common ; -import path ; - -rule log-summary ( ) -{ -     -} - -.width = 30 ; - -rule set-width ( width ) -{ -    .width = $(width) ; -} - -# Declare that the components specified by the parameter exist. -rule register-components ( components * ) -{ -    .components += $(components) ; -} - -# Declare that the components specified by the parameters will -# be build. -rule components-building ( components * ) -{ -    .built-components += $(components) ; -} - -# Report something about component configuration that the -# user should better know. -rule log-component-configuration ( component : message ) -{ -    # FIXME: implement per-property-set logs -    .component-logs.$(component) += $(message) ; -} - - - -rule log-check-result ( result ) -{ -    if ! $(.announced-checks) -    { -        ECHO "Performing configuration checks\n" ; -        .announced-checks = 1 ; -    } -     -    ECHO $(result) ;     -    #.check-results += $(result) ; -} - -rule log-library-search-result ( library : result ) -{ -    local x = [ PAD "    - $(library) : $(result)" : $(.width) ] ; -    log-check-result "$(x)" ; -} - -rule print-component-configuration ( ) -{ -    local c = [ sequence.unique $(.components) ] ; -     -    ECHO "\nComponent configuration:\n" ; -    for c in $(.components) -    { -        local s ; -        if $(c) in $(.built-components) -        { -            s = "building" ; -        } -        else -        { -            s = "not building" ; -        } -        ECHO [ PAD "    - $(c)" : $(.width) ] ": $(s)" ; -        for local m in $(.component-logs.$(c)) -        { -            ECHO "        -" $(m) ; -        }         -    } -    ECHO ; -} - -rule print-configure-checks-summary ( ) -{ -    # FIXME: the problem with that approach is tha -    # the user sees checks summary when all checks are -    # done, and has no progress reporting while the -    # checks are being executed.     -    if $(.check-results) -    {         -        ECHO "Configuration checks summary\n" ; -     -        for local r in $(.check-results) -        { -            ECHO $(r) ; -        } -        ECHO ; -    }     -} - -# Attempt to build a metatarget named by 'metatarget-reference' -# in context of 'project' with properties 'ps'. -# Returns non-empty value if build is OK. -rule builds-raw ( metatarget-reference : project : ps : what : retry ? ) -{    -    local result ; -            -    if ! $(retry) && ! $(.$(what)-tested.$(ps)) -    {         -        .$(what)-tested.$(ps) = true ; -         -        local targets = [ targets.generate-from-reference  -            $(metatarget-reference) : $(project) : $(ps) ] ; -         -        local jam-targets ; -        for local t in $(targets[2-]) -        { -            jam-targets += [ $(t).actualize ] ; -        } -                     -        if ! UPDATE_NOW in [ RULENAMES ] -        { -            # Cannot determine. Assume existance. -        } -        else  -        {            -            local x = [ PAD "    - $(what)" : $(.width) ] ;             -            if [ UPDATE_NOW $(jam-targets) : -                 $(.log-fd) : ignore-minus-n : ignore-minus-q ]  -            { -                .$(what)-supported.$(ps) = yes ; -                result = true ; -                log-check-result "$(x) : yes" ; -            }         -            else -            { -                log-check-result "$(x) : no" ; -            } -        }         -        return $(result) ; -    }     -    else -    { -        return $(.$(what)-supported.$(ps)) ; -    } -} - -rule builds ( metatarget-reference : properties * : what ? : retry ? ) -{ -    what ?= "$(metatarget-reference) builds" ; -     -    # FIXME: this should not be hardcoded. Other checks might -    # want to consider different set of features as relevant. -    local toolset = [ property.select <toolset> : $(properties) ] ; -    local toolset-version-property = "<toolset-$(toolset:G=):version>" ; -    local relevant = [ property.select <target-os> <toolset> $(toolset-version-property) -      <address-model> <architecture> -      : $(properties) ] ; -    local ps = [ property-set.create $(relevant) ] ;         -    local t = [ targets.current ] ; -    local p = [ $(t).project ] ; - -    return [ builds-raw $(metatarget-reference) : $(p) : $(ps) : $(what) : $(retry) ] ; -} - - -# Called by Boost.Build startup code to specify name of a file -# that will receive results of configure checks.  This -# should never be called by users. -rule set-log-file ( log-file ) -{ -    path.makedirs [ path.parent $(log-file) ] ; -     -    .log-fd = [ FILE_OPEN $(log-file) : "w" ] ; -} - -# Frontend rules - -class check-target-builds-worker -{ -    import configure ; -    import property-set ; -    import targets ; -    import property ;  -     -    rule __init__ ( target message ? : true-properties * : false-properties * )     -    { -        self.target = $(target) ; -        self.message = $(message) ;      -        self.true-properties = $(true-properties) ; -        self.false-properties = $(false-properties) ; -    } -         -    rule check ( properties * ) -    { -        local choosen ; -        if [ configure.builds $(self.target) : $(properties) : $(self.message) ] -        { -            choosen = $(self.true-properties) ; -        }         -        else -        { -            choosen = $(self.false-properties) ; -        }         -        return [ property.evaluate-conditionals-in-context $(choosen) : $(properties) ] ; -    }     -} - - -rule check-target-builds ( target message ? : true-properties * : false-properties * ) -{ -    local instance = [ new check-target-builds-worker $(target) $(message) : $(true-properties) -      : $(false-properties) ] ; -    return <conditional>@$(instance).check ; -} - -IMPORT $(__name__) : check-target-builds :  : check-target-builds ; - - diff --git a/jam-files/boost-build/build/configure.py b/jam-files/boost-build/build/configure.py deleted file mode 100644 index 0426832c..00000000 --- a/jam-files/boost-build/build/configure.py +++ /dev/null @@ -1,164 +0,0 @@ -# Status: ported. -# Base revison: 64488 -# -# Copyright (c) 2010 Vladimir Prus. -# -# Use, modification and distribution is subject to the Boost Software -# License Version 1.0. (See accompanying file LICENSE_1_0.txt or -# http://www.boost.org/LICENSE_1_0.txt) - -# This module defines function to help with two main tasks: -# -# - Discovering build-time configuration for the purposes of adjusting -#   build process.   -# - Reporting what is built, and how it is configured. - -import b2.build.property as property -import b2.build.property_set as property_set - -import b2.build.targets - -from b2.manager import get_manager -from b2.util.sequence import unique -from b2.util import bjam_signature, value_to_jam - -import bjam -import os - -__width = 30 - -def set_width(width): -    global __width -    __width = 30 - -__components = [] -__built_components = [] -__component_logs = {} -__announced_checks = False - -__log_file = None -__log_fd = -1 - -def register_components(components): -    """Declare that the components specified by the parameter exist.""" -    __components.extend(components) -     -def components_building(components): -    """Declare that the components specified by the parameters will be build.""" -    __built_components.extend(components) - -def log_component_configuration(component, message): -    """Report something about component configuration that the user should better know.""" -    __component_logs.setdefault(component, []).append(message) - -def log_check_result(result): -    global __announced_checks -    if not __announced_checks: -        print "Performing configuration checks" -        __announced_checks = True - -    print result - -def log_library_search_result(library, result): -    log_check_result(("    - %(library)s : %(result)s" % locals()).rjust(width)) - - -def print_component_configuration(): - -    print "\nComponent configuration:" -    for c in __components: -        if c in __built_components: -            s = "building" -        else: -            s = "not building" -        message = "    - %s)" % c -        message = message.rjust(__width) -        message += " : " + s -        for m in __component_logs.get(c, []): -            print "        -" + m -    print "" - -__builds_cache = {} - -def builds(metatarget_reference, project, ps, what): -    # Attempt to build a metatarget named by 'metatarget-reference' -    # in context of 'project' with properties 'ps'. -    # Returns non-empty value if build is OK. - -    result = [] - -    existing = __builds_cache.get((what, ps), None) -    if existing is None: - -        result = False -        __builds_cache[(what, ps)] = False - -        targets = b2.build.targets.generate_from_reference( -            metatarget_reference, project, ps).targets() -        jam_targets = [] -        for t in targets: -            jam_targets.append(t.actualize()) -         -        x = ("    - %s" % what).rjust(__width) -        if bjam.call("UPDATE_NOW", jam_targets, str(__log_fd), "ignore-minus-n"): -            __builds_cache[(what, ps)] = True -            result = True -            log_check_result("%s: yes" % x) -        else: -            log_check_result("%s: no" % x) - -        return result -    else: -        return existing - -def set_log_file(log_file_name): -    # Called by Boost.Build startup code to specify name of a file -    # that will receive results of configure checks.  This -    # should never be called by users. -    global __log_file, __log_fd -    dirname = os.path.dirname(log_file_name) -    if not os.path.exists(dirname): -        os.makedirs(dirname) -    # Make sure to keep the file around, so that it's not -    # garbage-collected and closed -    __log_file = open(log_file_name, "w") -    __log_fd = __log_file.fileno() - -# Frontend rules - -class CheckTargetBuildsWorker: - -    def __init__(self, target, true_properties, false_properties): -        self.target = target -        self.true_properties = property.create_from_strings(true_properties, True) -        self.false_properties = property.create_from_strings(false_properties, True) - -    def check(self, ps): -         -        # FIXME: this should not be hardcoded. Other checks might -        # want to consider different set of features as relevant. -        toolset = ps.get('toolset')[0] -        toolset_version_property = "<toolset-" + toolset + ":version>" ; -        relevant = ps.get_properties('target-os') + \ -                   ps.get_properties("toolset") + \ -                   ps.get_properties(toolset_version_property) + \ -                   ps.get_properties("address-model") + \ -                   ps.get_properties("architecture") -        rps = property_set.create(relevant) -        t = get_manager().targets().current() -        p = t.project()         -        if builds(self.target, p, rps, "%s builds" % self.target): -            choosen = self.true_properties -        else: -            choosen = self.false_properties -        return property.evaluate_conditionals_in_context(choosen, ps) - -@bjam_signature((["target"], ["true_properties", "*"], ["false_properties", "*"])) -def check_target_builds(target, true_properties, false_properties): -    worker = CheckTargetBuildsWorker(target, true_properties, false_properties) -    value = value_to_jam(worker.check) -    return "<conditional>" + value - -get_manager().projects().add_rule("check-target-builds", check_target_builds) - - diff --git a/jam-files/boost-build/build/engine.py b/jam-files/boost-build/build/engine.py deleted file mode 100644 index be9736e0..00000000 --- a/jam-files/boost-build/build/engine.py +++ /dev/null @@ -1,172 +0,0 @@ -# Copyright Pedro Ferreira 2005. -# Copyright Vladimir Prus 2007. -# Distributed under the Boost -# Software License, Version 1.0. (See accompanying -# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -bjam_interface = __import__('bjam') - -import operator -import re - -import b2.build.property_set as property_set -import b2.util - -class BjamAction: -    """Class representing bjam action defined from Python.""" -     -    def __init__(self, action_name, function): -        self.action_name = action_name -        self.function = function -             -    def __call__(self, targets, sources, property_set): -        if self.function: -            self.function(targets, sources, property_set) - -        # Bjam actions defined from Python have only the command -        # to execute, and no associated jam procedural code. So -        # passing 'property_set' to it is not necessary. -        bjam_interface.call("set-update-action", self.action_name, -                            targets, sources, []) - -class BjamNativeAction: -    """Class representing bjam action defined by Jam code. - -    We still allow to associate a Python callable that will -    be called when this action is installed on any target. -    """ -     -    def __init__(self, action_name, function): -        self.action_name = action_name -        self.function = function -         -    def __call__(self, targets, sources, property_set): -        if self.function: -            self.function(targets, sources, property_set) -         -        p = [] -        if property_set: -            p = property_set.raw() - -        b2.util.set_jam_action(self.action_name, targets, sources, p) -         -action_modifiers = {"updated": 0x01, -                    "together": 0x02, -                    "ignore": 0x04, -                    "quietly": 0x08, -                    "piecemeal": 0x10, -                    "existing": 0x20} - -class Engine: -    """ The abstract interface to a build engine. - -    For now, the naming of targets, and special handling of some -    target variables like SEARCH and LOCATE make this class coupled -    to bjam engine. -    """ -    def __init__ (self): -        self.actions = {} - -    def add_dependency (self, targets, sources): -        """Adds a dependency from 'targets' to 'sources' - -        Both 'targets' and 'sources' can be either list -        of target names, or a single target name. -        """ -        if isinstance (targets, str): -            targets = [targets] -        if isinstance (sources, str): -            sources = [sources] - -        for target in targets: -            for source in sources: -                self.do_add_dependency (target, source) -     -    def set_target_variable (self, targets, variable, value, append=0): -        """ Sets a target variable. - -        The 'variable' will be available to bjam when it decides -        where to generate targets, and will also be available to -        updating rule for that 'taret'. -        """ -        if isinstance (targets, str):  -            targets = [targets] - -        for target in targets: -            self.do_set_target_variable (target, variable, value, append) - -    def set_update_action (self, action_name, targets, sources, properties=property_set.empty()): -        """ Binds a target to the corresponding update action. -            If target needs to be updated, the action registered -            with action_name will be used. -            The 'action_name' must be previously registered by -            either 'register_action' or 'register_bjam_action' -            method. -        """ -        assert(isinstance(properties, property_set.PropertySet)) -        if isinstance (targets, str):  -            targets = [targets] -        self.do_set_update_action (action_name, targets, sources, properties) - -    def register_action (self, action_name, command, bound_list = [], flags = [], -                         function = None): -        """Creates a new build engine action. - -        Creates on bjam side an action named 'action_name', with -        'command' as the command to be executed, 'bound_variables' -        naming the list of variables bound when the command is executed -        and specified flag. -        If 'function' is not None, it should be a callable taking three -        parameters: -            - targets -            - sources -            - instance of the property_set class -        This function will be called by set_update_action, and can -        set additional target variables. -        """ -        if self.actions.has_key(action_name): -            raise "Bjam action %s is already defined" % action_name - -        assert(isinstance(flags, list)) - -        bjam_flags = reduce(operator.or_, -                            (action_modifiers[flag] for flag in flags), 0) - -        bjam_interface.define_action(action_name, command, bound_list, bjam_flags) - -        self.actions[action_name] = BjamAction(action_name, function) - -    def register_bjam_action (self, action_name, function=None): -        """Informs self that 'action_name' is declared in bjam. - -        From this point, 'action_name' is a valid argument to the -        set_update_action method. The action_name should be callable -        in the global module of bjam. -        """ - -        # We allow duplicate calls to this rule for the same -        # action name.  This way, jamfile rules that take action names -        # can just register them without specially checking if -        # action is already registered. -        if not self.actions.has_key(action_name): -            self.actions[action_name] = BjamNativeAction(action_name, function) -     -    # Overridables - - -    def do_set_update_action (self, action_name, targets, sources, property_set): -        action = self.actions.get(action_name) -        if not action: -            raise Exception("No action %s was registered" % action_name) -        action(targets, sources, property_set) - -    def do_set_target_variable (self, target, variable, value, append): -        if append: -            bjam_interface.call("set-target-variable", target, variable, value, "true") -        else: -            bjam_interface.call("set-target-variable", target, variable, value) -         -    def do_add_dependency (self, target, source): -        bjam_interface.call("DEPENDS", target, source) -          -         diff --git a/jam-files/boost-build/build/errors.py b/jam-files/boost-build/build/errors.py deleted file mode 100644 index d9dceefe..00000000 --- a/jam-files/boost-build/build/errors.py +++ /dev/null @@ -1,127 +0,0 @@ -# Status: being written afresh by Vladimir Prus - -# Copyright 2007 Vladimir Prus  -# Distributed under the Boost Software License, Version 1.0.  -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)  - -# This file is supposed to implement error reporting for Boost.Build. -# Experience with jam version has shown that printing full backtrace -# on each error is buffling. Further, for errors printed after parsing -- -# during target building, the stacktrace does not even mention what -# target is being built. - -# This module implements explicit contexts -- where other code can -# communicate which projects/targets are being built, and error -# messages will show those contexts. For programming errors, -# Python assertions are to be used. - -import bjam -import traceback -import sys - -def format(message, prefix=""): -    parts = str(message).split("\n") -    return "\n".join(prefix+p for p in parts) -     - -class Context: - -    def __init__(self, message, nested=None): -        self.message_ = message -        self.nested_ = nested - -    def report(self, indent=""): -        print indent + "    -", self.message_ -        if self.nested_: -            print indent + "        declared at:" -            for n in self.nested_: -                n.report(indent + "    ") - -class JamfileContext: - -    def __init__(self): -        raw = bjam.backtrace() -        self.raw_ = raw - -    def report(self, indent=""): -        for r in self.raw_: -            print indent + "    - %s:%s" % (r[0], r[1]) - -class ExceptionWithUserContext(Exception): - -    def __init__(self, message, context, -                 original_exception=None, original_tb=None, stack=None): -        Exception.__init__(self, message) -        self.context_ = context -        self.original_exception_ = original_exception -        self.original_tb_ = original_tb -        self.stack_ = stack - -    def report(self): -        print "error:", self.args[0] -        if self.original_exception_: -            print format(str(self.original_exception_), "    ") -        print -        print "    error context (most recent first):" -        for c in self.context_[::-1]: -            c.report() -        print -        if "--stacktrace" in bjam.variable("ARGV"): -            if self.original_tb_: -                traceback.print_tb(self.original_tb_) -            elif self.stack_: -                for l in traceback.format_list(self.stack_): -                    print l,                 -        else: -            print "    use the '--stacktrace' option to get Python stacktrace" -        print - -def user_error_checkpoint(callable): -    def wrapper(self, *args): -        errors = self.manager().errors() -        try: -            return callable(self, *args) -        except ExceptionWithUserContext, e: -            raise -        except Exception, e: -            errors.handle_stray_exception(e) -        finally: -            errors.pop_user_context() -             -    return wrapper -                             -class Errors: - -    def __init__(self): -        self.contexts_ = [] -        self._count = 0 - -    def count(self): -        return self._count - -    def push_user_context(self, message, nested=None): -        self.contexts_.append(Context(message, nested)) - -    def pop_user_context(self): -        del self.contexts_[-1] - -    def push_jamfile_context(self): -        self.contexts_.append(JamfileContext()) - -    def pop_jamfile_context(self): -        del self.contexts_[-1] - -    def capture_user_context(self): -        return self.contexts_[:] - -    def handle_stray_exception(self, e): -        raise ExceptionWithUserContext("unexpected exception", self.contexts_[:], -                                       e, sys.exc_info()[2])     -    def __call__(self, message): -        self._count = self._count + 1 -        raise ExceptionWithUserContext(message, self.contexts_[:],  -                                       stack=traceback.extract_stack()) - -         - -     diff --git a/jam-files/boost-build/build/feature.jam b/jam-files/boost-build/build/feature.jam deleted file mode 100644 index 6f54adef..00000000 --- a/jam-files/boost-build/build/feature.jam +++ /dev/null @@ -1,1335 +0,0 @@ -# Copyright 2001, 2002, 2003 Dave Abrahams -# Copyright 2002, 2006 Rene Rivera -# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - -import assert : * ; -import "class" : * ; -import errors : lol->list ; -import indirect ; -import modules ; -import regex ; -import sequence ; -import set ; -import utility ; - - -local rule setup ( ) -{ -    .all-attributes = -        implicit -        composite -        optional -        symmetric -        free -        incidental -        path -        dependency -        propagated -        link-incompatible -        subfeature -        order-sensitive -    ; - -    .all-features = ; -    .all-subfeatures = ; -    .all-top-features = ;  # non-subfeatures -    .all-implicit-values = ; -} -setup ; - - -# Prepare a fresh space to test in by moving all global variable settings into -# the given temporary module and erasing them here. -# -rule prepare-test ( temp-module ) -{ -    DELETE_MODULE $(temp-module) ; - -    # Transfer globals to temp-module. -    for local v in [ VARNAMES feature ] -    { -        if [ MATCH (\\.) : $(v) ] -        { -            modules.poke $(temp-module) : $(v) : $($(v)) ; -            $(v) = ; -        } -    } -    setup ; -} - - -# Clear out all global variables and recover all variables from the given -# temporary module. -# -rule finish-test ( temp-module ) -{ -    # Clear globals. -    for local v in [ VARNAMES feature ] -    { -        if [ MATCH (\\.) : $(v) ] -        { -            $(v) = ; -        } -    } - -    for local v in [ VARNAMES $(temp-module) ] -    { -        $(v) = [ modules.peek $(temp-module) : $(v) ] ; -    } -    DELETE_MODULE $(temp-module) ; -} - - -# Transform features by bracketing any elements which are not already bracketed -# by "<>". -# -local rule grist ( features * ) -{ -    local empty = "" ; -    return $(empty:G=$(features)) ; -} - - -# Declare a new feature with the given name, values, and attributes. -# -rule feature ( -      name          # Feature name. -    : values *      # Allowable values - may be extended later using feature.extend. -    : attributes *  # Feature attributes (e.g. implicit, free, propagated...). -) -{ -    name = [ grist $(name) ] ; - -    local error ; - -    # Check for any unknown attributes. -    if ! ( $(attributes) in $(.all-attributes) ) -    { -        error = unknown attributes: -            [ set.difference $(attributes) : $(.all-attributes) ] ; -    } -    else if $(name) in $(.all-features) -    { -        error = feature already defined: ; -    } -    else if implicit in $(attributes) && free in $(attributes) -    { -        error = free features cannot also be implicit ; -    } -    else if free in $(attributes) && propagated in $(attributes) -    { -        error = free features cannot be propagated ; -    } -    else -    { -        local m = [ MATCH (.*=.*) : $(values) ] ; -        if $(m[1]) -        { -            error = "feature value may not contain '='" ; -        } -    } - -    if $(error) -    { -        errors.error $(error) -              : "in" feature declaration: -              : feature [ lol->list $(1) : $(2) : $(3) ] ; -    } - -    $(name).values ?= ; -    $(name).attributes = $(attributes) ; -    $(name).subfeatures ?= ; -    $(attributes).features += $(name) ; - -    .all-features += $(name) ; -    if subfeature in $(attributes) -    { -        .all-subfeatures += $(name) ; -    } -    else -    { -        .all-top-features += $(name) ; -    } -    extend $(name) : $(values) ; -} - - -# Sets the default value of the given feature, overriding any previous default. -# -rule set-default ( feature : value ) -{ -    local f = [ grist $(feature) ] ; -    local a = $($(f).attributes) ; -    local bad-attribute = ; -    if free in $(a) -    { -        bad-attribute = free ; -    } -    else if optional in $(a) -    { -        bad-attribute = optional ; -    } -    if $(bad-attribute) -    { -        errors.error "$(bad-attribute) property $(f) cannot have a default." ; -    } -    if ! $(value) in $($(f).values) -    { -        errors.error "The specified default value, '$(value)' is invalid" -          : "allowed values are: " $($(f).values) ; -    } -    $(f).default = $(value) ; -} - - -# Returns the default property values for the given features. -# -rule defaults ( features * ) -{ -    local result ; -    for local f in $(features) -    { -        local gf = $(:E=:G=$(f)) ; -        local a = $($(gf).attributes) ; -        if ( free in $(a) ) || ( optional in $(a) ) -        { -        } -        else -        { -            result += $(gf)$($(gf).default) ; -        } -    } -    return $(result) ; -} - - -# Returns true iff all 'names' elements are valid features. -# -rule valid ( names + ) -{ -    if $(names) in $(.all-features) -    { -        return true ; -    } -} - - -# Returns the attibutes of the given feature. -# -rule attributes ( feature ) -{ -    return $($(:E=:G=$(feature)).attributes) ; -} - - -# Returns the values of the given feature. -# -rule values ( feature ) -{ -    return $($(:E=:G=$(feature)).values) ; -} - - -# Returns true iff 'value-string' is a value-string of an implicit feature. -# -rule is-implicit-value ( value-string ) -{ -    local v = [ regex.split $(value-string) - ] ; -    local failed ; -    if ! $(v[1]) in $(.all-implicit-values) -    { -        failed = true ; -    } -    else -    { -        local feature = $($(v[1]).implicit-feature) ; -        for local subvalue in $(v[2-]) -        { -            if ! [ find-implied-subfeature $(feature) $(subvalue) : $(v[1]) ] -            { -                failed = true ; -            } -        } -    } - -    if ! $(failed) -    { -        return true ; -    } -} - - -# Returns the implicit feature associated with the given implicit value. -# -rule implied-feature ( implicit-value ) -{ -    local components = [ regex.split $(implicit-value) "-" ] ; - -    local feature = $($(components[1]).implicit-feature) ; -    if ! $(feature) -    { -        errors.error \"$(implicit-value)\" is not a value of an implicit feature ; -        feature = "" ;  # Keep testing happy; it expects a result. -    } -    return $(feature) ; -} - - -local rule find-implied-subfeature ( feature subvalue : value-string ? ) -{ -    # Feature should be of the form <feature-name>. -    if $(feature) != $(feature:G) -    { -        errors.error invalid feature $(feature) ; -    } - -    return $($(feature)$(value-string:E="")<>$(subvalue).subfeature) ; -} - - -# Given a feature and a value of one of its subfeatures, find the name of the -# subfeature. If value-string is supplied, looks for implied subfeatures that -# are specific to that value of feature -# -rule implied-subfeature ( -      feature         # The main feature name. -      subvalue        # The value of one of its subfeatures. -    : value-string ?  # The value of the main feature. -) -{ -    local subfeature = [ find-implied-subfeature $(feature) $(subvalue) -        : $(value-string) ] ; -    if ! $(subfeature) -    { -        value-string ?= "" ; -        errors.error \"$(subvalue)\" is not a known subfeature value of -            $(feature)$(value-string) ; -    } -    return $(subfeature) ; -} - - -# Generate an error if the feature is unknown. -# -local rule validate-feature ( feature ) -{ -    if ! $(feature) in $(.all-features) -    { -        errors.error unknown feature \"$(feature)\" ; -    } -} - - -# Given a feature and its value or just a value corresponding to an implicit -# feature, returns a property set consisting of all component subfeatures and -# their values. For example all the following calls: -# -#   expand-subfeatures-aux <toolset>gcc-2.95.2-linux-x86 -#   expand-subfeatures-aux gcc-2.95.2-linux-x86 -# -# return: -# -#   <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86 -# -local rule expand-subfeatures-aux ( -      feature ?        # Feature name or empty if value corresponds to an -                       # implicit property. -    : value            # Feature value. -    : dont-validate ?  # If set, no value string validation will be done. -) -{ -    if $(feature) -    { -        feature = $(feature) ; -    } - -    if ! $(feature) -    { -        feature = [ implied-feature $(value) ] ; -    } -    else -    { -        validate-feature $(feature) ; -    } -    if ! $(dont-validate) -    { -        validate-value-string $(feature) $(value) ; -    } - -    local components = [ regex.split $(value) "-" ] ; - -    # Get the top-level feature's value. -    local value = $(components[1]:G=) ; - -    local result = $(components[1]:G=$(feature)) ; - -    local subvalues = $(components[2-]) ; -    while $(subvalues) -    { -        local subvalue = $(subvalues[1]) ;  # Pop the head off of subvalues. -        subvalues = $(subvalues[2-]) ; - -        local subfeature = [ find-implied-subfeature $(feature) $(subvalue) : -            $(value) ] ; - -        # If no subfeature was found reconstitute the value string and use that. -        if ! $(subfeature) -        { -            result = $(components:J=-) ; -            result = $(result:G=$(feature)) ; -            subvalues = ;  # Stop looping. -        } -        else -        { -            local f = [ MATCH ^<(.*)>$ : $(feature) ] ; -            result += $(subvalue:G=$(f)-$(subfeature)) ; -        } -    } - -    return $(result) ; -} - - -# Make all elements of properties corresponding to implicit features explicit, -# and express all subfeature values as separate properties in their own right. -# For example, all of the following properties -# -#    gcc-2.95.2-linux-x86 -#    <toolset>gcc-2.95.2-linux-x86 -# -# might expand to -# -#   <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86 -# -rule expand-subfeatures ( -    properties *       # Property set with elements of the form -                       # <feature>value-string or just value-string in the case -                       # of implicit features. -    : dont-validate ? -) -{ -    local result ; -    for local p in $(properties) -    { -        # Don't expand subfeatures in subfeatures -        if ! [ MATCH "(:)" : $(p:G) ] -        { -            result += [ expand-subfeatures-aux $(p:G) : $(p:G=) : $(dont-validate) ] ; -        } -        else -        { -            result += $(p) ; -        } -    } -    return $(result) ; -} - - -# Helper for extend, below. Handles the feature case. -# -local rule extend-feature ( feature : values * ) -{ -    feature = [ grist $(feature) ] ; -    validate-feature $(feature) ; -    if implicit in $($(feature).attributes) -    { -        for local v in $(values) -        { -            if $($(v).implicit-feature) -            { -                errors.error $(v) is already associated with the \"$($(v).implicit-feature)\" feature ; -            } -            $(v).implicit-feature = $(feature) ; -        } - -        .all-implicit-values += $(values) ; -    } -    if ! $($(feature).values) -    { -        # This is the first value specified for this feature so make it be the -        # default. -        $(feature).default = $(values[1]) ; -    } -    $(feature).values += $(values) ; -} - - -# Checks that value-string is a valid value-string for the given feature. -# -rule validate-value-string ( feature value-string ) -{ -    if ! ( -        free in $($(feature).attributes) -        || ( $(value-string) in $(feature).values ) -    ) -    { -        local values = $(value-string) ; - -        if $($(feature).subfeatures) -        { -            if ! ( $(value-string) in $($(feature).values) ) -               && ! ( $(value-string) in $($(feature).subfeatures) )  -            { -                values = [ regex.split $(value-string) - ] ; -            } -        } - -        if ! ( $(values[1]) in $($(feature).values) ) && - -            # An empty value is allowed for optional features. -            ( $(values[1]) || ! ( optional in $($(feature).attributes) ) ) -        { -            errors.error \"$(values[1])\" is not a known value of feature $(feature) -                : legal values: \"$($(feature).values)\" ; -        } - -        for local v in $(values[2-]) -        { -            # This will validate any subfeature values in value-string. -            implied-subfeature $(feature) $(v) : $(values[1]) ; -        } -    } -} - - -# A helper that computes: -#  * name(s) of module-local variable(s) used to record the correspondence -#    between subvalue(s) and a subfeature -#  * value of that variable when such a subfeature/subvalue has been defined and -# returns a list consisting of the latter followed by the former. -# -local rule subvalue-var ( -    feature         # Main feature name. -    value-string ?  # If supplied, specifies a specific value of the main -                    # feature for which the subfeature values are valid. -    : subfeature    # Subfeature name. -    : subvalues *   # Subfeature values. -) -{ -    feature = [ grist $(feature) ] ; -    validate-feature $(feature) ; -    if $(value-string) -    { -        validate-value-string $(feature) $(value-string) ; -    } - -    local subfeature-name = [ get-subfeature-name $(subfeature) $(value-string) ] ; - -    return $(subfeature-name) -    $(feature)$(value-string:E="")<>$(subvalues).subfeature ; -} - - -# Extends the given subfeature with the subvalues. If the optional value-string -# is provided, the subvalues are only valid for the given value of the feature. -# Thus, you could say that <target-platform>mingw is specific to -# <toolset>gcc-2.95.2 as follows: -# -#       extend-subfeature toolset gcc-2.95.2 : target-platform : mingw ; -# -rule extend-subfeature ( -    feature         # The feature whose subfeature is being extended. - -    value-string ?  # If supplied, specifies a specific value of the main -                    # feature for which the new subfeature values are valid. - -    : subfeature    # Subfeature name. -    : subvalues *   # Additional subfeature values. -) -{ -    local subfeature-vars = [ subvalue-var $(feature) $(value-string) -        : $(subfeature) : $(subvalues) ] ; - -    local f = [ utility.ungrist [ grist $(feature) ] ] ; -    extend $(f)-$(subfeature-vars[1]) : $(subvalues) ; - -    # Provide a way to get from the given feature or property and subfeature -    # value to the subfeature name. -    $(subfeature-vars[2-]) = $(subfeature-vars[1]) ; -} - - -# Returns true iff the subvalues are valid for the feature. When the optional -# value-string is provided, returns true iff the subvalues are valid for the -# given value of the feature. -# -rule is-subvalue ( feature : value-string ? : subfeature : subvalue ) -{ -    local subfeature-vars = [ subvalue-var $(feature) $(value-string) -        : $(subfeature) : $(subvalue) ] ; - -    if $($(subfeature-vars[2])) = $(subfeature-vars[1]) -    { -        return true ; -    } -} - - -# Can be called three ways: -# -#    1. extend feature : values * -#    2. extend <feature> subfeature : values * -#    3. extend <feature>value-string subfeature : values * -# -# * Form 1 adds the given values to the given feature. -# * Forms 2 and 3 add subfeature values to the given feature. -# * Form 3 adds the subfeature values as specific to the given property -#   value-string. -# -rule extend ( feature-or-property subfeature ? : values * ) -{ -    local feature ;       # If a property was specified this is its feature. -    local value-string ;  # E.g., the gcc-2.95-2 part of <toolset>gcc-2.95.2. - -    # If a property was specified. -    if $(feature-or-property:G) && $(feature-or-property:G=) -    { -        # Extract the feature and value-string, if any. -        feature = $(feature-or-property:G) ; -        value-string = $(feature-or-property:G=) ; -    } -    else -    { -        feature = [ grist $(feature-or-property) ] ; -    } - -    # Dispatch to the appropriate handler. -    if $(subfeature) -    { -        extend-subfeature $(feature) $(value-string) : $(subfeature) -            : $(values) ; -    } -    else -    { -        # If no subfeature was specified, we do not expect to see a -        # value-string. -        if $(value-string) -        { -            errors.error can only specify a property as the first argument when -                extending a subfeature -                : usage: -                : "    extend" feature ":" values... -                : "  | extend" <feature>value-string subfeature ":" values... -                ; -        } - -        extend-feature $(feature) : $(values) ; -    } -} - - -local rule get-subfeature-name ( subfeature value-string ? ) -{ -    local prefix = $(value-string): ; -    return $(prefix:E="")$(subfeature) ; -} - - -# Declares a subfeature. -# -rule subfeature ( -    feature         # Root feature that is not a subfeature. -    value-string ?  # A value-string specifying which feature or subfeature -                    # values this subfeature is specific to, if any. -    : subfeature    # The name of the subfeature being declared. -    : subvalues *   # The allowed values of this subfeature. -    : attributes *  # The attributes of the subfeature. -) -{ -    feature = [ grist $(feature) ] ; -    validate-feature $(feature) ; - -    # Add grist to the subfeature name if a value-string was supplied. -    local subfeature-name = [ get-subfeature-name $(subfeature) $(value-string) ] ; - -    if $(subfeature-name) in $($(feature).subfeatures) -    { -        errors.error \"$(subfeature)\" already declared as a subfeature of \"$(feature)\" -            "specific to "$(value-string) ; -    } -    $(feature).subfeatures += $(subfeature-name) ; - -    # First declare the subfeature as a feature in its own right. -    local f = [ utility.ungrist $(feature) ] ; -    feature $(f)-$(subfeature-name) : $(subvalues) : $(attributes) subfeature ; - -    # Now make sure the subfeature values are known. -    extend-subfeature $(feature) $(value-string) : $(subfeature) : $(subvalues) ; -} - - -# Set components of the given composite property. -# -rule compose ( composite-property : component-properties * ) -{ -    local feature = $(composite-property:G) ; -    if ! ( composite in [ attributes $(feature) ] ) -    { -        errors.error "$(feature)" is not a composite feature ; -    } - -    $(composite-property).components ?= ; -    if $($(composite-property).components) -    { -        errors.error components of "$(composite-property)" already set: -            $($(composite-property).components) ; -    } - -    if $(composite-property) in $(component-properties) -    { -        errors.error composite property "$(composite-property)" cannot have itself as a component ; -    } -    $(composite-property).components = $(component-properties) ; -} - - -local rule expand-composite ( property ) -{ -    return $(property) -        [ sequence.transform expand-composite : $($(property).components) ] ; -} - - -# Return all values of the given feature specified by the given property set. -# -rule get-values ( feature : properties * ) -{ -    local result ; - -    feature = $(:E=:G=$(feature)) ;  # Add <> if necessary. -    for local p in $(properties) -    { -        if $(p:G) = $(feature) -        { -            # Use MATCH instead of :G= to get the value, in order to preserve -            # the value intact instead of having bjam treat it as a decomposable -            # path. -            result += [ MATCH ">(.*)" : $(p) ] ; -        } -    } -    return $(result) ; -} - - -rule free-features ( ) -{ -    return $(free.features) ; -} - - -# Expand all composite properties in the set so that all components are -# explicitly expressed. -# -rule expand-composites ( properties * ) -{ -    local explicit-features = $(properties:G) ; -    local result ; - -    # Now expand composite features. -    for local p in $(properties) -    { -        local expanded = [ expand-composite $(p) ] ; - -        for local x in $(expanded) -        { -            if ! $(x) in $(result) -            { -                local f = $(x:G) ; - -                if $(f) in $(free.features) -                { -                    result += $(x) ; -                } -                else if ! $(x) in $(properties)  # x is the result of expansion -                { -                    if ! $(f) in $(explicit-features)  # not explicitly-specified -                    { -                        if $(f) in $(result:G) -                        { -                            errors.error expansions of composite features result -                                in conflicting values for $(f) -                                : values: [ get-values $(f) : $(result) ] $(x:G=) -                                : one contributing composite property was $(p) ; -                        } -                        else -                        { -                            result += $(x) ; -                        } -                    } -                } -                else if $(f) in $(result:G) -                { -                    errors.error explicitly-specified values of non-free feature -                        $(f) conflict : -                        "existing values:" [ get-values $(f) : $(properties) ] : -                        "value from expanding " $(p) ":" $(x:G=) ; -                } -                else -                { -                    result += $(x) ; -                } -            } -        } -    } -    return $(result) ; -} - - -# Return true iff f is an ordinary subfeature of the parent-property's feature, -# or if f is a subfeature of the parent-property's feature specific to the -# parent-property's value. -# -local rule is-subfeature-of ( parent-property f ) -{ -    if subfeature in $($(f).attributes) -    { -        local specific-subfeature = [ MATCH <(.*):(.*)> : $(f) ] ; -        if $(specific-subfeature) -        { -            # The feature has the form <topfeature-topvalue:subfeature>, e.g. -            # <toolset-msvc:version>. -            local feature-value = [ split-top-feature $(specific-subfeature[1]) -                ] ; -            if <$(feature-value[1])>$(feature-value[2]) = $(parent-property) -            { -                return true ; -            } -        } -        else -        { -            # The feature has the form <topfeature-subfeature>, e.g. -            # <toolset-version> -            local top-sub = [ split-top-feature [ utility.ungrist $(f) ] ] ; -            if $(top-sub[2]) && <$(top-sub[1])> = $(parent-property:G) -            { -                return true ; -            } -        } -    } -} - - -# As for is-subfeature-of but for subproperties. -# -local rule is-subproperty-of ( parent-property p ) -{ -    return [ is-subfeature-of $(parent-property) $(p:G) ] ; -} - - -# Given a property, return the subset of features consisting of all ordinary -# subfeatures of the property's feature, and all specific subfeatures of the -# property's feature which are conditional on the property's value. -# -local rule select-subfeatures ( parent-property : features * ) -{ -    return [ sequence.filter is-subfeature-of $(parent-property) : $(features) ] ; -} - - -# As for select-subfeatures but for subproperties. -# -local rule select-subproperties ( parent-property : properties * ) -{ -    return [ sequence.filter is-subproperty-of $(parent-property) : $(properties) ] ; -} - - -# Given a property set which may consist of composite and implicit properties -# and combined subfeature values, returns an expanded, normalized property set -# with all implicit features expressed explicitly, all subfeature values -# individually expressed, and all components of composite properties expanded. -# Non-free features directly expressed in the input properties cause any values -# of those features due to composite feature expansion to be dropped. If two -# values of a given non-free feature are directly expressed in the input, an -# error is issued. -# -rule expand ( properties * ) -{ -    local expanded = [ expand-subfeatures $(properties) ] ; -    return [ expand-composites $(expanded) ] ; -} - - -# Helper rule for minimize. Returns true iff property's feature is present in -# the contents of the variable named by feature-set-var. -# -local rule in-features ( feature-set-var property ) -{ -    if $(property:G) in $($(feature-set-var)) -    { -        return true ; -    } -} - - -# Helper rule for minimize. Returns the list with the same properties, but with -# all subfeatures moved to the end of the list. -# -local rule move-subfeatures-to-the-end ( properties * ) -{ -    local x1 ; -    local x2 ; -    for local p in $(properties) -    { -        if subfeature in $($(p:G).attributes) -        { -            x2 += $(p) ; -        } -        else -        { -            x1 += $(p) ; -        } -    } -    return $(x1) $(x2) ; -} - - -# Given an expanded property set, eliminate all redundancy: properties that are -# elements of other (composite) properties in the set will be eliminated. -# Non-symmetric properties equal to default values will be eliminated unless -# they override a value from some composite property. Implicit properties will -# be expressed without feature grist, and sub-property values will be expressed -# as elements joined to the corresponding main property. -# -rule minimize ( properties * ) -{ -    # Precondition checking -    local implicits = [ set.intersection $(p:G=) : $(p:G) ] ; -    if $(implicits) -    { -        errors.error minimize requires an expanded property set, but -            \"$(implicits[1])\" appears to be the value of an un-expanded -            implicit feature ; -    } - -    # Remove properties implied by composite features. -    local components = $($(properties).components) ; -    local x = [ set.difference $(properties) : $(components) ] ; - -    # Handle subfeatures and implicit features. -    x = [ move-subfeatures-to-the-end $(x) ] ; -    local result ; -    while $(x) -    { -        local p fullp = $(x[1]) ; -        local f = $(p:G) ; -        local v = $(p:G=) ; - -        # Eliminate features in implicit properties. -        if implicit in [ attributes $(f) ] -        { -            p = $(v) ; -        } - -        # Locate all subproperties of $(x[1]) in the property set. -        local subproperties = [ select-subproperties $(fullp) : $(x) ] ; -        if $(subproperties) -        { -            # Reconstitute the joined property name. -            local sorted = [ sequence.insertion-sort $(subproperties) ] ; -            result += $(p)-$(sorted:G="":J=-) ; - -            x = [ set.difference $(x[2-]) : $(subproperties) ] ; -        } -        else -        { -            # Eliminate properties whose value is equal to feature's default, -            # which are not symmetric and which do not contradict values implied -            # by composite properties. - -            # Since all component properties of composites in the set have been -            # eliminated, any remaining property whose feature is the same as a -            # component of a composite in the set must have a non-redundant -            # value. -            if $(fullp) != [ defaults $(f) ] -                || symmetric in [ attributes $(f) ] -                || $(fullp:G) in $(components:G) -            { -                result += $(p) ; -            } - -            x = $(x[2-]) ; -        } -    } -    return $(result) ; -} - - -# Combine all subproperties into their parent properties -# -# Requires: for every subproperty, there is a parent property. All features are -# explicitly expressed. -# -# This rule probably should not be needed, but build-request.expand-no-defaults -# is being abused for unintended purposes and it needs help. -# -rule compress-subproperties ( properties * ) -{ -    local all-subs ; -    local matched-subs ; -    local result ; - -    for local p in $(properties) -    { -        if ! $(p:G) -        { -            # Expecting fully-gristed properties. -            assert.variable-not-empty p:G ; -        } - -        if ! subfeature in $($(p:G).attributes) -        { -            local subs = [ sequence.insertion-sort -                [ sequence.filter is-subproperty-of $(p) : $(properties) ] ] ; - -            matched-subs += $(subs) ; - -            local subvalues = -$(subs:G=:J=-) ; -            subvalues ?= "" ; -            result += $(p)$(subvalues) ; -        } -        else -        { -            all-subs += $(p) ; -        } -    } -    assert.result true : set.equal $(all-subs) : $(matched-subs) ; -    return $(result) ; -} - - -# Given an ungristed string, finds the longest prefix which is a top-level -# feature name followed by a dash, and return a pair consisting of the parts -# before and after that dash. More interesting than a simple split because -# feature names may contain dashes. -# -local rule split-top-feature ( feature-plus ) -{ -    local e = [ regex.split $(feature-plus) - ] ; -    local f = $(e[1]) ; -    local v ; -    while $(e) -    { -        if <$(f)> in $(.all-top-features) -        { -            v = $(f) $(e[2-]:J=-) ; -        } -        e = $(e[2-]) ; -        f = $(f)-$(e[1]) ; -    } -    return $(v) ; -} - - -# Given a set of properties, add default values for features not represented in -# the set. -# -# Note: if there's an ordinary feature F1 and a composite feature F2 which -# includes some value for F1 and both feature have default values then the -# default value of F1 will be added (as opposed to the value in F2). This might -# not be the right idea, e.g. consider: -# -#   feature variant : debug ... ; -#        <variant>debug : .... <runtime-debugging>on -#   feature <runtime-debugging> : off on ; -# -#   Here, when adding default for an empty property set, we'll get -# -#     <variant>debug <runtime_debugging>off -# -#   and that's kind of strange. -# -rule add-defaults ( properties * ) -{ -    for local v in $(properties:G=) -    { -        if $(v) in $(properties) -        { -            errors.error add-defaults requires explicitly specified features, -                but \"$(v)\" appears to be the value of an un-expanded implicit -                feature ; -        } -    } -    # We don't add default for elements with ":" inside. This catches: -    # 1. Conditional properties --- we don't want <variant>debug:<define>DEBUG -    #    to be takes as specified value for <variant> -    # 2. Free properties with ":" in values. We don't care, since free -    #    properties don't have defaults. -    local xproperties = [ MATCH "^([^:]+)$" : $(properties) ] ; -    local missing-top = [ set.difference $(.all-top-features) : $(xproperties:G) ] ; -    local more =  [ defaults $(missing-top) ] ; -    properties += $(more) ; -    xproperties += $(more) ; - -    # Add defaults for subfeatures of features which are present. -    for local p in $(xproperties) -    { -        local s = $($(p:G).subfeatures) ; -        local f = [ utility.ungrist $(p:G) ] ; -        local missing-subs = [ set.difference <$(f)-$(s)> : $(properties:G) ] ; -        properties += [ defaults [ select-subfeatures $(p) : $(missing-subs) ] ] ; -    } - -    return $(properties)  ; -} - - -# Given a property-set of the form -#       v1/v2/...vN-1/<fN>vN/<fN+1>vN+1/...<fM>vM -# -# Returns -#       v1 v2 ... vN-1 <fN>vN <fN+1>vN+1 ... <fM>vM -# -# Note that vN...vM may contain slashes. This needs to be resilient to the -# substitution of backslashes for slashes, since Jam, unbidden, sometimes swaps -# slash direction on NT. -# -rule split ( property-set ) -{ -    local pieces = [ regex.split $(property-set) [\\/] ] ; -    local result ; - -    for local x in $(pieces) -    { -        if ( ! $(x:G) ) && $(result[-1]:G) -        { -            result = $(result[1--2]) $(result[-1])/$(x) ; -        } -        else -        { -            result += $(x) ; -        } -    } - -    return $(result) ; -} - - -# Tests of module feature. -# -rule __test__ ( ) -{ -    # Use a fresh copy of the feature module. -    prepare-test feature-test-temp ; - -    import assert ; -    import errors : try catch ; - -    # These are local rules and so must be explicitly reimported into the -    # testing module. -    import feature : extend-feature validate-feature select-subfeatures ; - -    feature toolset : gcc : implicit ; -    feature define : : free ; -    feature runtime-link : dynamic static : symmetric ; -    feature optimization : on off ; -    feature variant : debug release profile : implicit composite symmetric ; -    feature stdlib : native stlport ; -    feature magic : : free ; - -    compose <variant>debug : <define>_DEBUG <optimization>off ; -    compose <variant>release : <define>NDEBUG <optimization>on ; - -    assert.result dynamic static : values <runtime-link> ; -    assert.result dynamic static : values runtime-link ; - -    try ; -    { -        compose <variant>profile : <variant>profile ; -    } -    catch composite property <variant>profile cannot have itself as a component ; - -    extend-feature toolset : msvc metrowerks ; -    subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4 3.0 3.0.1 3.0.2 ; - -    assert.true is-subvalue toolset : gcc : version : 2.95.3 ; -    assert.false is-subvalue toolset : gcc : version : 1.1 ; - -    assert.false is-subvalue toolset : msvc : version : 2.95.3 ; -    assert.false is-subvalue toolset : : version : yabba ; - -    feature yabba ; -    subfeature yabba : version : dabba ; -    assert.true is-subvalue yabba : : version : dabba ; - -    subfeature toolset gcc : platform : linux cygwin : optional ; - -    assert.result <toolset-gcc:version> -        : select-subfeatures <toolset>gcc -        : <toolset-gcc:version> -          <toolset-msvc:version> -          <toolset-version> -          <stdlib> ; - -    subfeature stdlib : version : 3 4 : optional ; - -    assert.result <stdlib-version> -        : select-subfeatures <stdlib>native -        : <toolset-gcc:version> -          <toolset-msvc:version> -          <toolset-version> -          <stdlib-version> ; - -    assert.result <toolset>gcc <toolset-gcc:version>3.0.1 -        : expand-subfeatures <toolset>gcc-3.0.1 ; - -    assert.result <toolset>gcc <toolset-gcc:version>3.0.1 <toolset-gcc:platform>linux -        : expand-subfeatures <toolset>gcc-3.0.1-linux ; - -    assert.result <toolset>gcc <toolset-gcc:version>3.0.1 -        : expand <toolset>gcc <toolset-gcc:version>3.0.1  ; - -    assert.result <define>foo=x-y -        : expand-subfeatures <define>foo=x-y ; - -    assert.result <toolset>gcc <toolset-gcc:version>3.0.1 -        : expand-subfeatures gcc-3.0.1 ; - -    assert.result a c e -        : get-values <x> : <x>a <y>b <x>c <y>d <x>e ; - -    assert.result <toolset>gcc <toolset-gcc:version>3.0.1 -        <variant>debug <define>_DEBUG <optimization>on -        : expand gcc-3.0.1 debug <optimization>on ; - -    assert.result <variant>debug <define>_DEBUG <optimization>on -        : expand debug <optimization>on ; - -    assert.result <optimization>on <variant>debug <define>_DEBUG -        : expand <optimization>on debug ; - -    assert.result <runtime-link>dynamic <optimization>on -        : defaults <runtime-link> <define> <optimization> ; - -    # Make sure defaults is resilient to missing grist. -    assert.result <runtime-link>dynamic <optimization>on -        : defaults runtime-link define optimization ; - -    feature dummy : dummy1 dummy2 ; -    subfeature dummy : subdummy : x y z : optional ; - -    feature fu : fu1 fu2 : optional ; -    subfeature fu : subfu : x y z : optional ; -    subfeature fu : subfu2 : q r s ; - -    assert.result optional : attributes <fu> ; -    assert.result optional : attributes fu ; - -    assert.result <runtime-link>static <define>foobar <optimization>on -        <toolset>gcc:<define>FOO <toolset>gcc <variant>debug <stdlib>native -        <dummy>dummy1 <toolset-gcc:version>2.95.2 -        : add-defaults <runtime-link>static <define>foobar <optimization>on -          <toolset>gcc:<define>FOO ; - -    assert.result <runtime-link>static <define>foobar <optimization>on -        <toolset>gcc:<define>FOO <fu>fu1 <toolset>gcc <variant>debug -        <stdlib>native <dummy>dummy1 <fu-subfu2>q <toolset-gcc:version>2.95.2 -        : add-defaults <runtime-link>static <define>foobar <optimization>on -          <toolset>gcc:<define>FOO <fu>fu1 ; - -    set-default <runtime-link> : static ; -    assert.result <runtime-link>static : defaults <runtime-link> ; - -    assert.result gcc-3.0.1 debug <optimization>on -        : minimize [ expand gcc-3.0.1 debug <optimization>on <stdlib>native ] ; - -    assert.result gcc-3.0.1 debug <runtime-link>dynamic -        : minimize -          [ expand gcc-3.0.1 debug <optimization>off <runtime-link>dynamic ] ; - -    assert.result gcc-3.0.1 debug -        : minimize [ expand gcc-3.0.1 debug <optimization>off ] ; - -    assert.result debug <optimization>on -        : minimize [ expand debug <optimization>on ] ; - -    assert.result gcc-3.0 -        : minimize <toolset>gcc <toolset-gcc:version>3.0 ; - -    assert.result gcc-3.0 -        : minimize <toolset-gcc:version>3.0 <toolset>gcc ; - -    assert.result <x>y/z <a>b/c <d>e/f -        : split <x>y/z/<a>b/c/<d>e/f ; - -    assert.result <x>y/z <a>b/c <d>e/f -        : split <x>y\\z\\<a>b\\c\\<d>e\\f ; - -    assert.result a b c <d>e/f/g <h>i/j/k -        : split a/b/c/<d>e/f/g/<h>i/j/k ; - -    assert.result a b c <d>e/f/g <h>i/j/k -        : split a\\b\\c\\<d>e\\f\\g\\<h>i\\j\\k ; - -    # Test error checking. - -    try ; -    { -        expand release <optimization>off <optimization>on ; -    } -    catch explicitly-specified values of non-free feature <optimization> conflict ; - -    try ; -    { -        validate-feature <foobar> ; -    } -    catch unknown feature ; - -    validate-value-string <toolset> gcc ; -    validate-value-string <toolset> gcc-3.0.1 ; - -    try ; -    { -        validate-value-string <toolset> digital_mars ; -    } -    catch \"digital_mars\" is not a known value of <toolset> ; - -    try ; -    { -        feature foobar : : baz ; -    } -    catch unknown attributes: baz ; - -    feature feature1 ; -    try ; -    { -        feature feature1 ; -    } -    catch feature already defined: ; - -    try ; -    { -        feature feature2 : : free implicit ; -    } -    catch free features cannot also be implicit ; - -    try ; -    { -        feature feature3 : : free propagated ; -    } -    catch free features cannot be propagated ; - -    try ; -    { -        implied-feature lackluster ; -    } -    catch \"lackluster\" is not a value of an implicit feature ; - -    try ; -    { -        implied-subfeature <toolset> 3.0.1 ; -    } -    catch \"3.0.1\" is not a known subfeature value of <toolset> ; - -    try ; -    { -        implied-subfeature <toolset> not-a-version : gcc ; -    } -    catch \"not-a-version\" is not a known subfeature value of <toolset>gcc ; - -    # Leave a clean copy of the features module behind. -    finish-test feature-test-temp ; -} diff --git a/jam-files/boost-build/build/feature.py b/jam-files/boost-build/build/feature.py deleted file mode 100644 index 315a18e9..00000000 --- a/jam-files/boost-build/build/feature.py +++ /dev/null @@ -1,905 +0,0 @@ -# Status: ported, except for unit tests. -# Base revision: 64488 -# -# Copyright 2001, 2002, 2003 Dave Abrahams  -# Copyright 2002, 2006 Rene Rivera  -# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus  -# Distributed under the Boost Software License, Version 1.0.  -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)  - -import re - -from b2.util import utility, bjam_signature -import b2.util.set -from b2.util.utility import add_grist, get_grist, ungrist, replace_grist, to_seq -from b2.exceptions import * - -__re_split_subfeatures = re.compile ('<(.*):(.*)>') -__re_no_hyphen = re.compile ('^([^:]+)$') -__re_slash_or_backslash = re.compile (r'[\\/]') - -class Feature(object): - -    # Map from string attribute names to integers bit flags. -    # This will be initialized after declaration of the class. -    _attribute_name_to_integer = {} - -    def __init__(self, name, values, attributes): -        self._name = name -        self._values = values -        self._default = None -        self._attributes = 0 -        for a in attributes: -            self._attributes = self._attributes | Feature._attribute_name_to_integer[a] -        self._attributes_string_list = attributes -        self._subfeatures = [] -        self._parent = None - -    def name(self): -        return self._name - -    def values(self): -        return self._values - -    def add_values(self, values): -        self._values.extend(values) - -    def attributes(self): -        return self._attributes - -    def set_default(self, value): -        self._default = value - -    def default(self): -        return self._default - -    # FIXME: remove when we fully move to using classes for features/properties -    def attributes_string_list(self): -        return self._attributes_string_list - -    def subfeatures(self): -        return self._subfeatures - -    def add_subfeature(self, name): -        self._subfeatures.append(name) - -    def parent(self): -        """For subfeatures, return pair of (parent_feature, value). - -        Value may be None if this subfeature is not specific to any -        value of the parent feature. -        """ -        return self._parent - -    def set_parent(self, feature, value): -        self._parent = (feature, value) - -    def __str__(self): -        return self._name - -     -def reset (): -    """ Clear the module state. This is mainly for testing purposes. -    """ -    global __all_attributes, __all_features, __implicit_features, __composite_properties -    global __features_with_attributes, __subfeature_from_value, __all_top_features, __free_features -    global __all_subfeatures -         -    # The list with all attribute names. -    __all_attributes = [ 'implicit', -                        'composite', -                        'optional', -                        'symmetric', -                        'free', -                        'incidental', -                        'path', -                        'dependency', -                        'propagated', -                        'link-incompatible', -                        'subfeature', -                        'order-sensitive' -                       ] -    i = 1 -    for a in __all_attributes: -        setattr(Feature, a.upper(), i) -        Feature._attribute_name_to_integer[a] = i -        def probe(self, flag=i): -            return getattr(self, "_attributes") & flag -        setattr(Feature, a.replace("-", "_"), probe) -        i = i << 1 -     -    # A map containing all features. The key is the feature name. -    # The value is an instance of Feature class. -    __all_features = {} -     -    # All non-subfeatures. -    __all_top_features = [] -     -    # Maps valus to the corresponding implicit feature -    __implicit_features = {} -     -    # A map containing all composite properties. The key is a Property instance, -    # and the value is a list of Property instances -    __composite_properties = {} -     -    __features_with_attributes = {} -    for attribute in __all_attributes: -        __features_with_attributes [attribute] = [] -     -    # Maps a value to the corresponding subfeature name. -    __subfeature_from_value = {} -     -    # All free features -    __free_features = [] - -    __all_subfeatures = [] - -reset () - -def enumerate (): -    """ Returns an iterator to the features map. -    """ -    return __all_features.iteritems () - -def get(name): -    """Return the Feature instance for the specified name. - -    Throws if no feature by such name exists -    """ -    return __all_features[name] - -# FIXME: prepare-test/finish-test? - -@bjam_signature((["name"], ["values", "*"], ["attributes", "*"])) -def feature (name, values, attributes = []): -    """ Declares a new feature with the given name, values, and attributes. -        name: the feature name -        values: a sequence of the allowable values - may be extended later with feature.extend -        attributes: a sequence of the feature's attributes (e.g. implicit, free, propagated, ...) -    """ -    __validate_feature_attributes (name, attributes) - -    feature = Feature(name, [], attributes) -    __all_features[name] = feature -    # Temporary measure while we have not fully moved from 'gristed strings' -    __all_features["<" + name + ">"] = feature -         -    for attribute in attributes: -        __features_with_attributes [attribute].append (name) - -    name = add_grist(name) -         -    if 'subfeature' in attributes: -        __all_subfeatures.append(name) -    else: -        __all_top_features.append(feature) - -    extend (name, values) - -    # FIXME: why his is needed. -    if 'free' in attributes: -        __free_features.append (name) - -    return feature - -@bjam_signature((["feature"], ["value"])) -def set_default (feature, value): -    """ Sets the default value of the given feature, overriding any previous default. -        feature: the name of the feature -        value: the default value to assign -    """ -    f = __all_features[feature] -    attributes = f.attributes() -    bad_attribute = None - -    if attributes & Feature.FREE: -        bad_attribute = "free" -    elif attributes & Feature.OPTIONAL: -        bad_attribute = "optional" -         -    if bad_attribute: -        raise InvalidValue ("%s property %s cannot have a default" % (bad_attribute, feature.name())) -         -    if not value in f.values(): -        raise InvalidValue ("The specified default value, '%s' is invalid.\n" % value + "allowed values are: %s" % values) - -    f.set_default(value) - -def defaults(features): -    """ Returns the default property values for the given features. -    """ -    # FIXME: should merge feature and property modules. -    import property -     -    result = [] -    for f in features: -        if not f.free() and not f.optional() and f.default(): -            result.append(property.Property(f, f.default())) - -    return result - -def valid (names): -    """ Returns true iff all elements of names are valid features. -    """ -    def valid_one (name): return __all_features.has_key (name) -         -    if isinstance (names, str): -        return valid_one (names) -    else: -        return [ valid_one (name) for name in names ] - -def attributes (feature): -    """ Returns the attributes of the given feature. -    """ -    return __all_features[feature].attributes_string_list() -         -def values (feature): -    """ Return the values of the given feature. -    """ -    validate_feature (feature) -    return __all_features[feature].values() - -def is_implicit_value (value_string): -    """ Returns true iff 'value_string' is a value_string -    of an implicit feature. -    """ - -    if __implicit_features.has_key(value_string): -        return __implicit_features[value_string] -     -    v = value_string.split('-') - -    if not __implicit_features.has_key(v[0]): -        return False - -    feature = __implicit_features[v[0]] -     -    for subvalue in (v[1:]): -        if not __find_implied_subfeature(feature, subvalue, v[0]): -            return False -             -    return True - -def implied_feature (implicit_value): -    """ Returns the implicit feature associated with the given implicit value. -    """ -    components = implicit_value.split('-') -     -    if not __implicit_features.has_key(components[0]): -        raise InvalidValue ("'%s' is not a value of an implicit feature" % implicit_value) -         -    return __implicit_features[components[0]] - -def __find_implied_subfeature (feature, subvalue, value_string): -     -    #if value_string == None: value_string = '' - -    if not __subfeature_from_value.has_key(feature) \ -        or not __subfeature_from_value[feature].has_key(value_string) \ -        or not __subfeature_from_value[feature][value_string].has_key (subvalue): -        return None -         -    return __subfeature_from_value[feature][value_string][subvalue] - -# Given a feature and a value of one of its subfeatures, find the name -# of the subfeature. If value-string is supplied, looks for implied -# subfeatures that are specific to that value of feature -#  feature             # The main feature name -#  subvalue            # The value of one of its subfeatures -#  value-string        # The value of the main feature - -def implied_subfeature (feature, subvalue, value_string): -    result = __find_implied_subfeature (feature, subvalue, value_string) -    if not result: -        raise InvalidValue ("'%s' is not a known subfeature value of '%s%s'" % (subvalue, feature, value_string)) - -    return result - -def validate_feature (name): -    """ Checks if all name is a valid feature. Otherwise, raises an exception. -    """ -    if not __all_features.has_key(name): -        raise InvalidFeature ("'%s' is not a valid feature name" % name) -    else: -        return __all_features[name] - -def valid (names): -    """ Returns true iff all elements of names are valid features. -    """ -    def valid_one (name): return __all_features.has_key (name) -         -    if isinstance (names, str): -        return valid_one (names) -    else: -        return [ valid_one (name) for name in names ] - -# Uses Property -def __expand_subfeatures_aux (property, dont_validate = False): -    """ Helper for expand_subfeatures. -        Given a feature and value, or just a value corresponding to an -        implicit feature, returns a property set consisting of all component -        subfeatures and their values. For example: -         -          expand_subfeatures <toolset>gcc-2.95.2-linux-x86 -              -> <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86 -          equivalent to: -              expand_subfeatures gcc-2.95.2-linux-x86 - -        feature:        The name of the feature, or empty if value corresponds to an implicit property -        value:          The value of the feature. -        dont_validate:  If True, no validation of value string will be done. -    """ -    f = property.feature() -    v = property.value() -    if not dont_validate: -        validate_value_string(f, v) - -    components = v.split ("-") -     -    v = components[0] - -    import property - -    result = [property.Property(f, components[0])]  -     -    subvalues = components[1:] - -    while len(subvalues) > 0: -        subvalue = subvalues [0]    # pop the head off of subvalues -        subvalues = subvalues [1:] -         -        subfeature = __find_implied_subfeature (f, subvalue, v) -         -        # If no subfeature was found, reconstitute the value string and use that -        if not subfeature: -            return [property.Property(f, '-'.join(components))] -             -        result.append(property.Property(subfeature, subvalue)) -     -    return result - -def expand_subfeatures(properties, dont_validate = False): -    """ -    Make all elements of properties corresponding to implicit features -    explicit, and express all subfeature values as separate properties -    in their own right. For example, the property -     -       gcc-2.95.2-linux-x86 -     -    might expand to -     -      <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86 - -    properties:     A sequence with elements of the form -                    <feature>value-string or just value-string in the -                    case of implicit features. -  : dont_validate:  If True, no validation of value string will be done. -    """ -    result = [] -    for p in properties: -        # Don't expand subfeatures in subfeatures -        if p.feature().subfeature(): -            result.append (p) -        else: -            result.extend(__expand_subfeatures_aux (p, dont_validate)) - -    return result - - - -# rule extend was defined as below: -    # Can be called three ways: -    # -    #    1. extend feature : values * -    #    2. extend <feature> subfeature : values * -    #    3. extend <feature>value-string subfeature : values * -    # -    # * Form 1 adds the given values to the given feature -    # * Forms 2 and 3 add subfeature values to the given feature -    # * Form 3 adds the subfeature values as specific to the given -    #   property value-string. -    # -    #rule extend ( feature-or-property subfeature ? : values * ) -# -# Now, the specific rule must be called, depending on the desired operation: -#   extend_feature -#   extend_subfeature - -def extend (name, values): -    """ Adds the given values to the given feature. -    """ -    name = add_grist (name) -    __validate_feature (name) -    feature = __all_features [name] - -    if feature.implicit(): -        for v in values: -            if __implicit_features.has_key(v): -                raise BaseException ("'%s' is already associated with the feature '%s'" % (v, __implicit_features [v])) - -            __implicit_features[v] = feature - -    if len (feature.values()) == 0 and len (values) > 0: -        # This is the first value specified for this feature, -        # take it as default value -        feature.set_default(values[0]) - -    feature.add_values(values) - -def validate_value_string (f, value_string): -    """ Checks that value-string is a valid value-string for the given feature. -    """ -    if f.free() or value_string in f.values(): -        return - -    values = [value_string] - -    if f.subfeatures(): -        if not value_string in f.values() and \ -               not value_string in f.subfeatures(): -            values = value_string.split('-') - -    # An empty value is allowed for optional features -    if not values[0] in f.values() and \ -           (values[0] or not f.optional()): -        raise InvalidValue ("'%s' is not a known value of feature '%s'\nlegal values: '%s'" % (values [0], feature, f.values())) - -    for v in values [1:]: -        # this will validate any subfeature values in value-string -        implied_subfeature(f, v, values[0]) - - -""" Extends the given subfeature with the subvalues.  If the optional -    value-string is provided, the subvalues are only valid for the given -    value of the feature. Thus, you could say that -    <target-platform>mingw is specifc to <toolset>gcc-2.95.2 as follows: -     -          extend-subfeature toolset gcc-2.95.2 : target-platform : mingw ; - -    feature:        The feature whose subfeature is being extended. -     -    value-string:   If supplied, specifies a specific value of the -                    main feature for which the new subfeature values -                    are valid. -     -    subfeature:     The name of the subfeature. -     -    subvalues:      The additional values of the subfeature being defined. -""" -def extend_subfeature (feature_name, value_string, subfeature_name, subvalues): - -    feature = validate_feature(feature_name) -     -    if value_string: -        validate_value_string(feature, value_string) - -    subfeature_name = feature_name + '-' + __get_subfeature_name (subfeature_name, value_string) -     -    extend(subfeature_name, subvalues) ; -    subfeature = __all_features[subfeature_name] - -    if value_string == None: value_string = '' -     -    if not __subfeature_from_value.has_key(feature): -        __subfeature_from_value [feature] = {} -         -    if not __subfeature_from_value[feature].has_key(value_string): -        __subfeature_from_value [feature][value_string] = {} -         -    for subvalue in subvalues: -        __subfeature_from_value [feature][value_string][subvalue] = subfeature - -@bjam_signature((["feature_name", "value_string", "?"], ["subfeature"], -                 ["subvalues", "*"], ["attributes", "*"])) -def subfeature (feature_name, value_string, subfeature, subvalues, attributes = []): -    """ Declares a subfeature. -        feature_name:   Root feature that is not a subfeature. -        value_string:   An optional value-string specifying which feature or -                        subfeature values this subfeature is specific to, -                        if any.                 -        subfeature:     The name of the subfeature being declared. -        subvalues:      The allowed values of this subfeature. -        attributes:     The attributes of the subfeature. -    """ -    parent_feature = validate_feature (feature_name) -     -    # Add grist to the subfeature name if a value-string was supplied -    subfeature_name = __get_subfeature_name (subfeature, value_string) -     -    if subfeature_name in __all_features[feature_name].subfeatures(): -        message = "'%s' already declared as a subfeature of '%s'" % (subfeature, feature_name) -        message += " specific to '%s'" % value_string -        raise BaseException (message) - -    # First declare the subfeature as a feature in its own right -    f = feature (feature_name + '-' + subfeature_name, subvalues, attributes + ['subfeature']) -    f.set_parent(parent_feature, value_string) -     -    parent_feature.add_subfeature(f) - -    # Now make sure the subfeature values are known. -    extend_subfeature (feature_name, value_string, subfeature, subvalues) - - -@bjam_signature((["composite_property_s"], ["component_properties_s", "*"])) -def compose (composite_property_s, component_properties_s): -    """ Sets the components of the given composite property. - -    All paremeters are <feature>value strings -    """ -    import property - -    component_properties_s = to_seq (component_properties_s) -    composite_property = property.create_from_string(composite_property_s) -    f = composite_property.feature() - -    if len(component_properties_s) > 0 and isinstance(component_properties_s[0], property.Property): -        component_properties = component_properties_s -    else: -        component_properties = [property.create_from_string(p) for p in component_properties_s] -                                        -    if not f.composite(): -        raise BaseException ("'%s' is not a composite feature" % f) - -    if __composite_properties.has_key(property): -        raise BaseException ('components of "%s" already set: %s' % (composite_property, str (__composite_properties[composite_property]))) - -    if composite_property in component_properties: -        raise BaseException ('composite property "%s" cannot have itself as a component' % composite_property) - -    __composite_properties[composite_property] = component_properties - - -def expand_composite(property): -    result = [ property ] -    if __composite_properties.has_key(property): -        for p in __composite_properties[property]: -            result.extend(expand_composite(p)) -    return result - - -def get_values (feature, properties): -    """ Returns all values of the given feature specified by the given property set. -    """ -    result = [] -    for p in properties: -        if get_grist (p) == feature: -            result.append (replace_grist (p, '')) -     -    return result - -def free_features (): -    """ Returns all free features. -    """ -    return __free_features - -def expand_composites (properties): -    """ Expand all composite properties in the set so that all components -        are explicitly expressed. -    """ -    explicit_features = set(p.feature() for p in properties) - -    result = [] - -    # now expand composite features -    for p in properties: -        expanded = expand_composite(p) - -        for x in expanded: -            if not x in result: -                f = x.feature() - -                if f.free(): -                    result.append (x) -                elif not x in properties:  # x is the result of expansion -                    if not f in explicit_features:  # not explicitly-specified -                        if any(r.feature() == f for r in result): -                            raise FeatureConflict( -                                "expansions of composite features result in " -                                "conflicting values for '%s'\nvalues: '%s'\none contributing composite property was '%s'" % -                                (f.name(), [r.value() for r in result if r.feature() == f] + [x.value()], p)) -                        else: -                            result.append (x) -                elif any(r.feature() == f for r in result): -                    raise FeatureConflict ("explicitly-specified values of non-free feature '%s' conflict\n" -                    "existing values: '%s'\nvalue from expanding '%s': '%s'" % (f,  -                    [r.value() for r in result if r.feature() == f], p, x.value())) -                else: -                    result.append (x) - -    return result - -# Uses Property -def is_subfeature_of (parent_property, f): -    """ Return true iff f is an ordinary subfeature of the parent_property's -        feature, or if f is a subfeature of the parent_property's feature -        specific to the parent_property's value. -    """ -    if not f.subfeature(): -        return False - -    p = f.parent() -    if not p: -        return False - -    parent_feature = p[0] -    parent_value = p[1] - -    if parent_feature != parent_property.feature(): -        return False - -    if parent_value and parent_value != parent_property.value(): -        return False - -    return True - -def __is_subproperty_of (parent_property, p): -    """ As is_subfeature_of, for subproperties. -    """ -    return is_subfeature_of (parent_property, p.feature()) - -     -# Returns true iff the subvalue is valid for the feature.  When the -# optional value-string is provided, returns true iff the subvalues -# are valid for the given value of the feature. -def is_subvalue(feature, value_string, subfeature, subvalue): - -    if not value_string: -        value_string = '' - -    if not __subfeature_from_value.has_key(feature): -        return False -         -    if not __subfeature_from_value[feature].has_key(value_string): -        return False -         -    if not __subfeature_from_value[feature][value_string].has_key(subvalue): -        return False - -    if __subfeature_from_value[feature][value_string][subvalue]\ -           != subfeature: -        return False - -    return True - -def implied_subfeature (feature, subvalue, value_string): -    result = __find_implied_subfeature (feature, subvalue, value_string) -    if not result: -        raise InvalidValue ("'%s' is not a known subfeature value of '%s%s'" % (subvalue, feature, value_string)) - -    return result - - -# Uses Property -def expand (properties): -    """ Given a property set which may consist of composite and implicit -        properties and combined subfeature values, returns an expanded, -        normalized property set with all implicit features expressed -        explicitly, all subfeature values individually expressed, and all -        components of composite properties expanded. Non-free features -        directly expressed in the input properties cause any values of -        those features due to composite feature expansion to be dropped. If -        two values of a given non-free feature are directly expressed in the -        input, an error is issued. -    """ -    expanded = expand_subfeatures(properties) -    return expand_composites (expanded) -     -# Accepts list of Property objects -def add_defaults (properties): -    """ Given a set of properties, add default values for features not -        represented in the set.  -        Note: if there's there's ordinary feature F1 and composite feature -        F2, which includes some value for F1, and both feature have default values, -        then the default value of F1 will be added, not the value in F2. This might -        not be right idea: consider -         -          feature variant : debug ... ; -               <variant>debug : .... <runtime-debugging>on -          feature <runtime-debugging> : off on ; -           -          Here, when adding default for an empty property set, we'll get -         -            <variant>debug <runtime_debugging>off -          -          and that's kind of strange.         -    """ -    result = [x for x in properties] -     -    handled_features = set() -    for p in properties: -        # We don't add default for conditional properties.  We don't want -        # <variant>debug:<define>DEBUG to be takes as specified value for <variant> -        if not p.condition(): -            handled_features.add(p.feature()) -         -    missing_top = [f for f in __all_top_features if not f in handled_features]     -    more = defaults(missing_top) -    result.extend(more) -    for p in more: -        handled_features.add(p.feature()) -        -    # Add defaults for subfeatures of features which are present -    for p in result[:]: -        s = p.feature().subfeatures() -        more = defaults([s for s in p.feature().subfeatures() if not s in handled_features]) -        for p in more: -            handled_features.add(p.feature()) -        result.extend(more) -     -    return result - -def minimize (properties): -    """ Given an expanded property set, eliminate all redundancy: properties -        which are elements of other (composite) properties in the set will -        be eliminated. Non-symmetric properties equal to default values will be -        eliminated, unless the override a value from some composite property. -        Implicit properties will be expressed without feature -        grist, and sub-property values will be expressed as elements joined -        to the corresponding main property. -    """     -     -    # remove properties implied by composite features -    components = [] -    for property in properties: -        if __composite_properties.has_key (property): -            components.extend(__composite_properties[property]) -    properties = b2.util.set.difference (properties, components) -     -    # handle subfeatures and implicit features - -    # move subfeatures to the end of the list -    properties = [p for p in properties if not p.feature().subfeature()] +\ -        [p for p in properties if p.feature().subfeature()] -     -    result = [] -    while properties: -        p = properties[0] -        f = p.feature() -         -        # locate all subproperties of $(x[1]) in the property set -        subproperties = __select_subproperties (p, properties) -         -        if subproperties: -            # reconstitute the joined property name -            subproperties.sort () -            joined = b2.build.property.Property(p.feature(), p.value() + '-' + '-'.join ([sp.value() for sp in subproperties])) -            result.append(joined) - -            properties = b2.util.set.difference(properties[1:], subproperties) - -        else: -            # eliminate properties whose value is equal to feature's -            # default and which are not symmetric and which do not -            # contradict values implied by composite properties. -             -            # since all component properties of composites in the set -            # have been eliminated, any remaining property whose -            # feature is the same as a component of a composite in the -            # set must have a non-redundant value. -            if p.value() != f.default() or f.symmetric(): -                result.append (p) -                  #\ -                   #or get_grist (fullp) in get_grist (components): -                   # FIXME: restore above -                   - -            properties = properties[1:] - -    return result - - -def split (properties): -    """ Given a property-set of the form -        v1/v2/...vN-1/<fN>vN/<fN+1>vN+1/...<fM>vM - -    Returns -        v1 v2 ... vN-1 <fN>vN <fN+1>vN+1 ... <fM>vM - -    Note that vN...vM may contain slashes. This is resilient to the -    substitution of backslashes for slashes, since Jam, unbidden, -    sometimes swaps slash direction on NT. -    """ - -    def split_one (properties): -        pieces = re.split (__re_slash_or_backslash, properties) -        result = [] -         -        for x in pieces: -            if not get_grist (x) and len (result) > 0 and get_grist (result [-1]): -                result = result [0:-1] + [ result [-1] + '/' + x ] -            else: -                result.append (x) -         -        return result - -    if isinstance (properties, str): -        return split_one (properties) - -    result = [] -    for p in properties: -        result += split_one (p) -    return result -     - -def compress_subproperties (properties): -    """ Combine all subproperties into their parent properties - -        Requires: for every subproperty, there is a parent property.  All -        features are explicitly expressed. -         -        This rule probably shouldn't be needed, but -        build-request.expand-no-defaults is being abused for unintended -        purposes and it needs help -    """ -    result = [] -    matched_subs = set() -    all_subs = set() -    for p in properties: -        f = p.feature() -         -        if not f.subfeature(): -            subs = __select_subproperties (p, properties) -            if subs: -             -                matched_subs.update(subs) - -                subvalues = '-'.join (sub.value() for sub in subs) -                result.append(b2.build.property.Property( -                    p.feature(), p.value() + '-' + subvalues, -                    p.condition())) -            else: -                result.append(p) - -        else: -            all_subs.add(p) - -    # TODO: this variables are used just for debugging. What's the overhead? -    assert all_subs == matched_subs - -    return result - -###################################################################################### -# Private methods - -def __select_subproperties (parent_property, properties): -    return [ x for x in properties if __is_subproperty_of (parent_property, x) ] - -def __get_subfeature_name (subfeature, value_string): -    if value_string == None:  -        prefix = '' -    else: -        prefix = value_string + ':' - -    return prefix + subfeature - - -def __validate_feature_attributes (name, attributes): -    for attribute in attributes: -        if not attribute in __all_attributes: -            raise InvalidAttribute ("unknown attributes: '%s' in feature declaration: '%s'" % (str (b2.util.set.difference (attributes, __all_attributes)), name)) -     -    if name in __all_features: -            raise AlreadyDefined ("feature '%s' already defined" % name) -    elif 'implicit' in attributes and 'free' in attributes: -        raise InvalidAttribute ("free features cannot also be implicit (in declaration of feature '%s')" % name) -    elif 'free' in attributes and 'propagated' in attributes: -        raise InvalidAttribute ("free features cannot also be propagated (in declaration of feature '%s')" % name) - -     -def __validate_feature (feature): -    """ Generates an error if the feature is unknown. -    """ -    if not __all_features.has_key (feature): -        raise BaseException ('unknown feature "%s"' % feature) - - -def __select_subfeatures (parent_property, features): -    """ Given a property, return the subset of features consisting of all -        ordinary subfeatures of the property's feature, and all specific -        subfeatures of the property's feature which are conditional on the -        property's value. -    """ -    return [f for f in features if is_subfeature_of (parent_property, f)] -   -# FIXME: copy over tests. diff --git a/jam-files/boost-build/build/generators.jam b/jam-files/boost-build/build/generators.jam deleted file mode 100644 index 1515525f..00000000 --- a/jam-files/boost-build/build/generators.jam +++ /dev/null @@ -1,1408 +0,0 @@ -# Copyright Vladimir Prus 2002. -# Copyright Rene Rivera 2006. -# -# Distributed under the Boost Software License, Version 1.0. -#    (See accompanying file LICENSE_1_0.txt or copy at -#          http://www.boost.org/LICENSE_1_0.txt) - -# Manages 'generators' --- objects which can do transformation between different -# target types and contain algorithm for finding transformation from sources to -# targets. -# -# The main entry point to this module is generators.construct rule. It is given -# a list of source targets, desired target type and a set of properties. It -# starts by selecting 'viable generators', which have any chances of producing -# the desired target type with the required properties. Generators are ranked -# and a set of the most specific ones is selected. -# -# The most specific generators have their 'run' methods called, with the -# properties and list of sources. Each one selects a target which can be -# directly consumed, and tries to convert the remaining ones to the types it can -# consume. This is done by recursively calling 'construct' with all consumable -# types. -# -# If the generator has collected all the targets it needs, it creates targets -# corresponding to result, and returns it. When all generators have been run, -# results of one of them are selected and returned as a result. -# -# It is quite possible for 'construct' to return more targets that it was asked -# for. For example, if it were asked to generate a target of type EXE, but the -# only found generator produces both EXE and TDS (file with debug) information. -# The extra target will be returned. -# -# Likewise, when generator tries to convert sources to consumable types, it can -# get more targets that it was asked for. The question is what to do with extra -# targets. Boost.Build attempts to convert them to requested types, and attempts -# that as early as possible. Specifically, this is done after invoking each -# generator. TODO: An example is needed to document the rationale for trying -# extra target conversion at that point. -# -# In order for the system to be able to use a specific generator instance 'when -# needed', the instance needs to be registered with the system using -# generators.register() or one of its related rules. Unregistered generators may -# only be run explicitly and will not be considered by Boost.Build when when -# converting between given target types. - -import "class" : new ; -import errors ; -import property-set ; -import sequence ; -import set ; -import type ; -import utility ; -import virtual-target ; - - -if "--debug-generators" in [ modules.peek : ARGV ] -{ -    .debug = true ; -} - - -# Updated cached viable source target type information as needed after a new -# target type gets defined. This is needed because if a target type is a viable -# source target type for some generator then all of the target type's derived -# target types should automatically be considered as viable source target types -# for the same generator as well. Does nothing if a non-derived target type is -# passed to it. -# -rule update-cached-information-with-a-new-type ( type ) -{ -    local base-type = [ type.base $(type) ] ; -    if $(base-type) -    { -        for local g in $(.vstg-cached-generators) -        { -            if $(base-type) in $(.vstg.$(g)) -            { -                .vstg.$(g) += $(type) ; -            } -        } - -        for local t in $(.vst-cached-types) -        { -            if $(base-type) in $(.vst.$(t)) -            { -                .vst.$(t) += $(type) ; -            } -        } -    } -} - - -# Clears cached viable source target type information except for target types -# and generators with all source types listed as viable. Should be called when -# something invalidates those cached values by possibly causing some new source -# types to become viable. -# -local rule invalidate-extendable-viable-source-target-type-cache ( ) -{ -    local generators-with-cached-source-types = $(.vstg-cached-generators) ; -    .vstg-cached-generators = ; -    for local g in $(generators-with-cached-source-types) -    { -        if $(.vstg.$(g)) = * -        { -            .vstg-cached-generators += $(g) ; -        } -        else -        { -            .vstg.$(g) = ; -        } -    } - -    local types-with-cached-source-types = $(.vst-cached-types) ; -    .vst-cached-types = ; -    for local t in $(types-with-cached-source-types) -    { -        if $(.vst.$(t)) = * -        { -            .vst-cached-types += $(t) ; -        } -        else -        { -            .vst.$(t) = ; -        } -    } -} - - -# Outputs a debug message if generators debugging is on. Each element of -# 'message' is checked to see if it is a class instance. If so, instead of the -# value, the result of 'str' call is output. -# -local rule generators.dout ( message * ) -{ -    if $(.debug) -    { -        ECHO [ sequence.transform utility.str : $(message) ] ; -    } -} - - -local rule indent ( ) -{ -    return $(.indent:J="") ; -} - - -local rule increase-indent ( ) -{ -    .indent += "    " ; -} - - -local rule decrease-indent ( ) -{ -    .indent = $(.indent[2-]) ; -} - - -# Models a generator. -# -class generator -{ -    import generators : indent increase-indent decrease-indent generators.dout ; -    import set ; -    import utility ; -    import feature ; -    import errors ; -    import sequence ; -    import type ; -    import virtual-target ; -    import "class" : new ; -    import property ; -    import path ; - -    EXPORT class@generator : indent increase-indent decrease-indent -        generators.dout ; - -    rule __init__ ( -        id                          # Identifies the generator - should be name -                                    # of the rule which sets up the build -                                    # actions. - -        composing ?                 # Whether generator processes each source -                                    # target in turn, converting it to required -                                    # types. Ordinary generators pass all -                                    # sources together to the recursive -                                    # generators.construct-types call. - -        : source-types *            # Types that this generator can handle. If -                                    # empty, the generator can consume anything. - -        : target-types-and-names +  # Types the generator will create and, -                                    # optionally, names for created targets. -                                    # Each element should have the form -                                    # type["(" name-pattern ")"], for example, -                                    # obj(%_x). Generated target name will be -                                    # found by replacing % with the name of -                                    # source, provided an explicit name was not -                                    # specified. - -        : requirements * -    ) -    { -        self.id = $(id) ; -        self.rule-name = $(id) ; -        self.composing = $(composing) ; -        self.source-types = $(source-types) ; -        self.target-types-and-names = $(target-types-and-names) ; -        self.requirements = $(requirements) ; - -        for local e in $(target-types-and-names) -        { -            # Create three parallel lists: one with the list of target types, -            # and two other with prefixes and postfixes to be added to target -            # name. We use parallel lists for prefix and postfix (as opposed to -            # mapping), because given target type might occur several times, for -            # example "H H(%_symbols)". -            local m = [ MATCH ([^\\(]*)(\\((.*)%(.*)\\))? : $(e) ] ; -            self.target-types += $(m[1]) ; -            self.name-prefix += $(m[3]:E="") ; -            self.name-postfix += $(m[4]:E="") ; -        } - -        # Note that 'transform' here, is the same as 'for_each'. -        sequence.transform type.validate : $(self.source-types) ; -        sequence.transform type.validate : $(self.target-types) ; -    } - -    ################# End of constructor ################# - -    rule id ( ) -    { -        return $(self.id) ; -    } - -    # Returns the list of target type the generator accepts. -    # -    rule source-types ( ) -    { -        return $(self.source-types) ; -    } - -    # Returns the list of target types that this generator produces. It is -    # assumed to be always the same -- i.e. it can not change depending on some -    # provided list of sources. -    # -    rule target-types ( ) -    { -        return $(self.target-types) ; -    } - -    # Returns the required properties for this generator. Properties in returned -    # set must be present in build properties if this generator is to be used. -    # If result has grist-only element, that build properties must include some -    # value of that feature. -    # -    # XXX: remove this method? -    # -    rule requirements ( ) -    { -        return $(self.requirements) ; -    } -     -    rule set-rule-name ( rule-name ) -    { -        self.rule-name = $(rule-name) ; -    } -     -    rule rule-name ( ) -    { -        return $(self.rule-name) ; -    } -         -    # Returns a true value if the generator can be run with the specified -    # properties. -    # -    rule match-rank ( property-set-to-match ) -    { -        # See if generator requirements are satisfied by 'properties'. Treat a -        # feature name in requirements (i.e. grist-only element), as matching -        # any value of the feature. -        local all-requirements = [ requirements ] ; - -        local property-requirements feature-requirements ; -        for local r in $(all-requirements) -        { -            if $(r:G=) -            { -                property-requirements += $(r) ; -            } -            else -            { -                feature-requirements += $(r) ; -            } -        } - -        local properties-to-match = [ $(property-set-to-match).raw ] ; -        if $(property-requirements) in $(properties-to-match) && -            $(feature-requirements) in $(properties-to-match:G) -        { -            return true ; -        } -        else -        { -            return ; -        } -    } - -    # Returns another generator which differs from $(self) in -    #   - id -    #   - value to <toolset> feature in properties -    # -    rule clone ( new-id : new-toolset-properties + ) -    { -        local g = [ new $(__class__) $(new-id) $(self.composing) : -            $(self.source-types) : $(self.target-types-and-names) : -            # Note: this does not remove any subfeatures of <toolset> which -            # might cause problems. -            [ property.change $(self.requirements) : <toolset> ] -            $(new-toolset-properties) ] ;        -        return $(g) ; -    } - -    # Creates another generator that is the same as $(self), except that if -    # 'base' is in target types of $(self), 'type' will in target types of the -    # new generator. -    # -    rule clone-and-change-target-type ( base : type ) -    { -        local target-types ; -        for local t in $(self.target-types-and-names) -        { -            local m = [ MATCH ([^\\(]*)(\\(.*\\))? : $(t) ] ; -            if $(m) = $(base) -            { -                target-types += $(type)$(m[2]:E="") ; -            } -            else -            { -                target-types += $(t) ; -            } -        } - -        local g = [ new $(__class__) $(self.id) $(self.composing) : -            $(self.source-types) : $(target-types) : $(self.requirements) ] ; -        if $(self.rule-name) -        {             -            $(g).set-rule-name $(self.rule-name) ; -        }         -        return $(g) ;         -    } - -    # Tries to invoke this generator on the given sources. Returns a list of -    # generated targets (instances of 'virtual-target') and optionally a set of -    # properties to be added to the usage-requirements for all the generated -    # targets. Returning nothing from run indicates that the generator was -    # unable to create the target. -    # -    rule run -    ( -        project         # Project for which the targets are generated. -        name ?          # Used when determining the 'name' attribute for all -                        # generated targets. See the 'generated-targets' method. -        : property-set  # Desired properties for generated targets. -        : sources +     # Source targets. -    ) -    { -        generators.dout [ indent ] "  ** generator" $(self.id) ; -        generators.dout [ indent ] "  composing:" $(self.composing) ; - -        if ! $(self.composing) && $(sources[2]) && $(self.source-types[2]) -        { -            errors.error "Unsupported source/source-type combination" ; -        } - -        # We do not run composing generators if no name is specified. The reason -        # is that composing generator combines several targets, which can have -        # different names, and it cannot decide which name to give for produced -        # target. Therefore, the name must be passed. -        # -        # This in effect, means that composing generators are runnable only at -        # the top-level of a transformation graph, or if their name is passed -        # explicitly. Thus, we dissallow composing generators in the middle. For -        # example, the transformation CPP -> OBJ -> STATIC_LIB -> RSP -> EXE -        # will not be allowed as the OBJ -> STATIC_LIB generator is composing. -        if ! $(self.composing) || $(name) -        { -            run-really $(project) $(name) : $(property-set) : $(sources) ; -        } -    } - -    rule run-really ( project name ? : property-set : sources + ) -    { -        # Targets that this generator will consume directly. -        local consumed = ; -        # Targets that can not be consumed and will be returned as-is. -        local bypassed = ; - -        if $(self.composing) -        { -            convert-multiple-sources-to-consumable-types $(project) -                : $(property-set) : $(sources) : consumed bypassed ; -        } -        else -        { -            convert-to-consumable-types $(project) $(name) : $(property-set) -                : $(sources) : : consumed bypassed ; -        } - -        local result ; -        if $(consumed) -        { -            result = [ construct-result $(consumed) : $(project) $(name) : -                $(property-set) ] ; -        } - -        if $(result) -        { -            generators.dout [ indent ] "  SUCCESS: " $(result) ; -        } -        else -        { -            generators.dout [ indent ] "  FAILURE" ; -        } -        generators.dout ; -        return $(result) ; -    } - -    # Constructs the dependency graph to be returned by this generator. -    # -    rule construct-result -    ( -        consumed +        # Already prepared list of consumable targets. -                          # Composing generators may receive multiple sources -                          # all of which will have types matching those in -                          # $(self.source-types). Non-composing generators with -                          # multiple $(self.source-types) will receive exactly -                          # len $(self.source-types) sources with types matching -                          # those in $(self.source-types). And non-composing -                          # generators with only a single source type may -                          # receive multiple sources with all of them of the -                          # type listed in $(self.source-types). -        : project name ? -        : property-set    # Properties to be used for all actions created here. -    ) -    { -        local result ; -        # If this is 1->1 transformation, apply it to all consumed targets in -        # order. -        if ! $(self.source-types[2]) && ! $(self.composing) -        { -            for local r in $(consumed) -            { -                result += [ generated-targets $(r) : $(property-set) : -                    $(project) $(name) ] ; -            } -        } -        else if $(consumed) -        { -            result += [ generated-targets $(consumed) : $(property-set) : -                $(project) $(name) ] ; -        } -        return $(result) ; -    } - -    # Determine target name from fullname (maybe including path components) -    # Place optional prefix and postfix around basename -    # -    rule determine-target-name ( fullname  : prefix ? : postfix ? ) -    { -        # See if we need to add directory to the target name. -        local dir  = $(fullname:D) ;             -        local name = $(fullname:B) ;  -         -        name = $(prefix:E=)$(name) ; -        name = $(name)$(postfix:E=) ; - -        if $(dir) &&  -          # Never append '..' to target path. -          ! [ MATCH .*(\\.\\.).* : $(dir) ]  -            &&  -          ! [ path.is-rooted $(dir) ] -        { -            # Relative path is always relative to the source -            # directory. Retain it, so that users can have files -            # with the same in two different subdirectories. -            name = $(dir)/$(name) ;                 -        }             -        return $(name) ; -    } - -    # Determine the name of the produced target from the names of the sources. -    # -    rule determine-output-name ( sources + ) -    { -        # The simple case if when a name of source has single dot. Then, we take -        # the part before dot. Several dots can be caused by: -        #   - using source file like a.host.cpp, or -        #   - a type whose suffix has a dot. Say, we can type 'host_cpp' with -        #     extension 'host.cpp'. -        # In the first case, we want to take the part up to the last dot. In the -        # second case -- not sure, but for now take the part up to the last dot -        # too. -        name = [ utility.basename [ $(sources[1]).name ] ] ; - -        for local s in $(sources[2]) -        { -            local n2 = [ utility.basename [ $(s).name ] ] ; -            if $(n2) != $(name) -            { -                errors.error "$(self.id): source targets have different names: cannot determine target name" ; -            } -        } -        name = [ determine-target-name [ $(sources[1]).name ] ] ; -        return $(name) ; -    } - -    # Constructs targets that are created after consuming 'sources'. The result -    # will be the list of virtual-target, which has the same length as the -    # 'target-types' attribute and with corresponding types. -    # -    # When 'name' is empty, all source targets must have the same 'name' -    # attribute value, which will be used instead of the 'name' argument. -    # -    # The 'name' attribute value for each generated target will be equal to -    # the 'name' parameter if there is no name pattern for this type. Otherwise, -    # the '%' symbol in the name pattern will be replaced with the 'name' -    # parameter to obtain the 'name' attribute. -    # -    # For example, if targets types are T1 and T2 (with name pattern "%_x"), -    # suffixes for T1 and T2 are .t1 and .t2, and source is foo.z, then created -    # files would be "foo.t1" and "foo_x.t2". The 'name' attribute actually -    # determines the basename of a file. -    # -    # Note that this pattern mechanism has nothing to do with implicit patterns -    # in make. It is a way to produce a target whose name is different than the -    # name of its source. -    # -    rule generated-targets ( sources + : property-set : project name ? ) -    { -        if ! $(name) -        { -            name = [ determine-output-name $(sources) ] ; -        } - -        # Assign an action for each target. -        local action = [ action-class ] ; -        local a = [ class.new $(action) $(sources) : $(self.rule-name) : -                    $(property-set) ] ; - -        # Create generated target for each target type. -        local targets ; -        local pre = $(self.name-prefix) ; -        local post = $(self.name-postfix) ; -        for local t in $(self.target-types) -        { -            local generated-name = $(pre[1])$(name:BS)$(post[1]) ; -            generated-name = $(generated-name:R=$(name:D)) ; -            pre = $(pre[2-]) ; -            post = $(post[2-]) ; - -            targets += [ class.new file-target $(generated-name) : $(t) : -                $(project) : $(a) ] ; -        } - -        return [ sequence.transform virtual-target.register : $(targets) ] ; -    } - -    # Attempts to convert 'sources' to targets of types that this generator can -    # handle. The intention is to produce the set of targets that can be used -    # when the generator is run. -    # -    rule convert-to-consumable-types -    ( -        project name ? -        : property-set -        : sources + -        : only-one ?    # Convert 'source' to only one of the source types. If -                        # there is more that one possibility, report an error. -        : consumed-var  # Name of the variable which receives all targets which -                        # can be consumed. -          bypassed-var  # Name of the variable which receives all targets which -                        # can not be consumed. -    ) -    { -        # We are likely to be passed 'consumed' and 'bypassed' var names. Use -        # '_' to avoid name conflicts. -        local _consumed ; -        local _bypassed ; -        local missing-types ; - -        if $(sources[2]) -        { -            # Do not know how to handle several sources yet. Just try to pass -            # the request to other generator. -            missing-types = $(self.source-types) ; -        } -        else -        { -            consume-directly $(sources) : _consumed : missing-types ; -        } - -        # No need to search for transformation if some source type has consumed -        # source and no more source types are needed. -        if $(only-one) && $(_consumed) -        { -            missing-types = ; -        } - -        # TODO: we should check that only one source type if create of -        # 'only-one' is true. -        # TODO: consider if consumed/bypassed separation should be done by -        # 'construct-types'. - -        if $(missing-types) -        { -            local transformed = [ generators.construct-types $(project) $(name) -                : $(missing-types) : $(property-set) : $(sources) ] ; - -            # Add targets of right type to 'consumed'. Add others to 'bypassed'. -            # The 'generators.construct' rule has done its best to convert -            # everything to the required type. There is no need to rerun it on -            # targets of different types. - -            # NOTE: ignoring usage requirements. -            for local t in $(transformed[2-]) -            { -                if [ $(t).type ] in $(missing-types) -                { -                    _consumed += $(t) ; -                } -                else -                { -                    _bypassed += $(t) ; -                } -            } -        } - -        _consumed = [ sequence.unique $(_consumed) ] ; -        _bypassed = [ sequence.unique $(_bypassed) ] ; - -        # Remove elements of '_bypassed' that are in '_consumed'. - -        # Suppose the target type of current generator, X is produced from X_1 -        # and X_2, which are produced from Y by one generator. When creating X_1 -        # from Y, X_2 will be added to 'bypassed'. Likewise, when creating X_2 -        # from Y, X_1 will be added to 'bypassed', but they are also in -        # 'consumed'. We have to remove them from bypassed, so that generators -        # up the call stack do not try to convert them. - -        # In this particular case, X_1 instance in 'consumed' and X_1 instance -        # in 'bypassed' will be the same: because they have the same source and -        # action name, and 'virtual-target.register' will not allow two -        # different instances. Therefore, it is OK to use 'set.difference'. - -        _bypassed = [ set.difference $(_bypassed) : $(_consumed) ] ; - -        $(consumed-var) += $(_consumed) ; -        $(bypassed-var) += $(_bypassed) ; -    } - -    # Converts several files to consumable types. Called for composing -    # generators only. -    # -    rule convert-multiple-sources-to-consumable-types ( project : property-set : -        sources * : consumed-var bypassed-var ) -    { -        # We process each source one-by-one, trying to convert it to a usable -        # type. -        for local source in $(sources) -        { -            local _c ; -            local _b ; -            # TODO: need to check for failure on each source. -            convert-to-consumable-types $(project) : $(property-set) : $(source) -                : true : _c _b ; -            if ! $(_c) -            { -                generators.dout [ indent ] " failed to convert " $(source) ; -            } -            $(consumed-var) += $(_c) ; -            $(bypassed-var) += $(_b) ; -        } -    } - -    rule consume-directly ( source : consumed-var : missing-types-var ) -    { -        local real-source-type = [ $(source).type ] ; - -        # If there are no source types, we can consume anything. -        local source-types = $(self.source-types) ; -        source-types ?= $(real-source-type) ; - -        for local st in $(source-types) -        { -            # The 'source' if of the right type already. -            if $(real-source-type) = $(st) || [ type.is-derived -                $(real-source-type) $(st) ] -            { -                $(consumed-var) += $(source) ; -            } -            else -            { -                $(missing-types-var) += $(st) ; -            } -        } -    } - -    # Returns the class to be used to actions. Default implementation returns -    # "action". -    # -    rule action-class ( ) -    { -        return "action" ; -    } -} - - -# Registers a new generator instance 'g'. -# -rule register ( g ) -{ -    .all-generators += $(g) ; -         -    # A generator can produce several targets of the same type. We want unique -    # occurrence of that generator in .generators.$(t) in that case, otherwise, -    # it will be tried twice and we will get a false ambiguity. -    for local t in [ sequence.unique [ $(g).target-types ] ] -    { -        .generators.$(t) += $(g) ; -    } - -    # Update the set of generators for toolset. - -    # TODO: should we check that generator with this id is not already -    # registered. For example, the fop.jam module intentionally declared two -    # generators with the same id, so such check will break it. -    local id = [ $(g).id ] ; - -    # Some generators have multiple periods in their name, so a simple $(id:S=) -    # will not generate the right toolset name. E.g. if id = gcc.compile.c++, -    # then .generators-for-toolset.$(id:S=) will append to -    # .generators-for-toolset.gcc.compile, which is a separate value from -    # .generators-for-toolset.gcc. Correcting this makes generator inheritance -    # work properly. See also inherit-generators in the toolset module. -    local base = $(id) ; -    while $(base:S) -    { -        base = $(base:B) ; -    } -    .generators-for-toolset.$(base) += $(g) ; - - -    # After adding a new generator that can construct new target types, we need -    # to clear the related cached viable source target type information for -    # constructing a specific target type or using a specific generator. Cached -    # viable source target type lists affected by this are those containing any -    # of the target types constructed by the new generator or any of their base -    # target types. -    # -    # A more advanced alternative to clearing that cached viable source target -    # type information would be to expand it with additional source types or -    # even better - mark it as needing to be expanded on next use. -    # -    # Also see the http://thread.gmane.org/gmane.comp.lib.boost.build/19077 -    # mailing list thread for an even more advanced idea of how we could convert -    # Boost Build's Jamfile processing, target selection and generator selection -    # into separate steps which would prevent these caches from ever being -    # invalidated. -    # -    # For now we just clear all the cached viable source target type information -    # that does not simply state 'all types' and may implement a more detailed -    # algorithm later on if it becomes needed. - -    invalidate-extendable-viable-source-target-type-cache ; -} - - -# Creates a new non-composing 'generator' class instance and registers it. -# Returns the created instance. Rationale: the instance is returned so that it -# is possible to first register a generator and then call its 'run' method, -# bypassing the whole generator selection process. -# -rule register-standard ( id : source-types * : target-types + : requirements * ) -{ -    local g = [ new generator $(id) : $(source-types) : $(target-types) : -        $(requirements) ] ; -    register $(g) ; -    return $(g) ; -} - - -# Creates a new composing 'generator' class instance and registers it. -# -rule register-composing ( id : source-types * : target-types + : requirements * -    ) -{ -    local g = [ new generator $(id) true : $(source-types) : $(target-types) : -        $(requirements) ] ; -    register $(g) ; -    return $(g) ; -} - - -# Returns all generators belonging to the given 'toolset', i.e. whose ids are -# '$(toolset).<something>'. -# -rule generators-for-toolset ( toolset ) -{ -    return $(.generators-for-toolset.$(toolset)) ; -} - - -# Make generator 'overrider-id' be preferred to 'overridee-id'. If, when -# searching for generators that could produce a target of a certain type, both -# those generators are among viable generators, the overridden generator is -# immediately discarded. -# -# The overridden generators are discarded immediately after computing the list -# of viable generators but before running any of them. -# -rule override ( overrider-id : overridee-id ) -{ -    .override.$(overrider-id) += $(overridee-id) ; -} - - -# Returns a list of source type which can possibly be converted to 'target-type' -# by some chain of generator invocation. -# -# More formally, takes all generators for 'target-type' and returns a union of -# source types for those generators and result of calling itself recursively on -# source types. -# -# Returns '*' in case any type should be considered a viable source type for the -# given type. -# -local rule viable-source-types-real ( target-type ) -{ -    local result ; - -    # 't0' is the initial list of target types we need to process to get a list -    # of their viable source target types. New target types will not be added to -    # this list. -    local t0 = [ type.all-bases $(target-type) ] ; - -    # 't' is the list of target types which have not yet been processed to get a -    # list of their viable source target types. This list will get expanded as -    # we locate more target types to process. -    local t = $(t0) ; - -    while $(t) -    { -        # Find all generators for the current type. Unlike -        # 'find-viable-generators' we do not care about the property-set. -        local generators = $(.generators.$(t[1])) ; -        t = $(t[2-]) ; - -        while $(generators) -        { -            local g = $(generators[1]) ; -            generators = $(generators[2-]) ; - -            if ! [ $(g).source-types ] -            { -                # Empty source types -- everything can be accepted. -                result = * ; -                # This will terminate this loop. -                generators = ; -                # This will terminate the outer loop. -                t = ; -            } - -            for local source-type in [ $(g).source-types ] -            { -                if ! $(source-type) in $(result) -                { -                    # If a generator accepts a 'source-type' it will also -                    # happily accept any type derived from it. -                    for local n in [ type.all-derived $(source-type) ] -                    { -                        if ! $(n) in $(result) -                        { -                            # Here there is no point in adding target types to -                            # the list of types to process in case they are or -                            # have already been on that list. We optimize this -                            # check by realizing that we only need to avoid the -                            # original target type's base types. Other target -                            # types that are or have been on the list of target -                            # types to process have been added to the 'result' -                            # list as well and have thus already been eliminated -                            # by the previous if. -                            if ! $(n) in $(t0) -                            { -                                t += $(n) ; -                            } -                            result += $(n) ; -                        } -                    } -                } -            } -        } -    } - -    return $(result) ; -} - - -# Helper rule, caches the result of 'viable-source-types-real'. -# -rule viable-source-types ( target-type ) -{ -    local key = .vst.$(target-type) ; -    if ! $($(key)) -    { -        .vst-cached-types += $(target-type) ; -        local v = [ viable-source-types-real $(target-type) ] ; -        if ! $(v) -        { -            v = none ; -        } -        $(key) = $(v) ; -    } - -    if $($(key)) != none -    { -        return $($(key)) ; -    } -} - - -# Returns the list of source types, which, when passed to 'run' method of -# 'generator', has some change of being eventually used (probably after -# conversion by other generators). -# -# Returns '*' in case any type should be considered a viable source type for the -# given generator. -# -rule viable-source-types-for-generator-real ( generator ) -{ -    local source-types = [ $(generator).source-types ] ; -    if ! $(source-types) -    { -        # If generator does not specify any source types, it might be a special -        # generator like builtin.lib-generator which just relays to other -        # generators. Return '*' to indicate that any source type is possibly -        # OK, since we do not know for sure. -        return * ; -    } -    else -    { -        local result ; -        while $(source-types) -        { -            local s = $(source-types[1]) ; -            source-types = $(source-types[2-]) ; -            local viable-sources = [ generators.viable-source-types $(s) ] ; -            if $(viable-sources) = * -            { -                result = * ; -                source-types = ;  # Terminate the loop. -            } -            else -            { -                result += [ type.all-derived $(s) ] $(viable-sources) ; -            } -        } -        return [ sequence.unique $(result) ] ; -    } -} - - -# Helper rule, caches the result of 'viable-source-types-for-generator'. -# -local rule viable-source-types-for-generator ( generator ) -{ -    local key = .vstg.$(generator) ; -    if ! $($(key)) -    { -        .vstg-cached-generators += $(generator) ; -        local v = [ viable-source-types-for-generator-real $(generator) ] ; -        if ! $(v) -        { -            v = none ; -        } -        $(key) = $(v) ; -    } - -    if $($(key)) != none -    { -        return $($(key)) ; -    } -} - - -# Returns usage requirements + list of created targets. -# -local rule try-one-generator-really ( project name ? : generator : target-type -    : property-set : sources * ) -{ -    local targets = -        [ $(generator).run $(project) $(name) : $(property-set) : $(sources) ] ; - -    local usage-requirements ; -    local success ; - -    generators.dout [ indent ] returned $(targets) ; - -    if $(targets) -    { -        success = true ; - -        if  [ class.is-a $(targets[1]) : property-set ] -        { -            usage-requirements = $(targets[1]) ; -            targets = $(targets[2-]) ; -        } -        else -        { -            usage-requirements = [ property-set.empty ] ; -        } -    } - -    generators.dout [ indent ] "  generator" [ $(generator).id ] " spawned " ; -    generators.dout [ indent ] " " $(targets) ; -    if $(usage-requirements) -    { -        generators.dout [ indent ] "  with usage requirements:" $(x) ; -    } - -    if $(success) -    { -        return $(usage-requirements) $(targets) ; -    } -} - - -# Checks if generator invocation can be pruned, because it is guaranteed to -# fail. If so, quickly returns an empty list. Otherwise, calls -# try-one-generator-really. -# -local rule try-one-generator ( project name ? : generator : target-type -    : property-set : sources * ) -{ -    local source-types ; -    for local s in $(sources) -    { -        source-types += [ $(s).type ] ; -    } -    local viable-source-types = [ viable-source-types-for-generator $(generator) -        ] ; - -    if  $(source-types) && $(viable-source-types) != * && -        ! [ set.intersection $(source-types) : $(viable-source-types) ] -    { -        local id = [ $(generator).id ] ; -        generators.dout [ indent ] "  ** generator '$(id)' pruned" ; -        #generators.dout [ indent ] "source-types" '$(source-types)' ; -        #generators.dout [ indent ] "viable-source-types" '$(viable-source-types)' ; -    } -    else -    { -        return [ try-one-generator-really $(project) $(name) : $(generator) : -            $(target-type) : $(property-set) : $(sources) ] ; -    } -} - - -rule construct-types ( project name ? : target-types + : property-set -    : sources + ) -{ -    local result ; -    local matched-types ; -    local usage-requirements = [ property-set.empty ] ; -    for local t in $(target-types) -    { -        local r = [ construct $(project) $(name) : $(t) : $(property-set) : -            $(sources) ] ; -        if $(r) -        { -            usage-requirements = [ $(usage-requirements).add $(r[1]) ] ; -            result += $(r[2-]) ; -            matched-types += $(t) ; -        } -    } -    # TODO: have to introduce parameter controlling if several types can be -    # matched and add appropriate checks. - -    # TODO: need to review the documentation for 'construct' to see if it should -    # return $(source) even if nothing can be done with it. Currents docs seem -    # to imply that, contrary to the behaviour. -    if $(result) -    { -        return $(usage-requirements) $(result) ; -    } -    else -    { -        return $(usage-requirements) $(sources) ; -    } -} - - -# Ensures all 'targets' have their type. If this is not so, exists with error. -# -local rule ensure-type ( targets * ) -{ -    for local t in $(targets) -    { -        if ! [ $(t).type ] -        { -            errors.error "target" [ $(t).str ] "has no type" ; -        } -    } -} - - -# Returns generators which can be used to construct target of specified type -# with specified properties. Uses the following algorithm: -# - iterates over requested target-type and all its bases (in the order returned -#   by type.all-bases). -# - for each type find all generators that generate that type and whose -#   requirements are satisfied by properties. -# - if the set of generators is not empty, returns that set. -# -# Note: this algorithm explicitly ignores generators for base classes if there -# is at least one generator for the requested target-type. -# -local rule find-viable-generators-aux ( target-type : property-set ) -{ -    # Select generators that can create the required target type. -    local viable-generators = ; -    local generator-rank = ; - -    import type ; -    local t = [ type.all-bases $(target-type) ] ; - -    generators.dout [ indent ] find-viable-generators target-type= $(target-type) -        property-set= [ $(property-set).as-path ] ; - -    # Get the list of generators for the requested type. If no generator is -    # registered, try base type, and so on. -    local generators ; -    while $(t[1]) -    { -        generators.dout [ indent ] "trying type" $(t[1]) ; -        if $(.generators.$(t[1])) -        { -            generators.dout [ indent ] "there are generators for this type" ; -            generators = $(.generators.$(t[1])) ; - -            if $(t[1]) != $(target-type) -            { -                # We are here because there were no generators found for -                # target-type but there are some generators for its base type. -                # We will try to use them, but they will produce targets of -                # base type, not of 'target-type'. So, we clone the generators -                # and modify the list of target types. -                local generators2 ; -                for local g in $(generators) -                { -                    # generators.register adds a generator to the list of -                    # generators for toolsets, which is a bit strange, but -                    # should work. That list is only used when inheriting a -                    # toolset, which should have been done before running -                    # generators. -                    generators2 += [ $(g).clone-and-change-target-type $(t[1]) : -                        $(target-type) ] ; -                    generators.register $(generators2[-1]) ; -                } -                generators = $(generators2) ; -            } -            t = ; -        } -        t = $(t[2-]) ; -    } - -    for local g in $(generators) -    { -        generators.dout [ indent ] "trying generator" [ $(g).id ] "(" [ $(g).source-types ] -> [ $(g).target-types ] ")" ; - -        local m = [ $(g).match-rank $(property-set) ] ; -        if $(m) -        { -            generators.dout [ indent ] "  is viable" ; -            viable-generators += $(g) ; -        } -    } - -    return $(viable-generators) ; -} - - -rule find-viable-generators ( target-type : property-set ) -{ -    local key = $(target-type).$(property-set) ; -    local l = $(.fv.$(key)) ; -    if ! $(l) -    { -        l = [ find-viable-generators-aux $(target-type) : $(property-set) ] ; -        if ! $(l) -        { -            l = none ; -        } -        .fv.$(key) = $(l) ; -    } - -    if $(l) = none -    { -        l = ; -    } - -    local viable-generators ; -    for local g in $(l) -    { -        # Avoid trying the same generator twice on different levels. -        if ! $(g) in $(.active-generators) -        { -            viable-generators += $(g) ; -        } -        else -        { -            generators.dout [ indent ] "   generator " [ $(g).id ] "is active, discaring" ; -        }         -    } - -    # Generators which override 'all'. -    local all-overrides ; -    # Generators which are overriden. -    local overriden-ids ; -    for local g in $(viable-generators) -    { -        local id = [ $(g).id ] ; -        local this-overrides = $(.override.$(id)) ; -        overriden-ids += $(this-overrides) ; -        if all in $(this-overrides) -        { -            all-overrides += $(g) ; -        } -    } -    if $(all-overrides) -    { -        viable-generators = $(all-overrides) ; -    } -    local result ; -    for local g in $(viable-generators) -    { -        if ! [ $(g).id ] in $(overriden-ids) -        { -            result += $(g) ; -        } -    } - -    return $(result) ; -} - - -.construct-stack = ; - - -# Attempts to construct a target by finding viable generators, running them and -# selecting the dependency graph. -# -local rule construct-really ( project name ? : target-type : property-set : -    sources * ) -{ -    viable-generators = [ find-viable-generators $(target-type) : -        $(property-set) ] ; - -    generators.dout [ indent ] "*** " [ sequence.length $(viable-generators) ] -        " viable generators" ; - -    local result ; -    local generators-that-succeeded ; -    for local g in $(viable-generators) -    { -        # This variable will be restored on exit from this scope. -        local .active-generators = $(g) $(.active-generators) ; - -        local r = [ try-one-generator $(project) $(name) : $(g) : $(target-type) -            : $(property-set) : $(sources) ] ; - -        if $(r) -        { -            generators-that-succeeded += $(g) ; -            if $(result) -            { -                ECHO "Error: ambiguity found when searching for best transformation" ; -                ECHO "Trying to produce type '$(target-type)' from: " ; -                for local s in $(sources) -                { -                    ECHO " - " [ $(s).str ] ; -                } -                ECHO "Generators that succeeded:" ; -                for local g in $(generators-that-succeeded) -                { -                    ECHO " - " [ $(g).id ] ; -                } -                ECHO "First generator produced: " ; -                for local t in $(result[2-]) -                { -                    ECHO " - " [ $(t).str ] ; -                } -                ECHO "Second generator produced: " ; -                for local t in $(r[2-]) -                { -                    ECHO " - " [ $(t).str ] ; -                } -                EXIT ; -            } -            else -            { -                result = $(r) ; -            } -        } -    } - -    return $(result) ; -} - - -# Attempts to create a target of 'target-type' with 'properties' from 'sources'. -# The 'sources' are treated as a collection of *possible* ingridients, i.e. -# there is no obligation to consume them all. -# -# Returns a list of targets. When this invocation is first instance of -# 'construct' in stack, returns only targets of requested 'target-type', -# otherwise, returns also unused sources and additionally generated targets. -# -# If 'top-level' is set, does not suppress generators that are already -# used in the stack. This may be useful in cases where a generator -# has to build a metatargets -- for example a target corresponding to -# built tool. -# -rule construct ( project name ? : target-type : property-set * : sources * : top-level ? ) -{ -    local saved-stack ; -    if $(top-level) -    { -        saved-active = $(.active-generators) ; -        .active-generators = ; -    } -         -    if (.construct-stack) -    { -        ensure-type $(sources) ; -    } - -    .construct-stack += 1 ; - -    increase-indent ; - -    if $(.debug) -    { -        generators.dout [ indent ] "*** construct" $(target-type) ; - -        for local s in $(sources) -        { -            generators.dout [ indent ] "    from" $(s) ; -        } -        generators.dout [ indent ] "    properties:" [ $(property-set).raw ] ; -    } - -    local result = [ construct-really $(project) $(name) : $(target-type) : -        $(property-set) : $(sources) ] ; - -    decrease-indent ; - -    .construct-stack = $(.construct-stack[2-]) ; -     -    if $(top-level) -    { -        .active-generators = $(saved-active) ; -    } - -    return $(result) ; -} - -# Given 'result', obtained from some generator or generators.construct, adds -# 'raw-properties' as usage requirements to it. If result already contains usage -# requirements -- that is the first element of result of an instance of the -# property-set class, the existing usage requirements and 'raw-properties' are -# combined. -# -rule add-usage-requirements ( result * : raw-properties * ) -{ -    if $(result) -    { -        if [ class.is-a $(result[1]) : property-set ] -        { -            return [ $(result[1]).add-raw $(raw-properties) ] $(result[2-]) ; -        } -        else -        { -            return [ property-set.create $(raw-properties) ] $(result) ; -        } -    } -} - -rule dump ( ) -{ -    for local g in $(.all-generators) -    { -        ECHO [ $(g).id ] ":" [ $(g).source-types ] -> [ $(g).target-types ] ;             -    }     -} - diff --git a/jam-files/boost-build/build/generators.py b/jam-files/boost-build/build/generators.py deleted file mode 100644 index 2c59f7ca..00000000 --- a/jam-files/boost-build/build/generators.py +++ /dev/null @@ -1,1089 +0,0 @@ -# Status: being ported by Vladimir Prus -# Base revision: 48649 -# TODO: replace the logging with dout - -# Copyright Vladimir Prus 2002. -# Copyright Rene Rivera 2006. -# -# Distributed under the Boost Software License, Version 1.0. -#    (See accompanying file LICENSE_1_0.txt or copy at -#          http://www.boost.org/LICENSE_1_0.txt) - -#  Manages 'generators' --- objects which can do transformation between different -#  target types and contain algorithm for finding transformation from sources -#  to targets. -# -#  The main entry point to this module is generators.construct rule. It is given -#  a list of source targets, desired target type and a set of properties. -#  It starts by selecting 'viable generators', which have any chances of producing -#  the desired target type with the required properties. Generators are ranked and -#  a set of most specific ones is selected. -#  -#  The most specific generators have their 'run' methods called, with the properties -#  and list of sources. Each one selects target which can be directly consumed, and -#  tries to convert the remaining ones to the types it can consume. This is done -#  by recursively calling 'construct' with all consumable types. -# -#  If the generator has collected all the targets it needs, it creates targets  -#  corresponding to result, and returns it. When all generators have been run, -#  results of one of them are selected and returned as result. -# -#  It's quite possible that 'construct' returns more targets that it was asked for. -#  For example, it was asked to target type EXE, but the only found generators produces -#  both EXE and TDS (file with debug) information. The extra target will be returned. -# -#  Likewise, when generator tries to convert sources to consumable types, it can get -#  more targets that it was asked for. The question is what to do with extra targets. -#  Boost.Build attempts to convert them to requested types, and attempts as early as -#  possible. Specifically, this is done after invoking each generator. (Later I'll  -#  document the rationale for trying extra target conversion at that point). -# -#  That early conversion is not always desirable. Suppose a generator got a source of -#  type Y and must consume one target of type X_1 and one target of type X_2. -#  When converting Y to X_1 extra target of type Y_2 is created. We should not try to -#  convert it to type X_1, because if we do so, the generator will get two targets -#  of type X_1, and will be at loss as to which one to use. Because of that, the -#  'construct' rule has a parameter, telling if multiple targets can be returned. If -#  the parameter is false, conversion of extra targets is not performed. - - -import re -import cStringIO -import os.path - -from virtual_target import Subvariant -import virtual_target, type, property_set, property -from b2.util.logger import * -from b2.util.utility import * -from b2.util import set -from b2.util.sequence import unique -import b2.util.sequence as sequence -from b2.manager import get_manager -import b2.build.type - -def reset (): -    """ Clear the module state. This is mainly for testing purposes. -    """ -    global __generators, __type_to_generators, __generators_for_toolset, __construct_stack -    global __overrides, __active_generators -    global __viable_generators_cache, __viable_source_types_cache -    global __vstg_cached_generators, __vst_cached_types - -    __generators = {} -    __type_to_generators = {} -    __generators_for_toolset = {} -    __overrides = {} -     -    # TODO: can these be global?  -    __construct_stack = [] -    __viable_generators_cache = {} -    __viable_source_types_cache = {} -    __active_generators = [] - -    __vstg_cached_generators = [] -    __vst_cached_types = [] - -reset () - -_re_separate_types_prefix_and_postfix = re.compile ('([^\\(]*)(\\((.*)%(.*)\\))?') -_re_match_type = re.compile('([^\\(]*)(\\(.*\\))?') - - -__debug = None -__indent = "" - -def debug(): -    global __debug -    if __debug is None: -        __debug = "--debug-generators" in bjam.variable("ARGV")         -    return __debug - -def increase_indent(): -    global __indent -    __indent += "    " - -def decrease_indent(): -    global __indent -    __indent = __indent[0:-4] - - -# Updated cached viable source target type information as needed after a new -# derived target type gets added. This is needed because if a target type is a -# viable source target type for some generator then all of the target type's -# derived target types are automatically viable as source target types for the -# same generator. Does nothing if a non-derived target type is passed to it. -# -def update_cached_information_with_a_new_type(type): - -    base_type = b2.build.type.base(type) - -    if base_type: -        for g in __vstg_cached_generators: -            if base_type in __viable_source_types_cache.get(g, []): -                __viable_source_types_cache[g].append(type) - -        for t in __vst_cached_types: -            if base_type in __viable_source_types_cache.get(t, []): -                __viable_source_types_cache[t].append(type) - -# Clears cached viable source target type information except for target types -# and generators with all source types listed as viable. Should be called when -# something invalidates those cached values by possibly causing some new source -# types to become viable. -# -def invalidate_extendable_viable_source_target_type_cache(): - -    global __vstg_cached_generators -    generators_with_cached_source_types = __vstg_cached_generators -    __vstg_cached_generators = [] - -    for g in generators_with_cached_source_types: -        if __viable_source_types_cache.has_key(g): -            if __viable_source_types_cache[g] == ["*"]: -                __vstg_cached_generators.append(g) -            else: -                del __viable_source_types_cache[g] - -    global __vst_cached_types -    types_with_cached_sources_types = __vst_cached_types -    __vst_cached_types = [] -    for t in types_with_cached_sources_types: -        if __viable_source_types_cache.has_key(t): -            if __viable_source_types_cache[t] == ["*"]: -                __vst_cached_types.append(t) -            else: -                del __viable_source_types_cache[t] -  -def dout(message): -    if debug(): -        print __indent + message - -class Generator: -    """ Creates a generator. -            manager:                 the build manager. -            id:                      identifies the generator -             -            rule:                    the rule which sets up build actions. - -            composing:               whether generator processes each source target in -                                     turn, converting it to required types. -                                     Ordinary generators pass all sources together to -                                     recusrive generators.construct_types call. - -            source_types (optional): types that this generator can handle -     -            target_types_and_names:  types the generator will create and, optionally, names for -                                     created targets. Each element should have the form -                                         type["(" name-pattern ")"] -                                     for example, obj(%_x). Name of generated target will be found -                                     by replacing % with the name of source, provided explicit name -                                     was not specified. -     -            requirements (optional) -             -            NOTE: all subclasses must have a similar signature for clone to work! -    """ -    def __init__ (self, id, composing, source_types, target_types_and_names, requirements = []): -        assert(not isinstance(source_types, str)) -        assert(not isinstance(target_types_and_names, str)) -        self.id_ = id -        self.composing_ = composing -        self.source_types_ = source_types -        self.target_types_and_names_ = target_types_and_names -        self.requirements_ = requirements -         -        self.target_types_ = [] -        self.name_prefix_ = [] -        self.name_postfix_ = [] -         -        for e in target_types_and_names: -            # Create three parallel lists: one with the list of target types, -            # and two other with prefixes and postfixes to be added to target  -            # name. We use parallel lists for prefix and postfix (as opposed -            # to mapping), because given target type might occur several times, -            # for example "H H(%_symbols)". -            m = _re_separate_types_prefix_and_postfix.match (e) -             -            if not m: -                raise BaseException ("Invalid type and name '%s' in declaration of type '%s'" % (e, id)) -             -            target_type = m.group (1) -            if not target_type: target_type = '' -            prefix = m.group (3) -            if not prefix: prefix = '' -            postfix = m.group (4) -            if not postfix: postfix = '' -             -            self.target_types_.append (target_type) -            self.name_prefix_.append (prefix) -            self.name_postfix_.append (postfix) - -        for x in self.source_types_: -            type.validate (x) - -        for x in self.target_types_: -            type.validate (x) - -    def clone (self, new_id, new_toolset_properties): -        """ Returns another generator which differers from $(self) in -              - id -              - value to <toolset> feature in properties -        """ -        return self.__class__ (new_id,  -                               self.composing_,  -                               self.source_types_,  -                               self.target_types_and_names_, -                               # Note: this does not remove any subfeatures of <toolset> -                               # which might cause problems -                               property.change (self.requirements_, '<toolset>') + new_toolset_properties) - -    def clone_and_change_target_type(self, base, type): -        """Creates another generator that is the same as $(self), except that -        if 'base' is in target types of $(self), 'type' will in target types -        of the new generator.""" -        target_types = [] -        for t in self.target_types_and_names_: -            m = _re_match_type.match(t) -            assert m -             -            if m.group(1) == base: -                if m.group(2): -                    target_types.append(type + m.group(2)) -                else: -                    target_types.append(type) -            else: -                target_types.append(t) - -        return self.__class__(self.id_, self.composing_, -                              self.source_types_, -                              target_types, -                              self.requirements_) -                               - -    def id(self): -        return self.id_ - -    def source_types (self): -        """ Returns the list of target type the generator accepts. -        """ -        return self.source_types_ - -    def target_types (self): -        """ Returns the list of target types that this generator produces. -            It is assumed to be always the same -- i.e. it cannot change depending -            list of sources.     -        """ -        return self.target_types_ - -    def requirements (self): -        """ Returns the required properties for this generator. Properties -            in returned set must be present in build properties if this  -            generator is to be used. If result has grist-only element, -            that build properties must include some value of that feature. -        """ -        return self.requirements_ - -    def match_rank (self, ps): -        """ Returns true if the generator can be run with the specified  -            properties. -        """ -        # See if generator's requirements are satisfied by -        # 'properties'.  Treat a feature name in requirements -        # (i.e. grist-only element), as matching any value of the -        # feature. -        all_requirements = self.requirements () -         -        property_requirements = [] -        feature_requirements = [] -        # This uses strings because genenator requirements allow -        # the '<feature>' syntax without value and regular validation -        # is not happy about that. -        for r in all_requirements: -            if get_value (r): -                property_requirements.append (r) - -            else: -                feature_requirements.append (r) -                 -        return all(ps.get(get_grist(s)) == [get_value(s)] for s in property_requirements) \ -               and all(ps.get(get_grist(s)) for s in feature_requirements) -         -    def run (self, project, name, prop_set, sources): -        """ Tries to invoke this generator on the given sources. Returns a -            list of generated targets (instances of 'virtual-target'). - -            project:        Project for which the targets are generated. -             -            name:           Determines the name of 'name' attribute for  -                            all generated targets. See 'generated_targets' method. -                             -            prop_set:       Desired properties for generated targets. -             -            sources:        Source targets. -        """ -         -        if project.manager ().logger ().on (): -            project.manager ().logger ().log (__name__, "  generator '%s'" % self.id_) -            project.manager ().logger ().log (__name__, "  composing: '%s'" % self.composing_) -         -        if not self.composing_ and len (sources) > 1 and len (self.source_types_) > 1: -            raise BaseException ("Unsupported source/source_type combination") -                 -        # We don't run composing generators if no name is specified. The reason -        # is that composing generator combines several targets, which can have -        # different names, and it cannot decide which name to give for produced -        # target. Therefore, the name must be passed. -        # -        # This in effect, means that composing generators are runnable only -        # at top-level of transofrmation graph, or if name is passed explicitly. -        # Thus, we dissallow composing generators in the middle. For example, the -        # transofrmation CPP -> OBJ -> STATIC_LIB -> RSP -> EXE won't be allowed  -        # (the OBJ -> STATIC_LIB generator is composing) -        if not self.composing_ or name: -            return self.run_really (project, name, prop_set, sources) -        else: -            return [] - -    def run_really (self, project, name, prop_set, sources): - -        # consumed: Targets that this generator will consume directly. -        # bypassed: Targets that can't be consumed and will be returned as-is. -         -        if self.composing_: -            (consumed, bypassed) = self.convert_multiple_sources_to_consumable_types (project, prop_set, sources) -        else: -            (consumed, bypassed) = self.convert_to_consumable_types (project, name, prop_set, sources) -                 -        result = [] -        if consumed: -            result = self.construct_result (consumed, project, name, prop_set) -            result.extend (bypassed) - -        if result: -            if project.manager ().logger ().on (): -                project.manager ().logger ().log (__name__, "  SUCCESS: ", result) - -        else: -                project.manager ().logger ().log (__name__, "  FAILURE") - -        return result - -    def construct_result (self, consumed, project, name, prop_set): -        """ Constructs the dependency graph that will be returned by this  -            generator. -                consumed:        Already prepared list of consumable targets -                                 If generator requires several source files will contain  -                                 exactly len $(self.source_types_) targets with matching types -                                 Otherwise, might contain several targets with the type of  -                                 self.source_types_ [0] -                project: -                name: -                prop_set:        Properties to be used for all actions create here -        """ -        result = [] -        # If this is 1->1 transformation, apply it to all consumed targets in order. -        if len (self.source_types_) < 2 and not self.composing_: - -            for r in consumed: -                result.extend (self.generated_targets ([r], prop_set, project, name)) - -        else: - -            if consumed: -                result.extend (self.generated_targets (consumed, prop_set, project, name)) - -        return result - -    def determine_target_name(self, fullname): -        # Determine target name from fullname (maybe including path components) -        # Place optional prefix and postfix around basename - -        dir = os.path.dirname(fullname) -        name = os.path.basename(fullname) - -        if dir and not ".." in dir and not os.path.isabs(dir): -            # Relative path is always relative to the source -            # directory. Retain it, so that users can have files -            # with the same in two different subdirectories. -            name = dir + "/" + name - -        return name - -    def determine_output_name(self, sources): -        """Determine the name of the produced target from the -        names of the sources.""" -         -        # The simple case if when a name -        # of source has single dot. Then, we take the part before -        # dot. Several dots can be caused by: -        # - Using source file like a.host.cpp -        # - A type which suffix has a dot. Say, we can -        #   type 'host_cpp' with extension 'host.cpp'. -        # In the first case, we want to take the part till the last -        # dot. In the second case -- no sure, but for now take -        # the part till the last dot too. -        name = os.path.splitext(sources[0].name())[0] -                         -        for s in sources[1:]: -            n2 = os.path.splitext(s.name()) -            if n2 != name: -                get_manager().errors()( -                    "%s: source targets have different names: cannot determine target name" -                    % (self.id_)) -                         -        # Names of sources might include directory. We should strip it. -        return self.determine_target_name(sources[0].name()) -         -         -    def generated_targets (self, sources, prop_set, project, name): -        """ Constructs targets that are created after consuming 'sources'. -            The result will be the list of virtual-target, which the same length -            as 'target_types' attribute and with corresponding types. -             -            When 'name' is empty, all source targets must have the same value of  -            the 'name' attribute, which will be used instead of the 'name' argument. -             -            The value of 'name' attribute for each generated target will be equal to -            the 'name' parameter if there's no name pattern for this type. Otherwise, -            the '%' symbol in the name pattern will be replaced with the 'name' parameter  -            to obtain the 'name' attribute. -             -            For example, if targets types are T1 and T2(with name pattern "%_x"), suffixes -            for T1 and T2 are .t1 and t2, and source if foo.z, then created files would -            be "foo.t1" and "foo_x.t2". The 'name' attribute actually determined the -            basename of a file. -             -            Note that this pattern mechanism has nothing to do with implicit patterns -            in make. It's a way to produce target which name is different for name of  -            source. -        """ -        if not name: -            name = self.determine_output_name(sources) -         -        # Assign an action for each target -        action = self.action_class() -        a = action(project.manager(), sources, self.id_, prop_set) -                 -        # Create generated target for each target type. -        targets = [] -        pre = self.name_prefix_ -        post = self.name_postfix_ -        for t in self.target_types_: -            basename = os.path.basename(name) -            idx = basename.find(".") -            if idx != -1: -                basename = basename[:idx] -            generated_name = pre[0] + basename + post[0] -            generated_name = os.path.join(os.path.dirname(name), generated_name) -            pre = pre[1:] -            post = post[1:] -             -            targets.append(virtual_target.FileTarget(generated_name, t, project, a)) -         -        return [ project.manager().virtual_targets().register(t) for t in targets ] - -    def convert_to_consumable_types (self, project, name, prop_set, sources, only_one=False): -        """ Attempts to convert 'source' to the types that this generator can -            handle. The intention is to produce the set of targets can should be -            used when generator is run. -            only_one:   convert 'source' to only one of source types -                        if there's more that one possibility, report an -                        error. -                         -            Returns a pair: -                consumed: all targets that can be consumed.  -                bypassed: all targets that cannot be consumed. -        """ -        consumed = [] -        bypassed = [] -        missing_types = []  - -        if len (sources) > 1: -            # Don't know how to handle several sources yet. Just try  -            # to pass the request to other generator -            missing_types = self.source_types_ - -        else: -            (c, m) = self.consume_directly (sources [0]) -            consumed += c -            missing_types += m -         -        # No need to search for transformation if -        # some source type has consumed source and -        # no more source types are needed. -        if only_one and consumed: -            missing_types = [] -             -        #TODO: we should check that only one source type -        #if create of 'only_one' is true. -        # TODO: consider if consuned/bypassed separation should -        # be done by 'construct_types'. -                     -        if missing_types: -            transformed = construct_types (project, name, missing_types, prop_set, sources) -                                 -            # Add targets of right type to 'consumed'. Add others to -            # 'bypassed'. The 'generators.construct' rule has done -            # its best to convert everything to the required type. -            # There's no need to rerun it on targets of different types. -                 -            # NOTE: ignoring usage requirements -            for t in transformed[1]: -                if t.type() in missing_types: -                    consumed.append(t) - -                else: -                    bypassed.append(t) -         -        consumed = unique(consumed) -        bypassed = unique(bypassed) -         -        # remove elements of 'bypassed' that are in 'consumed' -         -        # Suppose the target type of current generator, X is produced from  -        # X_1 and X_2, which are produced from Y by one generator. -        # When creating X_1 from Y, X_2 will be added to 'bypassed' -        # Likewise, when creating X_2 from Y, X_1 will be added to 'bypassed' -        # But they are also in 'consumed'. We have to remove them from -        # bypassed, so that generators up the call stack don't try to convert -        # them.  - -        # In this particular case, X_1 instance in 'consumed' and X_1 instance -        # in 'bypassed' will be the same: because they have the same source and -        # action name, and 'virtual-target.register' won't allow two different -        # instances. Therefore, it's OK to use 'set.difference'. -         -        bypassed = set.difference(bypassed, consumed) - -        return (consumed, bypassed) -     - -    def convert_multiple_sources_to_consumable_types (self, project, prop_set, sources): -        """ Converts several files to consumable types. -        """         -        consumed = [] -        bypassed = [] - -        # We process each source one-by-one, trying to convert it to -        # a usable type. -        for s in sources: -            # TODO: need to check for failure on each source. -            (c, b) = self.convert_to_consumable_types (project, None, prop_set, [s], True) -            if not c: -                project.manager ().logger ().log (__name__, " failed to convert ", s) - -            consumed.extend (c) -            bypassed.extend (b) - -        return (consumed, bypassed) - -    def consume_directly (self, source): -        real_source_type = source.type () - -        # If there are no source types, we can consume anything -        source_types = self.source_types() -        if not source_types: -            source_types = [real_source_type]             - -        consumed = [] -        missing_types = [] -        for st in source_types: -            # The 'source' if of right type already) -            if real_source_type == st or type.is_derived (real_source_type, st): -                consumed.append (source) - -            else: -               missing_types.append (st) - -        return (consumed, missing_types) -     -    def action_class (self): -        """ Returns the class to be used to actions. Default implementation  -            returns "action". -        """ -        return virtual_target.Action - - -def find (id): -    """ Finds the generator with id. Returns None if not found. -    """ -    return __generators.get (id, None) - -def register (g): -    """ Registers new generator instance 'g'. -    """ -    id = g.id() - -    __generators [id] = g - -    # A generator can produce several targets of the -    # same type. We want unique occurence of that generator -    # in .generators.$(t) in that case, otherwise, it will -    # be tried twice and we'll get false ambiguity. -    for t in sequence.unique(g.target_types()): -        __type_to_generators.setdefault(t, []).append(g) - -    # Update the set of generators for toolset - -    # TODO: should we check that generator with this id -    # is not already registered. For example, the fop.jam -    # module intentionally declared two generators with the -    # same id, so such check will break it. - -    # Some generators have multiple periods in their name, so the -    # normal $(id:S=) won't generate the right toolset name. -    # e.g. if id = gcc.compile.c++, then -    # .generators-for-toolset.$(id:S=) will append to -    # .generators-for-toolset.gcc.compile, which is a separate -    # value from .generators-for-toolset.gcc. Correcting this -    # makes generator inheritance work properly. -    # See also inherit-generators in module toolset -    base = id.split ('.', 100) [0] - -    __generators_for_toolset.setdefault(base, []).append(g) - -    # After adding a new generator that can construct new target types, we need -    # to clear the related cached viable source target type information for -    # constructing a specific target type or using a specific generator. Cached -    # viable source target type lists affected by this are those containing any -    # of the target types constructed by the new generator or any of their base -    # target types. -    # -    # A more advanced alternative to clearing that cached viable source target -    # type information would be to expand it with additional source types or -    # even better - mark it as needing to be expanded on next use. -    # -    # For now we just clear all the cached viable source target type information -    # that does not simply state 'all types' and may implement a more detailed -    # algorithm later on if it becomes needed. - -    invalidate_extendable_viable_source_target_type_cache() - - -def register_standard (id, source_types, target_types, requirements = []): -    """ Creates new instance of the 'generator' class and registers it. -        Returns the creates instance. -        Rationale: the instance is returned so that it's possible to first register -        a generator and then call 'run' method on that generator, bypassing all -        generator selection. -    """ -    g = Generator (id, False, source_types, target_types, requirements) -    register (g) -    return g - -def register_composing (id, source_types, target_types, requirements = []): -    g = Generator (id, True, source_types, target_types, requirements) -    register (g) -    return g - -def generators_for_toolset (toolset): -    """ Returns all generators which belong to 'toolset'. -    """ -    return __generators_for_toolset.get(toolset, []) - -def override (overrider_id, overridee_id): -    """Make generator 'overrider-id' be preferred to -    'overridee-id'. If, when searching for generators -    that could produce a target of certain type, -    both those generators are amoung viable generators, -    the overridden generator is immediately discarded. -     -    The overridden generators are discarded immediately -    after computing the list of viable generators, before -    running any of them.""" -     -    __overrides.get(overrider_id, []).append(overridee_id) - -def __viable_source_types_real (target_type): -    """ Returns a list of source type which can possibly be converted -        to 'target_type' by some chain of generator invocation. -         -        More formally, takes all generators for 'target_type' and -        returns union of source types for those generators and result -        of calling itself recusrively on source types. -    """ -    generators = [] - -    # 't0' is the initial list of target types we need to process to get a list -    # of their viable source target types. New target types will not be added to -    # this list.          -    t0 = type.all_bases (target_type) - - -    # 't' is the list of target types which have not yet been processed to get a -    # list of their viable source target types. This list will get expanded as -    # we locate more target types to process. -    t = t0 -     -    result = [] -    while t: -        # Find all generators for current type.  -        # Unlike 'find_viable_generators' we don't care about prop_set. -        generators = __type_to_generators.get (t [0], []) -        t = t[1:] -         -        for g in generators: -            if not g.source_types(): -                # Empty source types -- everything can be accepted -                result = "*" -                # This will terminate outer loop. -                t = None -                break -             -            for source_type in g.source_types (): -                if not source_type in result: -                    # If generator accepts 'source_type' it -                    # will happily accept any type derived from it -                    all = type.all_derived (source_type) -                    for n in all: -                        if not n in result: - -                            # Here there is no point in adding target types to -                            # the list of types to process in case they are or -                            # have already been on that list. We optimize this -                            # check by realizing that we only need to avoid the -                            # original target type's base types. Other target -                            # types that are or have been on the list of target -                            # types to process have been added to the 'result' -                            # list as well and have thus already been eliminated -                            # by the previous if. -                            if not n in t0: -                                t.append (n) -                            result.append (n) -            -    return result - - -def viable_source_types (target_type): -    """ Helper rule, caches the result of '__viable_source_types_real'. -    """ -    if not __viable_source_types_cache.has_key(target_type): -        __vst_cached_types.append(target_type) -        __viable_source_types_cache [target_type] = __viable_source_types_real (target_type) -    return __viable_source_types_cache [target_type] - -def viable_source_types_for_generator_real (generator): -    """ Returns the list of source types, which, when passed to 'run' -        method of 'generator', has some change of being eventually used -        (probably after conversion by other generators) -    """ -    source_types = generator.source_types () - -    if not source_types: -        # If generator does not specify any source types, -        # it might be special generator like builtin.lib-generator -        # which just relays to other generators. Return '*' to -        # indicate that any source type is possibly OK, since we don't -        # know for sure. -        return ['*'] - -    else: -        result = [] -        for s in source_types: -            viable_sources = viable_source_types(s) -            if viable_sources == "*": -                result = ["*"] -                break -            else: -                result.extend(type.all_derived(s) + viable_sources) -        return unique(result) - -def viable_source_types_for_generator (generator): -    """ Caches the result of 'viable_source_types_for_generator'. -    """ -    if not __viable_source_types_cache.has_key(generator): -        __vstg_cached_generators.append(generator) -        __viable_source_types_cache[generator] = viable_source_types_for_generator_real (generator) -     -    return __viable_source_types_cache[generator] - -def try_one_generator_really (project, name, generator, target_type, properties, sources): -    """ Returns usage requirements + list of created targets. -    """ -    targets = generator.run (project, name, properties, sources) - -    usage_requirements = [] -    success = False - -    dout("returned " + str(targets)) - -    if targets: -        success = True; -         -        if isinstance (targets[0], property_set.PropertySet): -            usage_requirements = targets [0] -            targets = targets [1] - -        else: -            usage_requirements = property_set.empty () - -    dout(  "  generator" + generator.id() + " spawned ") -    #    generators.dout [ indent ] " " $(targets) ;  -#    if $(usage-requirements) -#    { -#        generators.dout [ indent ] "  with usage requirements:" $(x) ; -#    } - -    if success: -        return (usage_requirements, targets) -    else: -        return None - -def try_one_generator (project, name, generator, target_type, properties, sources): -    """ Checks if generator invocation can be pruned, because it's guaranteed -        to fail. If so, quickly returns empty list. Otherwise, calls -        try_one_generator_really. -    """ -    source_types = [] - -    for s in sources: -        source_types.append (s.type ()) - -    viable_source_types = viable_source_types_for_generator (generator) -     -    if source_types and viable_source_types != ['*'] and\ -           not set.intersection (source_types, viable_source_types): -        if project.manager ().logger ().on (): -            id = generator.id ()             -            project.manager ().logger ().log (__name__, "generator '%s' pruned" % id) -            project.manager ().logger ().log (__name__, "source_types" '%s' % source_types) -            project.manager ().logger ().log (__name__, "viable_source_types '%s'" % viable_source_types) -         -        return [] - -    else: -        return try_one_generator_really (project, name, generator, target_type, properties, sources) - - -def construct_types (project, name, target_types, prop_set, sources): -     -    result = [] -    usage_requirements = property_set.empty() -     -    for t in target_types: -        r = construct (project, name, t, prop_set, sources) - -        if r: -            (ur, targets) = r -            usage_requirements = usage_requirements.add(ur) -            result.extend(targets) - -    # TODO: have to introduce parameter controlling if -    # several types can be matched and add appropriate -    # checks  - -    # TODO: need to review the documentation for -    # 'construct' to see if it should return $(source) even -    # if nothing can be done with it. Currents docs seem to -    # imply that, contrary to the behaviour. -    if result: -        return (usage_requirements, result) - -    else: -        return (usage_requirements, sources) - -def __ensure_type (targets): -    """ Ensures all 'targets' have types. If this is not so, exists with  -        error. -    """ -    for t in targets: -        if not t.type (): -            get_manager().errors()("target '%s' has no type" % str (t)) - -def find_viable_generators_aux (target_type, prop_set): -    """ Returns generators which can be used to construct target of specified type -        with specified properties. Uses the following algorithm: -        - iterates over requested target_type and all it's bases (in the order returned bt -          type.all-bases. -        - for each type find all generators that generate that type and which requirements -          are satisfied by properties. -        - if the set of generators is not empty, returns that set. -         -        Note: this algorithm explicitly ignores generators for base classes if there's -        at least one generator for requested target_type. -    """ -    # Select generators that can create the required target type. -    viable_generators = [] -    initial_generators = [] - -    import type - -    # Try all-type generators first. Assume they have -    # quite specific requirements. -    all_bases = type.all_bases(target_type) -         -    for t in all_bases: -         -        initial_generators = __type_to_generators.get(t, []) -         -        if initial_generators: -            dout("there are generators for this type") -            if t != target_type: -                # We're here, when no generators for target-type are found, -                # but there are some generators for a base type. -                # We'll try to use them, but they will produce targets of -                # base type, not of 'target-type'. So, we clone the generators -                # and modify the list of target types. -                generators2 = [] -                for g in initial_generators[:]: -                    # generators.register adds generator to the list of generators -                    # for toolsets, which is a bit strange, but should work. -                    # That list is only used when inheriting toolset, which -                    # should have being done before generators are run. -                    ng = g.clone_and_change_target_type(t, target_type) -                    generators2.append(ng) -                    register(ng) -                     -                initial_generators = generators2 -            break -     -    for g in initial_generators: -        dout("trying generator " + g.id() -             + "(" + str(g.source_types()) + "->" + str(g.target_types()) + ")") -         -        m = g.match_rank(prop_set) -        if m: -            dout("  is viable") -            viable_generators.append(g)             -                             -    return viable_generators - -def find_viable_generators (target_type, prop_set): -    key = target_type + '.' + str (prop_set) - -    l = __viable_generators_cache.get (key, None) -    if not l: -        l = [] - -    if not l: -        l = find_viable_generators_aux (target_type, prop_set) - -        __viable_generators_cache [key] = l - -    viable_generators = [] -    for g in l: -        # Avoid trying the same generator twice on different levels. -        # TODO: is this really used? -        if not g in __active_generators: -            viable_generators.append (g) -        else: -            dout("      generator %s is active, discarding" % g.id()) - -    # Generators which override 'all'. -    all_overrides = [] -     -    # Generators which are overriden -    overriden_ids = []  -        -    for g in viable_generators: -        id = g.id () -         -        this_overrides = __overrides.get (id, []) -         -        if this_overrides: -            overriden_ids.extend (this_overrides) -            if 'all' in this_overrides: -                all_overrides.append (g) - -    if all_overrides: -        viable_generators = all_overrides - -    result = [] -    for g in viable_generators: -        if not g.id () in overriden_ids: -            result.append (g) - -         -    return result -     -def __construct_really (project, name, target_type, prop_set, sources): -    """ Attempts to construct target by finding viable generators, running them -        and selecting the dependency graph. -    """ -    viable_generators = find_viable_generators (target_type, prop_set) -                     -    result = [] - -    project.manager ().logger ().log (__name__, "*** %d viable generators" % len (viable_generators)) - -    generators_that_succeeded = [] -     -    for g in viable_generators: -        __active_generators.append(g)         -        r = try_one_generator (project, name, g, target_type, prop_set, sources) -        del __active_generators[-1] -         -        if r: -            generators_that_succeeded.append(g) -            if result: -                output = cStringIO.StringIO() -                print >>output, "ambiguity found when searching for best transformation" -                print >>output, "Trying to produce type '%s' from: " % (target_type) -                for s in sources: -                    print >>output, " - " + s.str() -                print >>output, "Generators that succeeded:" -                for g in generators_that_succeeded: -                    print >>output, " - " + g.id() -                print >>output, "First generator produced: " -                for t in result[1:]: -                    print >>output, " - " + str(t) -                print >>output, "Second generator produced:" -                for t in r[1:]: -                    print >>output, " - " + str(t) -                get_manager().errors()(output.getvalue()) -            else: -                result = r; -             -    return result; - - -def construct (project, name, target_type, prop_set, sources, top_level=False): -    """ Attempts to create target of 'target-type' with 'properties' -        from 'sources'. The 'sources' are treated as a collection of -        *possible* ingridients -- i.e. it is not required to consume -        them all. If 'multiple' is true, the rule is allowed to return -        several targets of 'target-type'.           -         -        Returns a list of target. When this invocation is first instance of -        'construct' in stack, returns only targets of requested 'target-type', -        otherwise, returns also unused sources and additionally generated -        targets. -         -        If 'top-level' is set, does not suppress generators that are already -        used in the stack. This may be useful in cases where a generator -        has to build a metatarget -- for example a target corresponding to -        built tool.         -    """ - -    global __active_generators -    if top_level: -        saved_active = __active_generators -        __active_generators = [] - -    global __construct_stack -    if not __construct_stack: -        __ensure_type (sources) -         -    __construct_stack.append (1) - -    if project.manager().logger().on(): -        increase_indent () -         -        dout( "*** construct " + target_type) -         -        for s in sources: -            dout("    from " + str(s)) - -        project.manager().logger().log (__name__, "    properties: ", prop_set.raw ()) -              -    result = __construct_really(project, name, target_type, prop_set, sources) - -    project.manager().logger().decrease_indent() -         -    __construct_stack = __construct_stack [1:] - -    if top_level: -        __active_generators = saved_active - -    return result -     diff --git a/jam-files/boost-build/build/modifiers.jam b/jam-files/boost-build/build/modifiers.jam deleted file mode 100644 index 6b009343..00000000 --- a/jam-files/boost-build/build/modifiers.jam +++ /dev/null @@ -1,232 +0,0 @@ -# Copyright 2003 Rene Rivera -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - -# Modifiers are generalized generators that mutate targets in specific ways. -# This structure allows for grouping a variety of functionality in an -# orthogonal way to the functionality in toolsets, and without specifying -# more target variations. In turn the modifiers can be used as building -# blocks to implement simple requests, like the <version> feature. - -import modules ; -import feature ; -import errors ; -import type ; -import "class" : new ; -import generators ; -import property ; -import virtual-target ; -import numbers ; -import sequence ; -import symlink ; -import property-set ; - -# Base generator for creating targets that are modifications of existing -# targets. -# -class modifier : generator -{ -    rule __init__ ( -        id -        composing ? -        : source-types * -        : target-types-and-names + -        : requirements * -        ) -    { -        generator.__init__ $(id) $(composing) -            : $(source-types) -            : $(target-types-and-names) -            : $(requirements) ; - -        self.targets-in-progress = ; -    } - -    # Wraps the generation of the target to call before and after rules to -    # affect the real target. -    # -    rule run ( project name ? : property-set : sources + ) -    { -        local result ; -        local current-target = $(project)^$(name) ; -        if ! $(current-target) in $(self.targets-in-progress) -        { -            # Before modifications... -            local project_ = -                [ modify-project-before -                    $(project) $(name) : $(property-set) : $(sources) ] ; -            local name_ = -                [ modify-name-before -                    $(project) $(name) : $(property-set) : $(sources) ] ; -            local property-set_ = -                [ modify-properties-before -                    $(project) $(name) : $(property-set) : $(sources) ] ; -            local sources_ = -                [ modify-sources-before -                    $(project) $(name) : $(property-set) : $(sources) ] ; -            project = $(project_) ; -            name = $(name_) ; -            property-set = $(property-set_) ; -            sources = $(sources_) ; - -            # Generate the real target... -            local target-type-p = -                [ property.select <main-target-type> : [ $(property-set).raw ] ] ; -            self.targets-in-progress += $(current-target) ; -            result = -                [ generators.construct $(project) $(name) -                    : $(target-type-p:G=) -                    : $(property-set) -                    : $(sources) ] ; -            self.targets-in-progress = $(self.targets-in-progress[1--2]) ; - -            # After modifications... -            result = -                [ modify-target-after $(result) -                    : $(project) $(name) -                    : $(property-set) -                    : $(sources) ] ; -        } -        return $(result) ; -    } - -    rule modify-project-before ( project name ? : property-set : sources + ) -    { -        return $(project) ; -    } - -    rule modify-name-before ( project name ? : property-set : sources + ) -    { -        return $(name) ; -    } - -    rule modify-properties-before ( project name ? : property-set : sources + ) -    { -        return $(property-set) ; -    } - -    rule modify-sources-before ( project name ? : property-set : sources + ) -    { -        return $(sources) ; -    } - -    rule modify-target-after ( target : project name ? : property-set : sources + ) -    { -        return $(target) ; -    } - -    # Utility, clones a file-target with optional changes to the name, type and -    # project of the target. -    # NOTE: This functionality should be moved, and generalized, to -    # virtual-targets. -    # -    rule clone-file-target ( target : new-name ? : new-type ? : new-project ? ) -    { -        # Need a MUTCH better way to clone a target... -        new-name ?= [ $(target).name ] ; -        new-type ?= [ $(target).type ] ; -        new-project ?= [ $(target).project ] ; -        local result = [ new file-target $(new-name) : $(new-type) : $(new-project) ] ; - -        if [ $(target).dependencies ] { $(result).depends [ $(target).dependencies ] ; } -        $(result).root [ $(target).root ] ; -        $(result).set-usage-requirements [ $(target).usage-requirements ] ; - -        local action = [ $(target).action ] ; -        local action-class = [ modules.peek $(action) : __class__ ] ; - -        local ps = [ $(action).properties ] ; -        local cloned-action = [ new $(action-class) $(result) : -          [ $(action).sources ] : [ $(action).action-name ] : $(ps) ] ; -        $(result).action $(cloned-action) ; - -        return $(result) ; -    } -} - - -# A modifier that changes the name of a target, after it's generated, given a -# regular expression to split the name, and a set of token to insert between the -# split tokens of the name. This also exposes the target for other uses with a -# symlink to the original name (optionally). -# -class name-modifier : modifier -{ -    rule __init__ ( ) -    { -        # Apply ourselves to EXE targets, for now. -        modifier.__init__ name.modifier : : EXE LIB : <name-modify>yes ; -    } - -    # Modifies the name, by cloning the target with the new name. -    # -    rule modify-target-after ( target : project name ? : property-set : sources + ) -    { -        local result = $(target) ; - -        local name-mod-p = [ property.select <name-modifier> : [ $(property-set).raw ] ] ; -        if $(name-mod-p) -        { -            local new-name = [ modify-name [ $(target).name ] : $(name-mod-p:G=) ] ; -            if $(new-name) != [ $(target).name ] -            { -                result = [ clone-file-target $(target) : $(new-name) ] ; -            } -            local expose-original-as-symlink = [ MATCH "<symlink>(.*)" : $(name-mod-p) ] ; -            if $(expose-original-as-symlink) -            { -                local symlink-t = [ new symlink-targets $(project) : $(name) : [ $(result).name ] ] ; -                result = [ $(symlink-t).construct $(result) -                    : [ property-set.create [ $(property-set).raw ] <symlink-location>build-relative ] ] ; -            } -        } - -        return $(result) ; -    } - -    # Do the transformation of the name. -    # -    rule modify-name ( name : modifier-spec + ) -    { -        local match = [ MATCH "<match>(.*)" : $(modifier-spec) ] ; -        local name-parts = [ MATCH $(match) : $(name) ] ; -        local insertions = [ sequence.insertion-sort [ MATCH "(<[0123456789]+>.*)" : $(modifier-spec) ] ] ; -        local new-name-parts ; -        local insert-position = 1 ; -        while $(insertions) -        { -            local insertion = [ MATCH "<$(insert-position)>(.*)" : $(insertions[1]) ] ; -            if $(insertion) -            { -                new-name-parts += $(insertion) ; -                insertions = $(insertions[2-]) ; -            } -            new-name-parts += $(name-parts[1]) ; -            name-parts = $(name-parts[2-]) ; -            insert-position = [ numbers.increment $(insert-position) ] ; -        } -        new-name-parts += $(name-parts) ; -        return [ sequence.join $(new-name-parts) ] ; -    } - -    rule optional-properties ( ) -    { -        return <name-modify>yes ; -    } -} -feature.feature name-modifier : : free ; -feature.feature name-modify : no yes : incidental optional ; -generators.register [ new name-modifier ] ; - -# Translates <version> property to a set of modification properties -# that are applied by the name-modifier, and symlink-modifier. -# -rule version-to-modifier ( property : properties * ) -{ -    return -        <name-modify>yes -            <name-modifier><match>"^([^.]*)(.*)" <name-modifier><2>.$(property:G=) -            <name-modifier><symlink>yes -        ; -} -feature.action <version> : version-to-modifier ; diff --git a/jam-files/boost-build/build/project.ann.py b/jam-files/boost-build/build/project.ann.py deleted file mode 100644 index 349f5495..00000000 --- a/jam-files/boost-build/build/project.ann.py +++ /dev/null @@ -1,996 +0,0 @@ -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000   1) # Status: being ported by Vladimir Prus -ddc17f01 (vladimir_prus 2007-10-26 14:57:56 +0000   2) # Base revision: 40480 -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000   3)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000   4) # Copyright 2002, 2003 Dave Abrahams  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000   5) # Copyright 2002, 2005, 2006 Rene Rivera  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000   6) # Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000   7) # Distributed under the Boost Software License, Version 1.0.  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000   8) # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000   9)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  10) #  Implements project representation and loading. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  11) #   Each project is represented by  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  12) #   - a module where all the Jamfile content live.  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  13) #   - an instance of 'project-attributes' class. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  14) #     (given module name, can be obtained by 'attributes' rule) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  15) #   - an instance of 'project-target' class (from targets.jam) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  16) #     (given a module name, can be obtained by 'target' rule) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  17) # -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  18) #  Typically, projects are created as result of loading Jamfile, which is -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  19) #  do by rules 'load' and 'initialize', below. First, module for Jamfile -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  20) #  is loaded and new project-attributes instance is created. Some rules -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  21) #  necessary for project are added to the module (see 'project-rules' module) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  22) #  at the bottom of this file. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  23) #  Default project attributes are set (inheriting attributes of parent project, if -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  24) #  it exists). After that, Jamfile is read. It can declare its own attributes, -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  25) #  via 'project' rule, which will be combined with already set attributes. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  26) # -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  27) # -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  28) #  The 'project' rule can also declare project id, which will be associated with  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  29) #  the project module. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  30) # -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  31) #  There can also be 'standalone' projects. They are created by calling 'initialize' -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  32) #  on arbitrary module, and not specifying location. After the call, the module can -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  33) #  call 'project' rule, declare main target and behave as regular projects. However, -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  34) #  since it's not associated with any location, it's better declare only prebuilt  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  35) #  targets. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  36) # -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  37) #  The list of all loaded Jamfile is stored in variable .project-locations. It's possible -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  38) #  to obtain module name for a location using 'module-name' rule. The standalone projects -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  39) #  are not recorded, the only way to use them is by project id. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  40)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  41) import b2.util.path -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000  42) from b2.build import property_set, property -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000  43) from b2.build.errors import ExceptionWithUserContext -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  44) import b2.build.targets -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  45)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  46) import bjam -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  47)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  48) import re -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  49) import sys -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  50) import os -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  51) import string -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000  52) import imp -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000  53) import traceback -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  54)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  55) class ProjectRegistry: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  56)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  57)     def __init__(self, manager, global_build_dir): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  58)         self.manager = manager -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  59)         self.global_build_dir = None -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000  60)         self.project_rules_ = ProjectRules(self) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  61)  -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000  62)         # The target corresponding to the project being loaded now -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  63)         self.current_project = None -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  64)          -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  65)         # The set of names of loaded project modules -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  66)         self.jamfile_modules = {} -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  67)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  68)         # Mapping from location to module name -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  69)         self.location2module = {} -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  70)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  71)         # Mapping from project id to project module -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  72)         self.id2module = {} -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  73)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  74)         # Map from Jamfile directory to parent Jamfile/Jamroot -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  75)         # location. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  76)         self.dir2parent_jamfile = {} -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  77)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  78)         # Map from directory to the name of Jamfile in -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  79)         # that directory (or None). -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  80)         self.dir2jamfile = {} -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  81)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  82)         # Map from project module to attributes object. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  83)         self.module2attributes = {} -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  84)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  85)         # Map from project module to target for the project -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  86)         self.module2target = {} -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  87)  -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000  88)         # Map from names to Python modules, for modules loaded -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000  89)         # via 'using' and 'import' rules in Jamfiles. -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000  90)         self.loaded_tool_modules_ = {} -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000  91)  -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000  92)         # Map from project target to the list of -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000  93)         # (id,location) pairs corresponding to all 'use-project' -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000  94)         # invocations. -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000  95)         # TODO: should not have a global map, keep this -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000  96)         # in ProjectTarget. -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000  97)         self.used_projects = {} -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000  98)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  99)         self.saved_current_project = [] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 100)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 101)         self.JAMROOT = self.manager.getenv("JAMROOT"); -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 102)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 103)         # Note the use of character groups, as opposed to listing -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 104)         # 'Jamroot' and 'jamroot'. With the latter, we'd get duplicate -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 105)         # matches on windows and would have to eliminate duplicates. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 106)         if not self.JAMROOT: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 107)             self.JAMROOT = ["project-root.jam", "[Jj]amroot", "[Jj]amroot.jam"] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 108)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 109)         # Default patterns to search for the Jamfiles to use for build -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 110)         # declarations. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 111)         self.JAMFILE = self.manager.getenv("JAMFILE") -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 112)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 113)         if not self.JAMFILE: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 114)             self.JAMFILE = ["[Bb]uild.jam", "[Jj]amfile.v2", "[Jj]amfile", -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 115)                             "[Jj]amfile.jam"] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 116)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 117)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 118)     def load (self, jamfile_location): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 119)         """Loads jamfile at the given location. After loading, project global -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 120)         file and jamfile needed by the loaded one will be loaded recursively. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 121)         If the jamfile at that location is loaded already, does nothing. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 122)         Returns the project module for the Jamfile.""" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 123)  -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 124)         absolute = os.path.join(os.getcwd(), jamfile_location) -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 125)         absolute = os.path.normpath(absolute) -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 126)         jamfile_location = b2.util.path.relpath(os.getcwd(), absolute) -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 127)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 128)         if "--debug-loading" in self.manager.argv(): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 129)             print "Loading Jamfile at '%s'" % jamfile_location -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 130)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 131)              -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 132)         mname = self.module_name(jamfile_location) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 133)         # If Jamfile is already loaded, don't try again. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 134)         if not mname in self.jamfile_modules: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 135)          -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 136)             self.load_jamfile(jamfile_location) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 137)                  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 138)             # We want to make sure that child project are loaded only -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 139)             # after parent projects. In particular, because parent projects -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 140)             # define attributes whch are inherited by children, and we don't -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 141)             # want children to be loaded before parents has defined everything. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 142)             # -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 143)             # While "build-project" and "use-project" can potentially refer -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 144)             # to child projects from parent projects, we don't immediately -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 145)             # load child projects when seing those attributes. Instead, -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 146)             # we record the minimal information that will be used only later. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 147)              -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 148)             self.load_used_projects(mname) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 149)               -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 150)         return mname -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 151)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 152)     def load_used_projects(self, module_name): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 153)         # local used = [ modules.peek $(module-name) : .used-projects ] ; -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 154)         used = self.used_projects[module_name] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 155)      -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 156)         location = self.attribute(module_name, "location") -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 157)         for u in used: -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 158)             id = u[0] -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 159)             where = u[1] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 160)  -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 161)             self.use(id, os.path.join(location, where)) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 162)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 163)     def load_parent(self, location): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 164)         """Loads parent of Jamfile at 'location'. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 165)         Issues an error if nothing is found.""" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 166)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 167)         found = b2.util.path.glob_in_parents( -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 168)             location, self.JAMROOT + self.JAMFILE)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 169)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 170)         if not found: -1674e2d9 (jhunold       2008-08-08 19:52:05 +0000 171)             print "error: Could not find parent for project at '%s'" % location -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 172)             print "error: Did not find Jamfile or project-root.jam in any parent directory." -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 173)             sys.exit(1) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 174)      -49c03622 (jhunold       2008-07-23 09:57:41 +0000 175)         return self.load(os.path.dirname(found[0])) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 176)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 177)     def act_as_jamfile(self, module, location): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 178)         """Makes the specified 'module' act as if it were a regularly loaded Jamfile  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 179)         at 'location'. If Jamfile is already located for that location, it's an  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 180)         error.""" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 181)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 182)         if self.module_name(location) in self.jamfile_modules: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 183)             self.manager.errors()( -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 184)                 "Jamfile was already loaded for '%s'" % location) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 185)      -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 186)         # Set up non-default mapping from location to module. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 187)         self.location2module[location] = module -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 188)      -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 189)         # Add the location to the list of project locations -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 190)         # so that we don't try to load Jamfile in future -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 191)         self.jamfile_modules.append(location) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 192)      -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 193)         self.initialize(module, location) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 194)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 195)     def find(self, name, current_location): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 196)         """Given 'name' which can be project-id or plain directory name, -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 197)         return project module corresponding to that id or directory. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 198)         Returns nothing of project is not found.""" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 199)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 200)         project_module = None -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 201)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 202)         # Try interpreting name as project id. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 203)         if name[0] == '/': -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 204)             project_module = self.id2module.get(name) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 205)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 206)         if not project_module: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 207)             location = os.path.join(current_location, name) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 208)             # If no project is registered for the given location, try to -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 209)             # load it. First see if we have Jamfile. If not we might have project -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 210)             # root, willing to act as Jamfile. In that case, project-root -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 211)             # must be placed in the directory referred by id. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 212)          -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 213)             project_module = self.module_name(location) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 214)             if not project_module in self.jamfile_modules and \ -49c03622 (jhunold       2008-07-23 09:57:41 +0000 215)                b2.util.path.glob([location], self.JAMROOT + self.JAMFILE): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 216)                 project_module = self.load(location) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 217)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 218)         return project_module -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 219)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 220)     def module_name(self, jamfile_location): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 221)         """Returns the name of module corresponding to 'jamfile-location'. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 222)         If no module corresponds to location yet, associates default -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 223)         module name with that location.""" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 224)         module = self.location2module.get(jamfile_location) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 225)         if not module: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 226)             # Root the path, so that locations are always umbiguious. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 227)             # Without this, we can't decide if '../../exe/program1' and '.' -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 228)             # are the same paths, or not. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 229)             jamfile_location = os.path.realpath( -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 230)                 os.path.join(os.getcwd(), jamfile_location)) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 231)             module = "Jamfile<%s>" % jamfile_location -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 232)             self.location2module[jamfile_location] = module -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 233)         return module -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 234)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 235)     def find_jamfile (self, dir, parent_root=0, no_errors=0): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 236)         """Find the Jamfile at the given location. This returns the -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 237)         exact names of all the Jamfiles in the given directory. The optional -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 238)         parent-root argument causes this to search not the given directory -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 239)         but the ones above it up to the directory given in it.""" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 240)          -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 241)         # Glob for all the possible Jamfiles according to the match pattern. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 242)         # -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 243)         jamfile_glob = None -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 244)         if parent_root: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 245)             parent = self.dir2parent_jamfile.get(dir) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 246)             if not parent: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 247)                 parent = b2.util.path.glob_in_parents(dir, -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 248)                                                                self.JAMFILE) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 249)                 self.dir2parent_jamfile[dir] = parent -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 250)             jamfile_glob = parent -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 251)         else: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 252)             jamfile = self.dir2jamfile.get(dir) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 253)             if not jamfile: -49c03622 (jhunold       2008-07-23 09:57:41 +0000 254)                 jamfile = b2.util.path.glob([dir], self.JAMFILE) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 255)                 self.dir2jamfile[dir] = jamfile -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 256)             jamfile_glob = jamfile -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 257)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 258)         if len(jamfile_glob): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 259)             # Multiple Jamfiles found in the same place. Warn about this. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 260)             # And ensure we use only one of them. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 261)             # As a temporary convenience measure, if there's Jamfile.v2 amount -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 262)             # found files, suppress the warning and use it. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 263)             # -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 264)             pattern = "(.*[Jj]amfile\\.v2)|(.*[Bb]uild\\.jam)" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 265)             v2_jamfiles = [x for x in jamfile_glob if re.match(pattern, x)] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 266)             if len(v2_jamfiles) == 1: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 267)                 jamfile_glob = v2_jamfiles -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 268)             else: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 269)                 print """warning: Found multiple Jamfiles at '%s'! -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 270) Loading the first one: '%s'.""" % (dir, jamfile_glob[0]) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 271)      -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 272)         # Could not find it, error. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 273)         if not no_errors and not jamfile_glob: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 274)             self.manager.errors()( -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 275)                 """Unable to load Jamfile. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 276) Could not find a Jamfile in directory '%s' -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 277) Attempted to find it with pattern '%s'. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 278) Please consult the documentation at 'http://boost.org/b2.'.""" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 279)                 % (dir, string.join(self.JAMFILE))) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 280)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 281)         return jamfile_glob[0] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 282)      -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 283)     def load_jamfile(self, dir): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 284)         """Load a Jamfile at the given directory. Returns nothing. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 285)         Will attempt to load the file as indicated by the JAMFILE patterns. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 286)         Effect of calling this rule twice with the same 'dir' is underfined.""" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 287)        -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 288)         # See if the Jamfile is where it should be. -49c03622 (jhunold       2008-07-23 09:57:41 +0000 289)         jamfile_to_load = b2.util.path.glob([dir], self.JAMROOT) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 290)         if not jamfile_to_load: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 291)             jamfile_to_load = self.find_jamfile(dir) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 292)         else: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 293)             jamfile_to_load = jamfile_to_load[0] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 294)              -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 295)         # The module of the jamfile. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 296)         dir = os.path.realpath(os.path.dirname(jamfile_to_load)) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 297)          -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 298)         jamfile_module = self.module_name (dir) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 299)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 300)         # Initialize the jamfile module before loading. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 301)         #     -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 302)         self.initialize(jamfile_module, dir, os.path.basename(jamfile_to_load)) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 303)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 304)         saved_project = self.current_project -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 305)  -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 306)         self.used_projects[jamfile_module] = [] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 307)          -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 308)         # Now load the Jamfile in it's own context. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 309)         # Initialization might have load parent Jamfiles, which might have -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 310)         # loaded the current Jamfile with use-project. Do a final check to make -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 311)         # sure it's not loaded already. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 312)         if not jamfile_module in self.jamfile_modules: -49c03622 (jhunold       2008-07-23 09:57:41 +0000 313)             self.jamfile_modules[jamfile_module] = True -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 314)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 315)             # FIXME: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 316)             # mark-as-user $(jamfile-module) ; -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 317)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 318)             bjam.call("load", jamfile_module, jamfile_to_load) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 319)             basename = os.path.basename(jamfile_to_load) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 320)                          -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 321)         # Now do some checks -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 322)         if self.current_project != saved_project: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 323)             self.manager.errors()( -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 324) """The value of the .current-project variable -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 325) has magically changed after loading a Jamfile. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 326) This means some of the targets might be defined a the wrong project. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 327) after loading %s -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 328) expected value %s -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 329) actual value %s""" % (jamfile_module, saved_project, self.current_project)) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 330)            -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 331)         if self.global_build_dir: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 332)             id = self.attribute(jamfile_module, "id") -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 333)             project_root = self.attribute(jamfile_module, "project-root") -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 334)             location = self.attribute(jamfile_module, "location") -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 335)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 336)             if location and project_root == dir: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 337)                 # This is Jamroot -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 338)                 if not id: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 339)                     # FIXME: go via errors module, so that contexts are -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 340)                     # shown? -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 341)                     print "warning: the --build-dir option was specified" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 342)                     print "warning: but Jamroot at '%s'" % dir -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 343)                     print "warning: specified no project id" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 344)                     print "warning: the --build-dir option will be ignored" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 345)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 346)  -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 347)     def load_standalone(self, jamfile_module, file): -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 348)         """Loads 'file' as standalone project that has no location -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 349)         associated with it.  This is mostly useful for user-config.jam, -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 350)         which should be able to define targets, but although it has -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 351)         some location in filesystem, we don't want any build to -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 352)         happen in user's HOME, for example. -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 353)  -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 354)         The caller is required to never call this method twice on -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 355)         the same file. -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 356)         """ -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 357)  -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 358)         self.initialize(jamfile_module) -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 359)         self.used_projects[jamfile_module] = [] -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 360)         bjam.call("load", jamfile_module, file) -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 361)         self.load_used_projects(jamfile_module) -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 362)          -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 363)     def is_jamroot(self, basename): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 364)         match = [ pat for pat in self.JAMROOT if re.match(pat, basename)] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 365)         if match: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 366)             return 1 -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 367)         else: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 368)             return 0 -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 369)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 370)     def initialize(self, module_name, location=None, basename=None): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 371)         """Initialize the module for a project. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 372)          -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 373)         module-name is the name of the project module. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 374)         location is the location (directory) of the project to initialize. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 375)                  If not specified, stanalone project will be initialized -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 376)         """ -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 377)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 378)         if "--debug-loading" in self.manager.argv(): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 379)             print "Initializing project '%s'" % module_name -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 380)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 381)         # TODO: need to consider if standalone projects can do anything but defining -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 382)         # prebuilt targets. If so, we need to give more sensible "location", so that -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 383)         # source paths are correct. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 384)         if not location: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 385)             location = "" -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 386)         else: -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 387)             location = b2.util.path.relpath(os.getcwd(), location) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 388)  -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 389)         attributes = ProjectAttributes(self.manager, location, module_name) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 390)         self.module2attributes[module_name] = attributes -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 391)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 392)         if location: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 393)             attributes.set("source-location", location, exact=1) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 394)         else: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 395)             attributes.set("source-location", "", exact=1) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 396)  -49c03622 (jhunold       2008-07-23 09:57:41 +0000 397)         attributes.set("requirements", property_set.empty(), exact=True) -49c03622 (jhunold       2008-07-23 09:57:41 +0000 398)         attributes.set("usage-requirements", property_set.empty(), exact=True) -49c03622 (jhunold       2008-07-23 09:57:41 +0000 399)         attributes.set("default-build", [], exact=True) -49c03622 (jhunold       2008-07-23 09:57:41 +0000 400)         attributes.set("projects-to-build", [], exact=True) -49c03622 (jhunold       2008-07-23 09:57:41 +0000 401)         attributes.set("project-root", None, exact=True) -49c03622 (jhunold       2008-07-23 09:57:41 +0000 402)         attributes.set("build-dir", None, exact=True) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 403)          -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 404)         self.project_rules_.init_project(module_name) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 405)  -49c03622 (jhunold       2008-07-23 09:57:41 +0000 406)         jamroot = False -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 407)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 408)         parent_module = None; -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 409)         if module_name == "site-config": -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 410)             # No parent -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 411)             pass -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 412)         elif module_name == "user-config": -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 413)             parent_module = "site-config" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 414)         elif location and not self.is_jamroot(basename): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 415)             # We search for parent/project-root only if jamfile was specified  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 416)             # --- i.e -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 417)             # if the project is not standalone. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 418)             parent_module = self.load_parent(location) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 419)         else: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 420)             # It's either jamroot, or standalone project. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 421)             # If it's jamroot, inherit from user-config. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 422)             if location: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 423)                 parent_module = "user-config" ;                 -49c03622 (jhunold       2008-07-23 09:57:41 +0000 424)                 jamroot = True ; -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 425)                  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 426)         if parent_module: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 427)             self.inherit_attributes(module_name, parent_module) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 428)             attributes.set("parent-module", parent_module, exact=1) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 429)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 430)         if jamroot: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 431)             attributes.set("project-root", location, exact=1) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 432)                                  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 433)         parent = None -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 434)         if parent_module: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 435)             parent = self.target(parent_module) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 436)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 437)         if not self.module2target.has_key(module_name): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 438)             target = b2.build.targets.ProjectTarget(self.manager, -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 439)                 module_name, module_name, parent, -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 440)                 self.attribute(module_name,"requirements"), -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 441)                 # FIXME: why we need to pass this? It's not -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 442)                 # passed in jam code. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 443)                 self.attribute(module_name, "default-build")) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 444)             self.module2target[module_name] = target -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 445)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 446)         self.current_project = self.target(module_name) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 447)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 448)     def inherit_attributes(self, project_module, parent_module): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 449)         """Make 'project-module' inherit attributes of project -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 450)         root and parent module.""" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 451)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 452)         attributes = self.module2attributes[project_module] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 453)         pattributes = self.module2attributes[parent_module] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 454)          -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 455)         # Parent module might be locationless user-config. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 456)         # FIXME: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 457)         #if [ modules.binding $(parent-module) ] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 458)         #{         -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 459)         #    $(attributes).set parent : [ path.parent  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 460)         #                                 [ path.make [ modules.binding $(parent-module) ] ] ] ; -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 461)         #    } -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 462)          -49c03622 (jhunold       2008-07-23 09:57:41 +0000 463)         attributes.set("project-root", pattributes.get("project-root"), exact=True) -49c03622 (jhunold       2008-07-23 09:57:41 +0000 464)         attributes.set("default-build", pattributes.get("default-build"), exact=True) -49c03622 (jhunold       2008-07-23 09:57:41 +0000 465)         attributes.set("requirements", pattributes.get("requirements"), exact=True) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 466)         attributes.set("usage-requirements", -cde6f09a (vladimir_prus 2007-10-19 23:12:33 +0000 467)                        pattributes.get("usage-requirements"), exact=1) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 468)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 469)         parent_build_dir = pattributes.get("build-dir") -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 470)          -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 471)         if parent_build_dir: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 472)         # Have to compute relative path from parent dir to our dir -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 473)         # Convert both paths to absolute, since we cannot -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 474)         # find relative path from ".." to "." -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 475)  -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 476)              location = attributes.get("location") -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 477)              parent_location = pattributes.get("location") -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 478)  -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 479)              our_dir = os.path.join(os.getcwd(), location) -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 480)              parent_dir = os.path.join(os.getcwd(), parent_location) -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 481)  -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 482)              build_dir = os.path.join(parent_build_dir, -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 483)                                       b2.util.path.relpath(parent_dir, -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 484)                                                                     our_dir)) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 485)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 486)     def register_id(self, id, module): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 487)         """Associate the given id with the given project module.""" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 488)         self.id2module[id] = module -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 489)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 490)     def current(self): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 491)         """Returns the project which is currently being loaded.""" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 492)         return self.current_project -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 493)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 494)     def push_current(self, project): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 495)         """Temporary changes the current project to 'project'. Should -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 496)         be followed by 'pop-current'.""" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 497)         self.saved_current_project.append(self.current_project) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 498)         self.current_project = project -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 499)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 500)     def pop_current(self): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 501)         self.current_project = self.saved_current_project[-1] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 502)         del self.saved_current_project[-1] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 503)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 504)     def attributes(self, project): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 505)         """Returns the project-attribute instance for the -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 506)         specified jamfile module.""" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 507)         return self.module2attributes[project] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 508)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 509)     def attribute(self, project, attribute): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 510)         """Returns the value of the specified attribute in the -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 511)         specified jamfile module.""" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 512)         return self.module2attributes[project].get(attribute) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 513)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 514)     def target(self, project_module): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 515)         """Returns the project target corresponding to the 'project-module'.""" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 516)         if not self.module2target[project_module]: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 517)             self.module2target[project_module] = \ -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 518)                 ProjectTarget(project_module, project_module, -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 519)                               self.attribute(project_module, "requirements")) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 520)          -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 521)         return self.module2target[project_module] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 522)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 523)     def use(self, id, location): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 524)         # Use/load a project. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 525)         saved_project = self.current_project -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 526)         project_module = self.load(location) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 527)         declared_id = self.attribute(project_module, "id") -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 528)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 529)         if not declared_id or declared_id != id: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 530)             # The project at 'location' either have no id or -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 531)             # that id is not equal to the 'id' parameter. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 532)             if self.id2module[id] and self.id2module[id] != project_module: -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 533)                 self.manager.errors()( -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 534) """Attempt to redeclare already existing project id '%s'""" % id) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 535)             self.id2module[id] = project_module -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 536)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 537)         self.current_module = saved_project -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 538)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 539)     def add_rule(self, name, callable): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 540)         """Makes rule 'name' available to all subsequently loaded Jamfiles. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 541)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 542)         Calling that rule wil relay to 'callable'.""" -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 543)         self.project_rules_.add_rule(name, callable) -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 544)  -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 545)     def project_rules(self): -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 546)         return self.project_rules_ -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 547)  -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 548)     def glob_internal(self, project, wildcards, excludes, rule_name): -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 549)         location = project.get("source-location") -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 550)  -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 551)         result = [] -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 552)         callable = b2.util.path.__dict__[rule_name] -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 553)          -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 554)         paths = callable(location, wildcards, excludes) -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 555)         has_dir = 0 -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 556)         for w in wildcards: -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 557)             if os.path.dirname(w): -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 558)                 has_dir = 1 -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 559)                 break -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 560)  -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 561)         if has_dir or rule_name != "glob": -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 562)             # The paths we've found are relative to current directory, -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 563)             # but the names specified in sources list are assumed to -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 564)             # be relative to source directory of the corresponding -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 565)             # prject. So, just make the name absolute. -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 566)             result = [os.path.join(os.getcwd(), p) for p in paths] -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 567)         else: -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 568)             # There were not directory in wildcard, so the files are all -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 569)             # in the source directory of the project. Just drop the -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 570)             # directory, instead of making paths absolute. -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 571)             result = [os.path.basename(p) for p in paths] -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 572)              -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 573)         return result -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 574)  -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 575)     def load_module(self, name, extra_path=None): -53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 576)         """Classic Boost.Build 'modules' are in fact global variables. -53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 577)         Therefore, try to find an already loaded Python module called 'name' in sys.modules.  -53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 578)         If the module ist not loaded, find it Boost.Build search -53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 579)         path and load it.  The new module is not entered in sys.modules. -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 580)         The motivation here is to have disjoint namespace of modules -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 581)         loaded via 'import/using' in Jamfile, and ordinary Python -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 582)         modules. We don't want 'using foo' in Jamfile to load ordinary -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 583)         Python module 'foo' which is going to not work. And we -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 584)         also don't want 'import foo' in regular Python module to -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 585)         accidentally grab module named foo that is internal to -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 586)         Boost.Build and intended to provide interface to Jamfiles.""" -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 587)  -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 588)         existing = self.loaded_tool_modules_.get(name) -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 589)         if existing: -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 590)             return existing -53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 591)  -53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 592)         modules = sys.modules -53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 593)         for class_name in modules: -53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 594)             if name in class_name: -53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 595)                 module = modules[class_name] -53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 596)                 self.loaded_tool_modules_[name] = module -53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 597)                 return module -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 598)          -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 599)         path = extra_path -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 600)         if not path: -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 601)             path = [] -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 602)         path.extend(self.manager.b2.path()) -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 603)         location = None -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 604)         for p in path: -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 605)             l = os.path.join(p, name + ".py") -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 606)             if os.path.exists(l): -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 607)                 location = l -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 608)                 break -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 609)  -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 610)         if not location: -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 611)             self.manager.errors()("Cannot find module '%s'" % name) -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 612)  -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 613)         mname = "__build_build_temporary__" -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 614)         file = open(location) -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 615)         try: -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 616)             # TODO: this means we'll never make use of .pyc module, -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 617)             # which might be a problem, or not. -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 618)             module = imp.load_module(mname, file, os.path.basename(location), -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 619)                                      (".py", "r", imp.PY_SOURCE)) -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 620)             del sys.modules[mname] -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 621)             self.loaded_tool_modules_[name] = module -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 622)             return module -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 623)         finally: -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 624)             file.close() -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 625)          -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 626)  -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 627)  -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 628) # FIXME: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 629) # Defines a Boost.Build extension project. Such extensions usually -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 630) # contain library targets and features that can be used by many people. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 631) # Even though extensions are really projects, they can be initialize as -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 632) # a module would be with the "using" (project.project-rules.using) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 633) # mechanism. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 634) #rule extension ( id : options * : * ) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 635) #{ -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 636) #    # The caller is a standalone module for the extension. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 637) #    local mod = [ CALLER_MODULE ] ; -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 638) #     -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 639) #    # We need to do the rest within the extension module. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 640) #    module $(mod) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 641) #    { -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 642) #        import path ; -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 643) #         -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 644) #        # Find the root project. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 645) #        local root-project = [ project.current ] ; -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 646) #        root-project = [ $(root-project).project-module ] ; -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 647) #        while -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 648) #            [ project.attribute $(root-project) parent-module ] && -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 649) #            [ project.attribute $(root-project) parent-module ] != user-config -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 650) #        { -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 651) #            root-project = [ project.attribute $(root-project) parent-module ] ; -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 652) #        } -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 653) #         -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 654) #        # Create the project data, and bring in the project rules -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 655) #        # into the module. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 656) #        project.initialize $(__name__) : -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 657) #            [ path.join [ project.attribute $(root-project) location ] ext $(1:L) ] ; -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 658) #         -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 659) #        # Create the project itself, i.e. the attributes. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 660) #        # All extensions are created in the "/ext" project space. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 661) #        project /ext/$(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ; -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 662) #        local attributes = [ project.attributes $(__name__) ] ; -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 663) #         -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 664) #        # Inherit from the root project of whomever is defining us. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 665) #        project.inherit-attributes $(__name__) : $(root-project) ; -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 666) #        $(attributes).set parent-module : $(root-project) : exact ; -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 667) #    } -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 668) #} -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 669)          -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 670)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 671) class ProjectAttributes: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 672)     """Class keeping all the attributes of a project. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 673)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 674)     The standard attributes are 'id', "location", "project-root", "parent" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 675)     "requirements", "default-build", "source-location" and "projects-to-build". -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 676)     """ -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 677)          -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 678)     def __init__(self, manager, location, project_module): -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 679)         self.manager = manager -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 680)         self.location = location -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 681)         self.project_module = project_module -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 682)         self.attributes = {} -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 683)         self.usage_requirements = None -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 684)          -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 685)     def set(self, attribute, specification, exact): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 686)         """Set the named attribute from the specification given by the user. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 687)         The value actually set may be different.""" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 688)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 689)         if exact: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 690)             self.__dict__[attribute] = specification -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 691)              -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 692)         elif attribute == "requirements": -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 693)             self.requirements = property_set.refine_from_user_input( -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 694)                 self.requirements, specification, -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 695)                 self.project_module, self.location) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 696)              -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 697)         elif attribute == "usage-requirements": -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 698)             unconditional = [] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 699)             for p in specification: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 700)                 split = property.split_conditional(p) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 701)                 if split: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 702)                     unconditional.append(split[1]) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 703)                 else: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 704)                     unconditional.append(p) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 705)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 706)             non_free = property.remove("free", unconditional) -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 707)             if non_free:                 -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 708)                 pass -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 709)                 # FIXME: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 710)                 #errors.error "usage-requirements" $(specification) "have non-free properties" $(non-free) ; -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 711)  -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 712)             t = property.translate_paths(specification, self.location) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 713)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 714)             existing = self.__dict__.get("usage-requirements") -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 715)             if existing: -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 716)                 new = property_set.create(existing.raw() +  t) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 717)             else: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 718)                 new = property_set.create(t) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 719)             self.__dict__["usage-requirements"] = new -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 720)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 721)                  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 722)         elif attribute == "default-build": -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 723)             self.__dict__["default-build"] = property_set.create(specification) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 724)              -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 725)         elif attribute == "source-location": -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 726)             source_location = [] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 727)             for path in specification: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 728)                 source_location += os.path.join(self.location, path) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 729)             self.__dict__["source-location"] = source_location -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 730)                  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 731)         elif attribute == "build-dir": -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 732)             self.__dict__["build-dir"] = os.path.join(self.location, specification) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 733)                   -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 734)         elif not attribute in ["id", "default-build", "location", -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 735)                                "source-location", "parent", -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 736)                                "projects-to-build", "project-root"]: -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 737)             self.manager.errors()( -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 738) """Invalid project attribute '%s' specified -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 739) for project at '%s'""" % (attribute, self.location)) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 740)         else: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 741)             self.__dict__[attribute] = specification -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 742)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 743)     def get(self, attribute): -cde6f09a (vladimir_prus 2007-10-19 23:12:33 +0000 744)         return self.__dict__[attribute] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 745)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 746)     def dump(self): -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 747)         """Prints the project attributes.""" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 748)         id = self.get("id") -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 749)         if not id: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 750)             id = "(none)" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 751)         else: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 752)             id = id[0] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 753)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 754)         parent = self.get("parent") -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 755)         if not parent: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 756)             parent = "(none)" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 757)         else: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 758)             parent = parent[0] -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 759)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 760)         print "'%s'" % id -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 761)         print "Parent project:%s", parent -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 762)         print "Requirements:%s", self.get("requirements") -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 763)         print "Default build:%s", string.join(self.get("debuild-build")) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 764)         print "Source location:%s", string.join(self.get("source-location")) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 765)         print "Projects to build:%s", string.join(self.get("projects-to-build").sort()); -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 766)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 767) class ProjectRules: -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 768)     """Class keeping all rules that are made available to Jamfile.""" -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 769)  -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 770)     def __init__(self, registry): -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 771)         self.registry = registry -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 772)         self.manager_ = registry.manager -38d984eb (vladimir_prus 2007-10-13 17:52:25 +0000 773)         self.rules = {} -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 774)         self.local_names = [x for x in self.__class__.__dict__ -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 775)                             if x not in ["__init__", "init_project", "add_rule", -7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 776)                                          "error_reporting_wrapper", "add_rule_for_type"]] -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 777)         self.all_names_ = [x for x in self.local_names] -7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 778)  -7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 779)     def add_rule_for_type(self, type): -7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 780)         rule_name = type.lower(); -7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 781)  -7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 782)         def xpto (name, sources, requirements = [], default_build = None, usage_requirements = []): -7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 783)             return self.manager_.targets().create_typed_target( -7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 784)                 type, self.registry.current(), name[0], sources, -7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 785)                 requirements, default_build, usage_requirements)  -7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 786)  -7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 787)         self.add_rule(type.lower(), xpto) -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 788)      -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 789)     def add_rule(self, name, callable): -38d984eb (vladimir_prus 2007-10-13 17:52:25 +0000 790)         self.rules[name] = callable -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 791)         self.all_names_.append(name) -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 792)  -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 793)     def all_names(self): -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 794)         return self.all_names_ -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 795)  -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 796)     def call_and_report_errors(self, callable, *args): -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 797)         result = None -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 798)         try: -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 799)             self.manager_.errors().push_jamfile_context() -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 800)             result = callable(*args) -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 801)         except ExceptionWithUserContext, e: -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 802)             e.report() -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 803)         except Exception, e: -7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 804)             try: -7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 805)                 self.manager_.errors().handle_stray_exception (e) -7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 806)             except ExceptionWithUserContext, e: -7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 807)                 e.report() -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 808)         finally:                 -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 809)             self.manager_.errors().pop_jamfile_context() -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 810)                                          -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 811)         return result -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 812)  -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 813)     def make_wrapper(self, callable): -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 814)         """Given a free-standing function 'callable', return a new -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 815)         callable that will call 'callable' and report all exceptins, -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 816)         using 'call_and_report_errors'.""" -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 817)         def wrapper(*args): -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 818)             self.call_and_report_errors(callable, *args) -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 819)         return wrapper -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 820)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 821)     def init_project(self, project_module): -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 822)  -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 823)         for n in self.local_names:             -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 824)             # Using 'getattr' here gives us a bound method, -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 825)             # while using self.__dict__[r] would give unbound one. -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 826)             v = getattr(self, n) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 827)             if callable(v): -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 828)                 if n == "import_": -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 829)                     n = "import" -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 830)                 else: -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 831)                     n = string.replace(n, "_", "-") -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 832)                      -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 833)                 bjam.import_rule(project_module, n, -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 834)                                  self.make_wrapper(v)) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 835)  -38d984eb (vladimir_prus 2007-10-13 17:52:25 +0000 836)         for n in self.rules: -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 837)             bjam.import_rule(project_module, n, -0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 838)                              self.make_wrapper(self.rules[n])) -38d984eb (vladimir_prus 2007-10-13 17:52:25 +0000 839)  -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 840)     def project(self, *args): -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 841)  -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 842)         jamfile_module = self.registry.current().project_module() -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 843)         attributes = self.registry.attributes(jamfile_module) -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 844)          -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 845)         id = None -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 846)         if args and args[0]: -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 847)             id = args[0][0] -092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 848)             args = args[1:] -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 849)  -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 850)         if id: -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 851)             if id[0] != '/': -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 852)                 id = '/' + id -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 853)             self.registry.register_id (id, jamfile_module) -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 854)  -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 855)         explicit_build_dir = None -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 856)         for a in args: -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 857)             if a: -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 858)                 attributes.set(a[0], a[1:], exact=0) -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 859)                 if a[0] == "build-dir": -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 860)                     explicit_build_dir = a[1] -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 861)          -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 862)         # If '--build-dir' is specified, change the build dir for the project. -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 863)         if self.registry.global_build_dir: -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 864)  -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 865)             location = attributes.get("location") -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 866)             # Project with empty location is 'standalone' project, like -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 867)             # user-config, or qt.  It has no build dir. -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 868)             # If we try to set build dir for user-config, we'll then -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 869)             # try to inherit it, with either weird, or wrong consequences. -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 870)             if location and location == attributes.get("project-root"): -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 871)                 # This is Jamroot. -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 872)                 if id: -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 873)                     if explicit_build_dir and os.path.isabs(explicit_build_dir): -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 874)                         self.register.manager.errors()( -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 875) """Absolute directory specified via 'build-dir' project attribute -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 876) Don't know how to combine that with the --build-dir option.""") -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 877)  -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 878)                     rid = id -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 879)                     if rid[0] == '/': -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 880)                         rid = rid[1:] -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 881)  -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 882)                     p = os.path.join(self.registry.global_build_dir, -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 883)                                      rid, explicit_build_dir) -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 884)                     attributes.set("build-dir", p, exact=1) -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 885)             elif explicit_build_dir: -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 886)                 self.registry.manager.errors()( -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 887) """When --build-dir is specified, the 'build-project' -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 888) attribute is allowed only for top-level 'project' invocations""") -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 889)  -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 890)     def constant(self, name, value): -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 891)         """Declare and set a project global constant. -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 892)         Project global constants are normal variables but should -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 893)         not be changed. They are applied to every child Jamfile.""" -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 894)         m = "Jamfile</home/ghost/Work/Boost/boost-svn/tools/build/v2_python/python/tests/bjam/make>" -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 895)         self.registry.current().add_constant(name[0], value) -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 896)  -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 897)     def path_constant(self, name, value): -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 898)         """Declare and set a project global constant, whose value is a path. The -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 899)         path is adjusted to be relative to the invocation directory. The given -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 900)         value path is taken to be either absolute, or relative to this project -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 901)         root.""" -0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 902)         self.registry.current().add_constant(name[0], value, path=1) -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 903)  -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 904)     def use_project(self, id, where): -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 905)         # See comment in 'load' for explanation why we record the -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 906)         # parameters as opposed to loading the project now. -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 907)         m = self.registry.current().project_module(); -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 908)         self.registry.used_projects[m].append((id, where)) -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 909)          -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 910)     def build_project(self, dir): -1674e2d9 (jhunold       2008-08-08 19:52:05 +0000 911)         assert(isinstance(dir, list)) -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 912)         jamfile_module = self.registry.current().project_module() -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 913)         attributes = self.registry.attributes(jamfile_module) -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 914)         now = attributes.get("projects-to-build") -1674e2d9 (jhunold       2008-08-08 19:52:05 +0000 915)         attributes.set("projects-to-build", now + dir, exact=True) -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 916)  -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 917)     def explicit(self, target_names): -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 918)         t = self.registry.current() -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 919)         for n in target_names: -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 920)             t.mark_target_as_explicit(n) -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 921)  -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 922)     def glob(self, wildcards, excludes=None): -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 923)         return self.registry.glob_internal(self.registry.current(), -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 924)                                            wildcards, excludes, "glob") -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 925)  -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 926)     def glob_tree(self, wildcards, excludes=None): -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 927)         bad = 0 -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 928)         for p in wildcards: -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 929)             if os.path.dirname(p): -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 930)                 bad = 1 -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 931)  -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 932)         if excludes: -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 933)             for p in excludes: -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 934)                 if os.path.dirname(p): -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 935)                     bad = 1 -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 936)  -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 937)         if bad: -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 938)             self.registry.manager().errors()( -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 939) "The patterns to 'glob-tree' may not include directory") -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 940)         return self.registry.glob_internal(self.registry.current(), -2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 941)                                            wildcards, excludes, "glob_tree") -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 942)      -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 943)  -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 944)     def using(self, toolset, *args): -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 945)         # The module referred by 'using' can be placed in -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 946)         # the same directory as Jamfile, and the user -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 947)         # will expect the module to be found even though -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 948)         # the directory is not in BOOST_BUILD_PATH. -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 949)         # So temporary change the search path. -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 950)         jamfile_module = self.registry.current().project_module() -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 951)         attributes = self.registry.attributes(jamfile_module) -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 952)         location = attributes.get("location") -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 953)  -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 954)         m = self.registry.load_module(toolset[0], [location]) -7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 955)         if not m.__dict__.has_key("init"): -7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 956)             self.registry.manager.errors()( -7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 957)                 "Tool module '%s' does not define the 'init' method" % toolset[0]) -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 958)         m.init(*args) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 959)  -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 960)  -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 961)     def import_(self, name, names_to_import=None, local_names=None): -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 962)  -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 963)         name = name[0] -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 964)         jamfile_module = self.registry.current().project_module() -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 965)         attributes = self.registry.attributes(jamfile_module) -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 966)         location = attributes.get("location") -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 967)  -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 968)         m = self.registry.load_module(name, [location]) -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 969)  -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 970)         for f in m.__dict__: -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 971)             v = m.__dict__[f] -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 972)             if callable(v): -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 973)                 bjam.import_rule(jamfile_module, name + "." + f, v) -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 974)  -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 975)         if names_to_import: -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 976)             if not local_names: -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 977)                 local_names = names_to_import -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 978)  -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 979)             if len(names_to_import) != len(local_names): -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 980)                 self.registry.manager.errors()( -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 981) """The number of names to import and local names do not match.""") -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 982)  -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 983)             for n, l in zip(names_to_import, local_names): -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 984)                 bjam.import_rule(jamfile_module, l, m.__dict__[n]) -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 985)          -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 986)     def conditional(self, condition, requirements): -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 987)         """Calculates conditional requirements for multiple requirements -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 988)         at once. This is a shorthand to be reduce duplication and to -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 989)         keep an inline declarative syntax. For example: -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 990)  -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 991)             lib x : x.cpp : [ conditional <toolset>gcc <variant>debug : -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 992)                 <define>DEBUG_EXCEPTION <define>DEBUG_TRACE ] ; -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 993)         """ -f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 994)  -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 995)         c = string.join(condition, ",") -f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 996)         return [c + ":" + r for r in requirements] diff --git a/jam-files/boost-build/build/project.jam b/jam-files/boost-build/build/project.jam deleted file mode 100644 index c9967613..00000000 --- a/jam-files/boost-build/build/project.jam +++ /dev/null @@ -1,1110 +0,0 @@ -# Copyright 2002, 2003 Dave Abrahams -# Copyright 2002, 2005, 2006 Rene Rivera -# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - -# Implements project representation and loading. Each project is represented by: -#  - a module where all the Jamfile content live. -#  - an instance of 'project-attributes' class. -#    (given a module name, can be obtained using the 'attributes' rule) -#  - an instance of 'project-target' class (from targets.jam) -#    (given a module name, can be obtained using the 'target' rule) -# -# Typically, projects are created as result of loading a Jamfile, which is done -# by rules 'load' and 'initialize', below. First, module for Jamfile is loaded -# and new project-attributes instance is created. Some rules necessary for -# project are added to the module (see 'project-rules' module) at the bottom of -# this file. Default project attributes are set (inheriting attributes of parent -# project, if it exists). After that the Jamfile is read. It can declare its own -# attributes using the 'project' rule which will be combined with any already -# set attributes. -# -# The 'project' rule can also declare a project id which will be associated with -# the project module. -# -# There can also be 'standalone' projects. They are created by calling -# 'initialize' on an arbitrary module and not specifying their location. After -# the call, the module can call the 'project' rule, declare main targets and -# behave as a regular project except that, since it is not associated with any -# location, it should not declare targets that are not prebuilt. -# -# The list of all loaded Jamfile is stored in the .project-locations variable. -# It is possible to obtain a module name for a location using the 'module-name' -# rule. Standalone projects are not recorded and can only be referenced using -# their project id. - -import "class" : new ; -import errors ; -import modules ; -import path ; -import print ; -import property-set ; -import sequence ; - - -# Loads the Jamfile at the given location. After loading, project global file -# and Jamfiles needed by the requested one will be loaded recursively. If the -# Jamfile at that location is loaded already, does nothing. Returns the project -# module for the Jamfile. -# -rule load ( jamfile-location ) -{ -    if --debug-loading in [ modules.peek : ARGV ] -    { -        ECHO "Loading Jamfile at" '$(jamfile-location)' ; -    } - -    local module-name = [ module-name $(jamfile-location) ] ; -    # If Jamfile is already loaded, don't try again. -    if ! $(module-name) in $(.jamfile-modules) -    { -        load-jamfile $(jamfile-location) : $(module-name) ; - -        # We want to make sure that child project are loaded only after parent -        # projects. In particular, because parent projects define attributes -        # which are inherited by children, and we don't want children to be -        # loaded before parent has defined everything. -        # -        # While "build-project" and "use-project" can potentially refer to child -        # projects from parent projects, we don't immediately load child -        # projects when seeing those attributes. Instead, we record the minimal -        # information to be used only later. -        load-used-projects $(module-name) ; -    } -    return $(module-name) ; -} - - -rule load-used-projects ( module-name ) -{ -    local used = [ modules.peek $(module-name) : .used-projects ] ; -    local location = [ attribute $(module-name) location ] ; -    import project ; -    while $(used) -    { -        local id = $(used[1]) ; -        local where = $(used[2]) ; - -        project.use $(id) : [ path.root [ path.make $(where) ] $(location) ] ; -        used = $(used[3-]) ; -    } -} - - -# Note the use of character groups, as opposed to listing 'Jamroot' and -# 'jamroot'. With the latter, we would get duplicate matches on Windows and -# would have to eliminate duplicates. -JAMROOT ?= [ modules.peek : JAMROOT ] ; -JAMROOT ?= project-root.jam [Jj]amroot [Jj]amroot.jam ; - - -# Loads parent of Jamfile at 'location'. Issues an error if nothing is found. -# -rule load-parent ( location ) -{ -    local found = [ path.glob-in-parents $(location) : $(JAMROOT) $(JAMFILE) ] ; - -    if ! $(found) -    { -        ECHO error: Could not find parent for project at '$(location)' ; -        EXIT error: Did not find Jamfile.jam or Jamroot.jam in any parent -            directory. ; -    } - -    return [ load $(found[1]:D) ] ; -} - - -# Makes the specified 'module' act as if it were a regularly loaded Jamfile at -# 'location'. Reports an error if a Jamfile has already been loaded for that -# location. -# -rule act-as-jamfile ( module : location ) -{ -    if [ module-name $(location) ] in $(.jamfile-modules) -    { -        errors.error "Jamfile was already loaded for '$(location)'" ; -    } -    # Set up non-default mapping from location to module. -    .module.$(location) = $(module) ; - -    # Add the location to the list of project locations so that we don't try to -    # reload the same Jamfile in the future. -    .jamfile-modules += [ module-name $(location) ] ; - -    initialize $(module) : $(location) ; -} - - -# Returns the project module corresponding to the given project-id or plain -# directory name. Returns nothing if such a project can not be found. -# -rule find ( name : current-location ) -{ -    local project-module ; - -    # Try interpreting name as project id. -    if [ path.is-rooted $(name) ] -    { -        project-module = $($(name).jamfile-module) ; -    } - -    if ! $(project-module) -    { -        local location = [ path.root [ path.make $(name) ] $(current-location) ] -            ; - -        # If no project is registered for the given location, try to load it. -        # First see if we have a Jamfile. If not, then see if we might have a -        # project root willing to act as a Jamfile. In that case, project root -        # must be placed in the directory referred by id. - -        project-module = [ module-name $(location) ] ; -        if ! $(project-module) in $(.jamfile-modules) -        { -            if [ path.glob $(location) : $(JAMROOT) $(JAMFILE) ] -            { -                project-module = [ load $(location) ] ; -            } -            else -            { -                project-module = ; -            } -        } -    } - -    return $(project-module) ; -} - - -# Returns the name of the module corresponding to 'jamfile-location'. If no -# module corresponds to that location yet, associates the default module name -# with that location. -# -rule module-name ( jamfile-location ) -{ -    if ! $(.module.$(jamfile-location)) -    { -        # Root the path, so that locations are always unambiguous. Without this, -        # we can't decide if '../../exe/program1' and '.' are the same paths. -        jamfile-location = [ path.root $(jamfile-location) [ path.pwd ] ] ; -        .module.$(jamfile-location) = Jamfile<$(jamfile-location)> ; -    } -    return $(.module.$(jamfile-location)) ; -} - - -# Default patterns to search for the Jamfiles to use for build declarations. -# -JAMFILE = [ modules.peek : JAMFILE ] ; -JAMFILE ?= [Bb]uild.jam [Jj]amfile.v2 [Jj]amfile [Jj]amfile.jam ; - - -# Find the Jamfile at the given location. This returns the exact names of all -# the Jamfiles in the given directory. The optional parent-root argument causes -# this to search not the given directory but the ones above it up to the -# directory given in it. -# -rule find-jamfile ( -    dir # The directory(s) to look for a Jamfile. -    parent-root ? # Optional flag indicating to search for the parent Jamfile. -    : no-errors ? -    ) -{ -    # Glob for all the possible Jamfiles according to the match pattern. -    # -    local jamfile-glob = ; -    if $(parent-root) -    { -        if ! $(.parent-jamfile.$(dir)) -        { -            .parent-jamfile.$(dir) = [ path.glob-in-parents $(dir) : $(JAMFILE) -                ] ; -        } -        jamfile-glob = $(.parent-jamfile.$(dir)) ; -    } -    else -    { -        if ! $(.jamfile.$(dir)) -        { -            .jamfile.$(dir) = [ path.glob $(dir) : $(JAMFILE) ] ; -        } -        jamfile-glob = $(.jamfile.$(dir)) ; - -    } - -    local jamfile-to-load = $(jamfile-glob) ; -    # Multiple Jamfiles found in the same place. Warn about this and ensure we -    # use only one of them. As a temporary convenience measure, if there is -    # Jamfile.v2 among found files, suppress the warning and use it. -    # -    if $(jamfile-to-load[2-]) -    { -        local v2-jamfiles = [ MATCH (.*[Jj]amfile\\.v2)|(.*[Bb]uild\\.jam) : $(jamfile-to-load) ] ; - -        if $(v2-jamfiles) && ! $(v2-jamfiles[2]) -        { -            jamfile-to-load = $(v2-jamfiles) ; -        } -        else -        { -            local jamfile = [ path.basename $(jamfile-to-load[1]) ] ; -            ECHO "warning: Found multiple Jamfiles at '"$(dir)"'!" -                "Loading the first one: '$(jamfile)'." ; -        } - -        jamfile-to-load = $(jamfile-to-load[1]) ; -    } - -    # Could not find it, error. -    # -    if ! $(no-errors) && ! $(jamfile-to-load) -    { -        errors.error Unable to load Jamfile. -            : Could not find a Jamfile in directory '$(dir)'. -            : Attempted to find it with pattern '"$(JAMFILE:J=" ")"'. -            : Please consult the documentation at 'http://www.boost.org'. ; -    } - -    return $(jamfile-to-load) ; -} - - -# Load a Jamfile at the given directory. Returns nothing. Will attempt to load -# the file as indicated by the JAMFILE patterns. Effect of calling this rule -# twice with the same 'dir' is undefined. -# -local rule load-jamfile ( -    dir  # The directory of the project Jamfile. -    : jamfile-module -    ) -{ -    # See if the Jamfile is where it should be. -    # -    local jamfile-to-load = [ path.glob $(dir) : $(JAMROOT) ] ; -    if ! $(jamfile-to-load) -    { -        jamfile-to-load = [ find-jamfile $(dir) ] ; -    } -     -    if $(jamfile-to-load[2]) -    { -        errors.error "Multiple Jamfiles found at '$(dir)'"  -          :  "Filenames are: " $(jamfile-to-load:D=) ; -    } -     -    # Now load the Jamfile in it's own context.  -    # The call to 'initialize' may load parent Jamfile, which might have -    # 'use-project' statement that causes a second attempt to load the -    # same project we're loading now.  Checking inside .jamfile-modules -    # prevents that second attempt from messing up. -    if ! $(jamfile-module) in $(.jamfile-modules) -    { -        .jamfile-modules += $(jamfile-module) ; - -        # Initialize the Jamfile module before loading. -        # -        initialize $(jamfile-module) : [ path.parent $(jamfile-to-load) ] -            : $(jamfile-to-load:BS) ; - -        local saved-project = $(.current-project) ; - -        mark-as-user $(jamfile-module) ; -        modules.load $(jamfile-module) : [ path.native $(jamfile-to-load) ] : . ; -        if [ MATCH ($(JAMROOT)) : $(jamfile-to-load:BS) ] -        { -            jamfile = [ find-jamfile $(dir) : no-errors ] ; -            if $(jamfile) -            { -                load-aux $(jamfile-module) : [ path.native $(jamfile) ] ; -            } -        } - -    # Now do some checks. -    if $(.current-project) != $(saved-project) -    { -        errors.error "The value of the .current-project variable has magically" -            : "changed after loading a Jamfile. This means some of the targets" -            : "might be defined in the wrong project." -            : "after loading" $(jamfile-module) -            : "expected value" $(saved-project) -            : "actual value" $(.current-project) ; -    } - -    if $(.global-build-dir) -    { -        local id           = [ attribute $(jamfile-module) id           ] ; -        local project-root = [ attribute $(jamfile-module) project-root ] ; -        local location     = [ attribute $(jamfile-module) location     ] ; - -        if $(location) && $(project-root) = $(dir) -        { -            # This is Jamroot. -            if ! $(id) -            { -                ECHO "warning: the --build-dir option was specified" ; -                ECHO "warning: but Jamroot at '$(dir)'" ; -                ECHO "warning: specified no project id" ; -                ECHO "warning: the --build-dir option will be ignored" ; -            } -        } -    } -    } -} - - -rule mark-as-user ( module-name ) -{ -    if USER_MODULE in [ RULENAMES ] -    { -        USER_MODULE $(module-name) ; -    } -} - - -rule load-aux ( module-name : file ) -{ -    mark-as-user $(module-name) ; - -    module $(module-name) -    { -        include $(2) ; -        local rules = [ RULENAMES $(1) ] ; -        IMPORT $(1) : $(rules) : $(1) : $(1).$(rules) ; -    } -} - - -.global-build-dir = [ MATCH --build-dir=(.*) : [ modules.peek : ARGV ] ] ; -if $(.global-build-dir) -{ -    # If the option is specified several times, take the last value. -    .global-build-dir = [ path.make $(.global-build-dir[-1]) ] ; -} - - -# Initialize the module for a project. -# -rule initialize ( -    module-name   # The name of the project module. -    : location ?  # The location (directory) of the project to initialize. If -                  # not specified, a standalone project will be initialized. -    : basename ? -    ) -{ -    if --debug-loading in [ modules.peek : ARGV ] -    { -        ECHO "Initializing project '$(module-name)'" ; -    } - -    # TODO: need to consider if standalone projects can do anything but define -    # prebuilt targets. If so, we need to give it a more sensible "location", so -    # that source paths are correct. -    location ?= "" ; -    # Create the module for the Jamfile first. -    module $(module-name) -    { -    } -    $(module-name).attributes = [ new project-attributes $(location) -        $(module-name) ] ; -    local attributes = $($(module-name).attributes) ; - -    if $(location) -    { -        $(attributes).set source-location : [ path.make $(location) ] : exact ; -    } -    else if ! $(module-name) in test-config site-config user-config project-config -    { -        # This is a standalone project with known location. Set source location -        # so that it can declare targets. This is intended so that you can put -        # a .jam file in your sources and use it via 'using'. Standard modules -        # (in 'tools' subdir) may not assume source dir is set. -        local s = [ modules.binding $(module-name) ] ; -        if ! $(s) -        { -            errors.error "Could not determine project location $(module-name)" ; -        }         -        $(attributes).set source-location : $(s:D) : exact ; -    } - -    $(attributes).set requirements       : [ property-set.empty ] : exact ; -    $(attributes).set usage-requirements : [ property-set.empty ] : exact ; - -    # Import rules common to all project modules from project-rules module, -    # defined at the end of this file. -    local rules = [ RULENAMES project-rules ] ; -    IMPORT project-rules : $(rules) : $(module-name) : $(rules) ; - -    local jamroot ; - -    local parent-module ; -    if $(module-name) = test-config -    { -        # No parent. -    } -    else if $(module-name) = site-config -    { -        parent-module = test-config ; -    } -    else if $(module-name) = user-config -    { -        parent-module = site-config ; -    } -    else if $(module-name) = project-config -    { -        parent-module = user-config ; -    }     -    else -    { -        # We search for parent/project-root only if Jamfile was specified, i.e. -        # if the project is not standalone. -        if $(location) && ! [ MATCH ($(JAMROOT)) : $(basename) ] -        { -            parent-module = [ load-parent $(location) ] ; -        } -        else -        { -            # It's either jamroot or standalone project. If it's jamroot, -            # inherit from user-config. -            if $(location) -            { -                # If project-config module exist, inherit from it. -                if $(project-config.attributes) -                {    -                    parent-module = project-config ; -                } -                else -                {                     -                    parent-module = user-config ; -                }                 -                jamroot = true ; -            } -        } -    } - -    if $(parent-module) -    { -        inherit-attributes $(module-name) : $(parent-module) ; -        $(attributes).set parent-module : $(parent-module) : exact ; -    } - -    if $(jamroot) -    { -        $(attributes).set project-root : $(location) : exact ; -    } - -    local parent ; -    if $(parent-module) -    { -        parent = [ target $(parent-module) ] ; -    } - -    if ! $(.target.$(module-name)) -    { -        .target.$(module-name) = [ new project-target $(module-name) -            : $(module-name) $(parent) -            : [ attribute $(module-name) requirements ] ] ; - -        if --debug-loading in [ modules.peek : ARGV ] -        { -            ECHO "Assigned project target" $(.target.$(module-name)) -                "to '$(module-name)'" ; -        } -    } - -    .current-project = [ target $(module-name) ] ; -} - - -# Make 'project-module' inherit attributes of project root and parent module. -# -rule inherit-attributes ( project-module : parent-module ) -{ -    local attributes = $($(project-module).attributes) ; -    local pattributes = [ attributes $(parent-module) ] ; -    # Parent module might be locationless configuration module. -    if [ modules.binding $(parent-module) ] -    { -        $(attributes).set parent : [ path.parent -            [ path.make [ modules.binding $(parent-module) ] ] ] ; -    } -    local v = [ $(pattributes).get project-root ] ; -    $(attributes).set project-root : $(v) : exact ; -    $(attributes).set default-build -        : [ $(pattributes).get default-build ] ; -    $(attributes).set requirements -        : [ $(pattributes).get requirements ] : exact ; -    $(attributes).set usage-requirements -        : [ $(pattributes).get usage-requirements ] : exact ; - -    local parent-build-dir = [ $(pattributes).get build-dir ] ; -    if $(parent-build-dir) -    { -        # Have to compute relative path from parent dir to our dir. Convert both -        # paths to absolute, since we cannot find relative path from ".." to -        # ".". - -        local location = [ attribute $(project-module) location ] ; -        local parent-location = [ attribute $(parent-module) location ] ; - -        local pwd = [ path.pwd ] ; -        local parent-dir = [ path.root $(parent-location) $(pwd) ] ; -        local our-dir = [ path.root $(location) $(pwd) ] ; -        $(attributes).set build-dir : [ path.join $(parent-build-dir) -            [ path.relative $(our-dir) $(parent-dir) ] ] : exact ; -    } -} - - -# Associate the given id with the given project module. -# -rule register-id ( id : module ) -{ -    $(id).jamfile-module = $(module) ; -} - - -# Class keeping all the attributes of a project. -# -# The standard attributes are "id", "location", "project-root", "parent" -# "requirements", "default-build", "source-location" and "projects-to-build". -# -class project-attributes -{ -    import property ; -    import property-set ; -    import errors ; -    import path ; -    import print ; -    import sequence ; -    import project ; - -    rule __init__ ( location project-module ) -    { -        self.location = $(location) ; -        self.project-module = $(project-module) ; -    } - -    # Set the named attribute from the specification given by the user. The -    # value actually set may be different. -    # -    rule set ( attribute : specification * -        : exact ?  # Sets value from 'specification' without any processing. -        ) -    { -        if $(exact) -        { -            self.$(attribute) = $(specification) ; -        } -        else if $(attribute) = "requirements" -        { -            local result = [ property-set.refine-from-user-input -                $(self.requirements) : $(specification) -                : $(self.project-module) : $(self.location) ] ; - -            if $(result[1]) = "@error" -            { -                errors.error Requirements for project at '$(self.location)' -                    conflict with parent's. : Explanation: $(result[2-]) ; -            } -            else -            { -                self.requirements = $(result) ; -            } -        } -        else if $(attribute) = "usage-requirements" -        { -            local unconditional ; -            for local p in $(specification) -            { -                local split = [ property.split-conditional $(p) ] ; -                split ?= nothing $(p) ; -                unconditional += $(split[2]) ; -            } - -            local non-free = [ property.remove free : $(unconditional) ] ; -            if $(non-free) -            { -                errors.error usage-requirements $(specification) have non-free -                    properties $(non-free) ; -            } -            local t = [ property.translate-paths $(specification) -                                      : $(self.location) ] ; -            if $(self.usage-requirements) -            { -                self.usage-requirements = [ property-set.create -                    [ $(self.usage-requirements).raw ] $(t) ] ; -            } -            else -            { -                self.usage-requirements = [ property-set.create $(t) ] ; -            } -        } -        else if $(attribute) = "default-build" -        { -            self.default-build = [ property.make $(specification) ] ; -        } -        else if $(attribute) = "source-location" -        { -            self.source-location = ; -            for local src-path in $(specification) -            { -                self.source-location += [ path.root [ path.make $(src-path) ] -                    $(self.location) ] ; -            } -        } -        else if $(attribute) = "build-dir" -        { -            self.build-dir = [ path.root -                [ path.make $(specification) ] $(self.location) ] ; -        } -        else if $(attribute) = "id" -        { -            id = [ path.root $(specification) / ] ; -            project.register-id $(id) : $(self.project-module) ; -            self.id = $(id) ; -        } -        else if ! $(attribute) in "default-build" "location" "parent" -            "projects-to-build" "project-root" "source-location" -        { -            errors.error Invalid project attribute '$(attribute)' specified for -                project at '$(self.location)' ; -        } -        else -        { -            self.$(attribute) = $(specification) ; -        } -    } - -    # Returns the value of the given attribute. -    # -    rule get ( attribute ) -    { -        return $(self.$(attribute)) ; -    } - -    # Prints the project attributes. -    # -    rule print ( ) -    { -        local id = $(self.id) ; id ?= (none) ; -        local parent = $(self.parent) ; parent ?= (none) ; -        print.section "'"$(id)"'" ; -        print.list-start ; -        print.list-item "Parent project:" $(parent) ; -        print.list-item "Requirements:" [ $(self.requirements).raw ] ; -        print.list-item "Default build:" $(self.default-build) ; -        print.list-item "Source location:" $(self.source-location) ; -        print.list-item "Projects to build:" -                        [ sequence.insertion-sort $(self.projects-to-build) ] ; -        print.list-end ; -    } -} - - -# Returns the project which is currently being loaded. -# -rule current ( ) -{ -    return $(.current-project) ; -} - - -# Temporarily changes the current project to 'project'. Should be followed by -# 'pop-current'. -# -rule push-current ( project ) -{ -    .saved-current-project += $(.current-project) ; -    .current-project = $(project) ; -} - - -rule pop-current ( ) -{ -    .current-project = $(.saved-current-project[-1]) ; -    .saved-current-project = $(.saved-current-project[1--2]) ; -} - - -# Returns the project-attribute instance for the specified Jamfile module. -# -rule attributes ( project ) -{ -    return $($(project).attributes) ; -} - - -# Returns the value of the specified attribute in the specified Jamfile module. -# -rule attribute ( project attribute ) -{ -    return [ $($(project).attributes).get $(attribute) ] ; -} - - -# Returns the project target corresponding to the 'project-module'. -# -rule target ( project-module ) -{ -    if ! $(.target.$(project-module)) -    { -        .target.$(project-module) = [ new project-target $(project-module) -            : $(project-module) -            : [ attribute $(project-module) requirements ] ] ; -    } -    return $(.target.$(project-module)) ; -} - - -# Use/load a project. -# -rule use ( id : location ) -{ -    local saved-project = $(.current-project) ; -    local project-module = [ project.load $(location) ] ; -    local declared-id = [ project.attribute $(project-module) id ] ; - -    if ! $(declared-id) || $(declared-id) != $(id) -    { -        # The project at 'location' either has no id or that id is not equal to -        # the 'id' parameter. -        if $($(id).jamfile-module) && ( $($(id).jamfile-module) != -            $(project-module) ) -        { -            errors.user-error Attempt to redeclare already existing project id -                '$(id)'  -                location '$(location)' ; -        } -        $(id).jamfile-module = $(project-module) ; -    } -    .current-project = $(saved-project) ; -} - - -# Defines a Boost.Build extension project. Such extensions usually contain -# library targets and features that can be used by many people. Even though -# extensions are really projects, they can be initialized as a module would be -# with the "using" (project.project-rules.using) mechanism. -# -rule extension ( id : options * : * ) -{ -    # The caller is a standalone module for the extension. -    local mod = [ CALLER_MODULE ] ; - -    # We need to do the rest within the extension module. -    module $(mod) -    { -        import path ; - -        # Find the root project. -        local root-project = [ project.current ] ; -        root-project = [ $(root-project).project-module ] ; -        while -            [ project.attribute $(root-project) parent-module ] && -            [ project.attribute $(root-project) parent-module ] != user-config -        { -            root-project = [ project.attribute $(root-project) parent-module ] ; -        } - -        # Create the project data, and bring in the project rules into the -        # module. -        project.initialize $(__name__) : [ path.join [ project.attribute -            $(root-project) location ] ext $(1:L) ] ; - -        # Create the project itself, i.e. the attributes. All extensions are -        # created in the "/ext" project space. -        project /ext/$(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : -            $(9) ; -        local attributes = [ project.attributes $(__name__) ] ; - -        # Inherit from the root project of whomever is defining us. -        project.inherit-attributes $(__name__) : $(root-project) ; -        $(attributes).set parent-module : $(root-project) : exact ; -    } -} - - -rule glob-internal ( project : wildcards + : excludes * : rule-name ) -{ -    local location = [ $(project).get source-location ] ; - -    local result ; -    local paths = [ path.$(rule-name) $(location) : -        [ sequence.transform path.make : $(wildcards) ] : -        [ sequence.transform path.make : $(excludes) ] ] ; -    if $(wildcards:D) || $(rule-name) != glob -    { -        # The paths we have found are relative to the current directory, but the -        # names specified in the sources list are assumed to be relative to the -        # source directory of the corresponding project. So, just make the names -        # absolute. -        for local p in $(paths) -        { -            # If the path is below source location, use relative path. -            # Otherwise, use full path just to avoid any ambiguities. -            local rel = [ path.relative $(p) $(location) : no-error ] ; -            if $(rel) = not-a-child -            {                    -                result += [ path.root $(p) [ path.pwd ] ] ; -            } -            else -            { -                result += $(rel) ; -            }                 -        } -    } -    else -    { -        # There were no wildcards in the directory path, so the files are all in -        # the source directory of the project. Just drop the directory, instead -        # of making paths absolute. -        result = $(paths:D="") ; -    } - -    return $(result) ; -} - - -# This module defines rules common to all projects. -# -module project-rules -{ -    rule using ( toolset-module : * ) -    { -        import toolset ; -        import modules ; -        import project ; - -        # Temporarily change the search path so the module referred to by -        # 'using' can be placed in the same directory as Jamfile. User will -        # expect the module to be found even though the directory is not in -        # BOOST_BUILD_PATH. -        local x = [ modules.peek : BOOST_BUILD_PATH ] ; -        local caller = [ CALLER_MODULE ] ; -        local caller-location = [ modules.binding $(caller) ] ; -        modules.poke : BOOST_BUILD_PATH : $(caller-location:D) $(x) ; -        toolset.using $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ; -        modules.poke : BOOST_BUILD_PATH : $(x) ; - -        # The above might have clobbered .current-project. Restore the correct -        # value. -        modules.poke project : .current-project -            : [ project.target $(caller) ] ; -    } - -    import modules ; - -    rule import ( * : * : * ) -    { -        modules.import project ; - -        local caller = [ CALLER_MODULE ] ; -        local saved = [ modules.peek project : .current-project ] ; -        module $(caller) -        { -            modules.import $(1) : $(2) : $(3) ; -        } -        modules.poke project : .current-project : $(saved) ; -    } - -    rule project ( id ? : options * : * ) -    { -        import errors ; -        import path ; -        import project ; - -        local caller = [ CALLER_MODULE ] ; -        local attributes = [ project.attributes $(caller) ] ; -        if $(id) -        { -           $(attributes).set id : $(id) ; -        } - -        local explicit-build-dir ; - -        for n in 2 3 4 5 6 7 8 9 -        { -            local option = $($(n)) ; -            if $(option) -            { -                $(attributes).set $(option[1]) : $(option[2-]) ; -            } -            if $(option[1]) = "build-dir" -            { -                explicit-build-dir = [ path.make $(option[2-]) ] ; -            } -        } - -        # If '--build-dir' is specified, change the build dir for the project. -        local global-build-dir = -            [ modules.peek project : .global-build-dir ] ; - -        if $(global-build-dir) -        { -            local location = [ $(attributes).get location ] ; -            # Project with an empty location is a 'standalone' project such as -            # user-config or qt. It has no build dir. If we try to set build dir -            # for user-config, we shall then try to inherit it, with either -            # weird or wrong consequences. -            if $(location) && $(location) = [ $(attributes).get project-root ] -            { -                # Re-read the project id, since it might have been changed in -                # the project's attributes. -                id = [ $(attributes).get id ] ; -                # This is Jamroot. -                if $(id) -                { -                    if $(explicit-build-dir) && -                        [ path.is-rooted $(explicit-build-dir) ] -                    { -                        errors.user-error Absolute directory specified via -                            'build-dir' project attribute : Do not know how to -                            combine that with the --build-dir option. ; -                    } -                    # Strip the leading slash from id. -                    local rid = [ MATCH /(.*) : $(id) ] ; -                    local p = [ path.join -                        $(global-build-dir) $(rid) $(explicit-build-dir) ] ; - -                    $(attributes).set build-dir : $(p) : exact ; -                } -            } -            else -            { -                # Not Jamroot. -                if $(explicit-build-dir) -                { -                    errors.user-error When --build-dir is specified, the -                        'build-dir' project : attribute is allowed only for -                        top-level 'project' invocations ; -                } -            } -        } -    } - -    # Declare and set a project global constant. Project global constants are -    # normal variables but should not be changed. They are applied to every -    # child Jamfile. -    # -    rule constant ( -        name  # Variable name of the constant. -        : value +  # Value of the constant. -    ) -    { -        import project ; -        local caller = [ CALLER_MODULE ] ; -        local p = [ project.target $(caller) ] ; -        $(p).add-constant $(name) : $(value) ; -    } - -    # Declare and set a project global constant, whose value is a path. The path -    # is adjusted to be relative to the invocation directory. The given value -    # path is taken to be either absolute, or relative to this project root. -    # -    rule path-constant ( -        name  # Variable name of the constant. -        : value +  # Value of the constant. -        ) -    { -        import project ; -        local caller = [ CALLER_MODULE ] ; -        local p = [ project.target $(caller) ] ; -        $(p).add-constant $(name) : $(value) : path ; -    } - -    rule use-project ( id : where ) -    { -        import modules ; -        # See comment in 'load' for explanation. -        local caller = [ CALLER_MODULE ] ; -        modules.poke $(caller) : .used-projects : -            [ modules.peek $(caller) : .used-projects ] -            $(id) $(where) ; -    } - -    rule build-project ( dir ) -    { -        import project ; -        local caller = [ CALLER_MODULE ] ; -        local attributes = [ project.attributes $(caller) ] ; - -        local now = [ $(attributes).get projects-to-build ] ; -        $(attributes).set projects-to-build : $(now) $(dir) ; -    } - -    rule explicit ( target-names * ) -    { -        import project ; -        # If 'explicit' is used in a helper rule defined in Jamroot and -        # inherited by children, then most of the time we want 'explicit' to -        # operate on the Jamfile where the helper rule is invoked. -        local t = [ project.current ] ; -        for local n in $(target-names) -        { -            $(t).mark-target-as-explicit $(n) ; -        } -    } - -    rule always ( target-names * ) -    { -        import project ; -        local t = [ project.current ] ; -        for local n in $(target-names) -        { -            $(t).mark-target-as-always $(n) ; -        }         -    } -     -    rule glob ( wildcards + : excludes * ) -    { -        import project ; -        return [ project.glob-internal [ project.current ] : $(wildcards) : -            $(excludes) : glob ] ; -    } - -    rule glob-tree ( wildcards + : excludes * ) -    { -        import project ; - -        if $(wildcards:D) || $(excludes:D) -        { -            errors.user-error The patterns to 'glob-tree' may not include -                directory ; -        } -        return [ project.glob-internal [ project.current ] : $(wildcards) : -            $(excludes) : glob-tree ] ; -    } - -    # Calculates conditional requirements for multiple requirements at once. -    # This is a shorthand to reduce duplication and to keep an inline -    # declarative syntax. For example: -    # -    #   lib x : x.cpp : [ conditional <toolset>gcc <variant>debug : -    #       <define>DEBUG_EXCEPTION <define>DEBUG_TRACE ] ; -    # -    rule conditional ( condition + : requirements * ) -    { -        local condition = $(condition:J=,) ; -        if [ MATCH (:) : $(condition) ] -        { -            return $(condition)$(requirements) ; -        } -        else -        { -            return $(condition):$(requirements) ; -        } -    } -     -    rule option ( name : value ) -    { -        if $(__name__) != site-config && $(__name__) != user-config && $(__name__) != project-config -        { -            import errors ; -            errors.error "The 'option' rule may be used only in site-config or user-config" ; -        }         -        import option ; -        option.set $(name) : $(value) ; -    }     -} diff --git a/jam-files/boost-build/build/project.py b/jam-files/boost-build/build/project.py deleted file mode 100644 index 1e1e16fa..00000000 --- a/jam-files/boost-build/build/project.py +++ /dev/null @@ -1,1120 +0,0 @@ -# Status: ported. -# Base revision: 64488 - -# Copyright 2002, 2003 Dave Abrahams  -# Copyright 2002, 2005, 2006 Rene Rivera  -# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus  -# Distributed under the Boost Software License, Version 1.0.  -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)  - -#  Implements project representation and loading. -#   Each project is represented by  -#   - a module where all the Jamfile content live.  -#   - an instance of 'project-attributes' class. -#     (given module name, can be obtained by 'attributes' rule) -#   - an instance of 'project-target' class (from targets.jam) -#     (given a module name, can be obtained by 'target' rule) -# -#  Typically, projects are created as result of loading Jamfile, which is -#  do by rules 'load' and 'initialize', below. First, module for Jamfile -#  is loaded and new project-attributes instance is created. Some rules -#  necessary for project are added to the module (see 'project-rules' module) -#  at the bottom of this file. -#  Default project attributes are set (inheriting attributes of parent project, if -#  it exists). After that, Jamfile is read. It can declare its own attributes, -#  via 'project' rule, which will be combined with already set attributes. -# -# -#  The 'project' rule can also declare project id, which will be associated with  -#  the project module. -# -#  There can also be 'standalone' projects. They are created by calling 'initialize' -#  on arbitrary module, and not specifying location. After the call, the module can -#  call 'project' rule, declare main target and behave as regular projects. However, -#  since it's not associated with any location, it's better declare only prebuilt  -#  targets. -# -#  The list of all loaded Jamfile is stored in variable .project-locations. It's possible -#  to obtain module name for a location using 'module-name' rule. The standalone projects -#  are not recorded, the only way to use them is by project id. - -import b2.util.path -from b2.build import property_set, property -from b2.build.errors import ExceptionWithUserContext -import b2.build.targets - -import bjam - -import re -import sys -import os -import string -import imp -import traceback -import b2.util.option as option - -from b2.util import record_jam_to_value_mapping, qualify_jam_action - -class ProjectRegistry: - -    def __init__(self, manager, global_build_dir): -        self.manager = manager -        self.global_build_dir = global_build_dir -        self.project_rules_ = ProjectRules(self) - -        # The target corresponding to the project being loaded now -        self.current_project = None -         -        # The set of names of loaded project modules -        self.jamfile_modules = {} - -        # Mapping from location to module name -        self.location2module = {} - -        # Mapping from project id to project module -        self.id2module = {} - -        # Map from Jamfile directory to parent Jamfile/Jamroot -        # location. -        self.dir2parent_jamfile = {} - -        # Map from directory to the name of Jamfile in -        # that directory (or None). -        self.dir2jamfile = {} - -        # Map from project module to attributes object. -        self.module2attributes = {} - -        # Map from project module to target for the project -        self.module2target = {} - -        # Map from names to Python modules, for modules loaded -        # via 'using' and 'import' rules in Jamfiles. -        self.loaded_tool_modules_ = {} - -        self.loaded_tool_module_path_ = {} - -        # Map from project target to the list of -        # (id,location) pairs corresponding to all 'use-project' -        # invocations. -        # TODO: should not have a global map, keep this -        # in ProjectTarget. -        self.used_projects = {} - -        self.saved_current_project = [] - -        self.JAMROOT = self.manager.getenv("JAMROOT"); - -        # Note the use of character groups, as opposed to listing -        # 'Jamroot' and 'jamroot'. With the latter, we'd get duplicate -        # matches on windows and would have to eliminate duplicates. -        if not self.JAMROOT: -            self.JAMROOT = ["project-root.jam", "[Jj]amroot", "[Jj]amroot.jam"] - -        # Default patterns to search for the Jamfiles to use for build -        # declarations. -        self.JAMFILE = self.manager.getenv("JAMFILE") - -        if not self.JAMFILE: -            self.JAMFILE = ["[Bb]uild.jam", "[Jj]amfile.v2", "[Jj]amfile", -                            "[Jj]amfile.jam"] - - -    def load (self, jamfile_location): -        """Loads jamfile at the given location. After loading, project global -        file and jamfile needed by the loaded one will be loaded recursively. -        If the jamfile at that location is loaded already, does nothing. -        Returns the project module for the Jamfile.""" - -        absolute = os.path.join(os.getcwd(), jamfile_location) -        absolute = os.path.normpath(absolute) -        jamfile_location = b2.util.path.relpath(os.getcwd(), absolute) - -        if "--debug-loading" in self.manager.argv(): -            print "Loading Jamfile at '%s'" % jamfile_location - -             -        mname = self.module_name(jamfile_location) -        # If Jamfile is already loaded, don't try again. -        if not mname in self.jamfile_modules: -         -            self.load_jamfile(jamfile_location, mname) -                 -            # We want to make sure that child project are loaded only -            # after parent projects. In particular, because parent projects -            # define attributes whch are inherited by children, and we don't -            # want children to be loaded before parents has defined everything. -            # -            # While "build-project" and "use-project" can potentially refer -            # to child projects from parent projects, we don't immediately -            # load child projects when seing those attributes. Instead, -            # we record the minimal information that will be used only later. -             -            self.load_used_projects(mname) -              -        return mname - -    def load_used_projects(self, module_name): -        # local used = [ modules.peek $(module-name) : .used-projects ] ; -        used = self.used_projects[module_name] -     -        location = self.attribute(module_name, "location") -        for u in used: -            id = u[0] -            where = u[1] - -            self.use(id, os.path.join(location, where)) - -    def load_parent(self, location): -        """Loads parent of Jamfile at 'location'. -        Issues an error if nothing is found.""" - -        found = b2.util.path.glob_in_parents( -            location, self.JAMROOT + self.JAMFILE)  - -        if not found: -            print "error: Could not find parent for project at '%s'" % location -            print "error: Did not find Jamfile or project-root.jam in any parent directory." -            sys.exit(1) -     -        return self.load(os.path.dirname(found[0])) - -    def act_as_jamfile(self, module, location): -        """Makes the specified 'module' act as if it were a regularly loaded Jamfile  -        at 'location'. If Jamfile is already located for that location, it's an  -        error.""" - -        if self.module_name(location) in self.jamfile_modules: -            self.manager.errors()( -                "Jamfile was already loaded for '%s'" % location) -     -        # Set up non-default mapping from location to module. -        self.location2module[location] = module -     -        # Add the location to the list of project locations -        # so that we don't try to load Jamfile in future -        self.jamfile_modules.append(location) -     -        self.initialize(module, location) - -    def find(self, name, current_location): -        """Given 'name' which can be project-id or plain directory name, -        return project module corresponding to that id or directory. -        Returns nothing of project is not found.""" - -        project_module = None - -        # Try interpreting name as project id. -        if name[0] == '/': -            project_module = self.id2module.get(name) - -        if not project_module: -            location = os.path.join(current_location, name) -            # If no project is registered for the given location, try to -            # load it. First see if we have Jamfile. If not we might have project -            # root, willing to act as Jamfile. In that case, project-root -            # must be placed in the directory referred by id. -         -            project_module = self.module_name(location) -            if not project_module in self.jamfile_modules: -                if b2.util.path.glob([location], self.JAMROOT + self.JAMFILE): -                    project_module = self.load(location) -                else: -                    project_module = None - -        return project_module - -    def module_name(self, jamfile_location): -        """Returns the name of module corresponding to 'jamfile-location'. -        If no module corresponds to location yet, associates default -        module name with that location.""" -        module = self.location2module.get(jamfile_location) -        if not module: -            # Root the path, so that locations are always umbiguious. -            # Without this, we can't decide if '../../exe/program1' and '.' -            # are the same paths, or not. -            jamfile_location = os.path.realpath( -                os.path.join(os.getcwd(), jamfile_location)) -            module = "Jamfile<%s>" % jamfile_location -            self.location2module[jamfile_location] = module -        return module - -    def find_jamfile (self, dir, parent_root=0, no_errors=0): -        """Find the Jamfile at the given location. This returns the -        exact names of all the Jamfiles in the given directory. The optional -        parent-root argument causes this to search not the given directory -        but the ones above it up to the directory given in it.""" -         -        # Glob for all the possible Jamfiles according to the match pattern. -        # -        jamfile_glob = None -        if parent_root: -            parent = self.dir2parent_jamfile.get(dir) -            if not parent: -                parent = b2.util.path.glob_in_parents(dir, -                                                               self.JAMFILE) -                self.dir2parent_jamfile[dir] = parent -            jamfile_glob = parent -        else: -            jamfile = self.dir2jamfile.get(dir) -            if not jamfile: -                jamfile = b2.util.path.glob([dir], self.JAMFILE) -                self.dir2jamfile[dir] = jamfile -            jamfile_glob = jamfile - -        if len(jamfile_glob) > 1: -            # Multiple Jamfiles found in the same place. Warn about this. -            # And ensure we use only one of them. -            # As a temporary convenience measure, if there's Jamfile.v2 amount -            # found files, suppress the warning and use it. -            # -            pattern = "(.*[Jj]amfile\\.v2)|(.*[Bb]uild\\.jam)" -            v2_jamfiles = [x for x in jamfile_glob if re.match(pattern, x)] -            if len(v2_jamfiles) == 1: -                jamfile_glob = v2_jamfiles -            else: -                print """warning: Found multiple Jamfiles at '%s'!""" % (dir) -                for j in jamfile_glob: -                    print "    -", j -                print "Loading the first one" -     -        # Could not find it, error. -        if not no_errors and not jamfile_glob: -            self.manager.errors()( -                """Unable to load Jamfile. -Could not find a Jamfile in directory '%s' -Attempted to find it with pattern '%s'. -Please consult the documentation at 'http://boost.org/boost-build2'.""" -                % (dir, string.join(self.JAMFILE))) - -        if jamfile_glob: -            return jamfile_glob[0] -     -    def load_jamfile(self, dir, jamfile_module): -        """Load a Jamfile at the given directory. Returns nothing. -        Will attempt to load the file as indicated by the JAMFILE patterns. -        Effect of calling this rule twice with the same 'dir' is underfined.""" -       -        # See if the Jamfile is where it should be. -        is_jamroot = False -        jamfile_to_load = b2.util.path.glob([dir], self.JAMROOT) -        if not jamfile_to_load: -            jamfile_to_load = self.find_jamfile(dir) -        else: -            if len(jamfile_to_load) > 1: -                get_manager().errors()("Multiple Jamfiles found at '%s'\n" +\ -                                       "Filenames are: %s" -                                       % (dir, [os.path.basename(j) for j in jamfile_to_load])) - -            is_jamroot = True -            jamfile_to_load = jamfile_to_load[0] - -        dir = os.path.dirname(jamfile_to_load) -        if not dir: -            dir = "." - -        self.used_projects[jamfile_module] = [] -         -        # Now load the Jamfile in it's own context.  -        # The call to 'initialize' may load parent Jamfile, which might have -        # 'use-project' statement that causes a second attempt to load the -        # same project we're loading now.  Checking inside .jamfile-modules -        # prevents that second attempt from messing up. -        if not jamfile_module in self.jamfile_modules: -            self.jamfile_modules[jamfile_module] = True - -            # Initialize the jamfile module before loading. -            #     -            self.initialize(jamfile_module, dir, os.path.basename(jamfile_to_load)) - -            saved_project = self.current_project - -            bjam.call("load", jamfile_module, jamfile_to_load) -            basename = os.path.basename(jamfile_to_load) - -            if is_jamroot: -                jamfile = self.find_jamfile(dir, no_errors=True) -                if jamfile: -                    bjam.call("load", jamfile_module, jamfile) -                                     -        # Now do some checks -        if self.current_project != saved_project: -            self.manager.errors()( -"""The value of the .current-project variable -has magically changed after loading a Jamfile. -This means some of the targets might be defined a the wrong project. -after loading %s -expected value %s -actual value %s""" % (jamfile_module, saved_project, self.current_project)) -           -        if self.global_build_dir: -            id = self.attributeDefault(jamfile_module, "id", None) -            project_root = self.attribute(jamfile_module, "project-root") -            location = self.attribute(jamfile_module, "location") - -            if location and project_root == dir: -                # This is Jamroot -                if not id: -                    # FIXME: go via errors module, so that contexts are -                    # shown? -                    print "warning: the --build-dir option was specified" -                    print "warning: but Jamroot at '%s'" % dir -                    print "warning: specified no project id" -                    print "warning: the --build-dir option will be ignored" - - -    def load_standalone(self, jamfile_module, file): -        """Loads 'file' as standalone project that has no location -        associated with it.  This is mostly useful for user-config.jam, -        which should be able to define targets, but although it has -        some location in filesystem, we don't want any build to -        happen in user's HOME, for example. - -        The caller is required to never call this method twice on -        the same file. -        """ - -        self.used_projects[jamfile_module] = [] -        bjam.call("load", jamfile_module, file) -        self.load_used_projects(jamfile_module) -         -    def is_jamroot(self, basename): -        match = [ pat for pat in self.JAMROOT if re.match(pat, basename)] -        if match: -            return 1 -        else: -            return 0 - -    def initialize(self, module_name, location=None, basename=None): -        """Initialize the module for a project. -         -        module-name is the name of the project module. -        location is the location (directory) of the project to initialize. -                 If not specified, stanalone project will be initialized -        """ - -        if "--debug-loading" in self.manager.argv(): -            print "Initializing project '%s'" % module_name - -        # TODO: need to consider if standalone projects can do anything but defining -        # prebuilt targets. If so, we need to give more sensible "location", so that -        # source paths are correct. -        if not location: -            location = "" - -        attributes = ProjectAttributes(self.manager, location, module_name) -        self.module2attributes[module_name] = attributes - -        python_standalone = False -        if location: -            attributes.set("source-location", [location], exact=1) -        elif not module_name in ["test-config", "site-config", "user-config", "project-config"]: -            # This is a standalone project with known location. Set source location -            # so that it can declare targets. This is intended so that you can put -            # a .jam file in your sources and use it via 'using'. Standard modules -            # (in 'tools' subdir) may not assume source dir is set. -            module = sys.modules[module_name]           -            attributes.set("source-location", self.loaded_tool_module_path_[module_name], exact=1) -            python_standalone = True - -        attributes.set("requirements", property_set.empty(), exact=True) -        attributes.set("usage-requirements", property_set.empty(), exact=True) -        attributes.set("default-build", property_set.empty(), exact=True) -        attributes.set("projects-to-build", [], exact=True) -        attributes.set("project-root", None, exact=True) -        attributes.set("build-dir", None, exact=True) -         -        self.project_rules_.init_project(module_name, python_standalone) - -        jamroot = False - -        parent_module = None; -        if module_name == "test-config": -            # No parent -            pass -        elif module_name == "site-config": -            parent_module = "test-config" -        elif module_name == "user-config": -            parent_module = "site-config" -        elif module_name == "project-config": -            parent_module = "user-config" -        elif location and not self.is_jamroot(basename): -            # We search for parent/project-root only if jamfile was specified  -            # --- i.e -            # if the project is not standalone. -            parent_module = self.load_parent(location) -        else: -            # It's either jamroot, or standalone project. -            # If it's jamroot, inherit from user-config. -            if location: -                # If project-config module exist, inherit from it. -                if self.module2attributes.has_key("project-config"): -                    parent_module = "project-config" -                else: -                    parent_module = "user-config" ; -                 -                jamroot = True ; -                 -        if parent_module: -            self.inherit_attributes(module_name, parent_module) -            attributes.set("parent-module", parent_module, exact=1) - -        if jamroot: -            attributes.set("project-root", location, exact=1) -                                 -        parent = None -        if parent_module: -            parent = self.target(parent_module) - -        if not self.module2target.has_key(module_name): -            target = b2.build.targets.ProjectTarget(self.manager, -                module_name, module_name, parent, -                self.attribute(module_name,"requirements"), -                # FIXME: why we need to pass this? It's not -                # passed in jam code. -                self.attribute(module_name, "default-build")) -            self.module2target[module_name] = target - -        self.current_project = self.target(module_name) - -    def inherit_attributes(self, project_module, parent_module): -        """Make 'project-module' inherit attributes of project -        root and parent module.""" - -        attributes = self.module2attributes[project_module] -        pattributes = self.module2attributes[parent_module] -         -        # Parent module might be locationless user-config. -        # FIXME: -        #if [ modules.binding $(parent-module) ] -        #{         -        #    $(attributes).set parent : [ path.parent  -        #                                 [ path.make [ modules.binding $(parent-module) ] ] ] ; -        #    } -         -        attributes.set("project-root", pattributes.get("project-root"), exact=True) -        attributes.set("default-build", pattributes.get("default-build"), exact=True) -        attributes.set("requirements", pattributes.get("requirements"), exact=True) -        attributes.set("usage-requirements", -                       pattributes.get("usage-requirements"), exact=1) - -        parent_build_dir = pattributes.get("build-dir") -         -        if parent_build_dir: -        # Have to compute relative path from parent dir to our dir -        # Convert both paths to absolute, since we cannot -        # find relative path from ".." to "." - -             location = attributes.get("location") -             parent_location = pattributes.get("location") - -             our_dir = os.path.join(os.getcwd(), location) -             parent_dir = os.path.join(os.getcwd(), parent_location) - -             build_dir = os.path.join(parent_build_dir, -                                      os.path.relpath(our_dir, parent_dir)) -             attributes.set("build-dir", build_dir, exact=True) - -    def register_id(self, id, module): -        """Associate the given id with the given project module.""" -        self.id2module[id] = module - -    def current(self): -        """Returns the project which is currently being loaded.""" -        return self.current_project - -    def set_current(self, c): -        self.current_project = c - -    def push_current(self, project): -        """Temporary changes the current project to 'project'. Should -        be followed by 'pop-current'.""" -        self.saved_current_project.append(self.current_project) -        self.current_project = project - -    def pop_current(self): -        self.current_project = self.saved_current_project[-1] -        del self.saved_current_project[-1] - -    def attributes(self, project): -        """Returns the project-attribute instance for the -        specified jamfile module.""" -        return self.module2attributes[project] - -    def attribute(self, project, attribute): -        """Returns the value of the specified attribute in the -        specified jamfile module.""" -        return self.module2attributes[project].get(attribute) -        try:     -            return self.module2attributes[project].get(attribute) -        except: -            raise BaseException("No attribute '%s' for project" % (attribute, project)) - -    def attributeDefault(self, project, attribute, default): -        """Returns the value of the specified attribute in the -        specified jamfile module.""" -        return self.module2attributes[project].getDefault(attribute, default) - -    def target(self, project_module): -        """Returns the project target corresponding to the 'project-module'.""" -        if not self.module2target.has_key(project_module): -            self.module2target[project_module] = \ -                b2.build.targets.ProjectTarget(project_module, project_module, -                              self.attribute(project_module, "requirements")) -         -        return self.module2target[project_module] - -    def use(self, id, location): -        # Use/load a project. -        saved_project = self.current_project -        project_module = self.load(location) -        declared_id = self.attributeDefault(project_module, "id", "") - -        if not declared_id or declared_id != id: -            # The project at 'location' either have no id or -            # that id is not equal to the 'id' parameter. -            if self.id2module.has_key(id) and self.id2module[id] != project_module: -                self.manager.errors()( -"""Attempt to redeclare already existing project id '%s' at location '%s'""" % (id, location)) -            self.id2module[id] = project_module - -        self.current_module = saved_project - -    def add_rule(self, name, callable): -        """Makes rule 'name' available to all subsequently loaded Jamfiles. - -        Calling that rule wil relay to 'callable'.""" -        self.project_rules_.add_rule(name, callable) - -    def project_rules(self): -        return self.project_rules_ - -    def glob_internal(self, project, wildcards, excludes, rule_name): -        location = project.get("source-location")[0] - -        result = [] -        callable = b2.util.path.__dict__[rule_name] -         -        paths = callable([location], wildcards, excludes) -        has_dir = 0 -        for w in wildcards: -            if os.path.dirname(w): -                has_dir = 1 -                break - -        if has_dir or rule_name != "glob": -            result = [] -            # The paths we've found are relative to current directory, -            # but the names specified in sources list are assumed to -            # be relative to source directory of the corresponding -            # prject. Either translate them or make absolute. - -            for p in paths: -                rel = os.path.relpath(p, location) -                # If the path is below source location, use relative path. -                if not ".." in rel: -                    result.append(rel) -                else: -                    # Otherwise, use full path just to avoid any ambiguities. -                    result.append(os.path.abspath(p)) -                     -        else: -            # There were not directory in wildcard, so the files are all -            # in the source directory of the project. Just drop the -            # directory, instead of making paths absolute. -            result = [os.path.basename(p) for p in paths] -             -        return result - -    def load_module(self, name, extra_path=None): -        """Load a Python module that should be useable from Jamfiles. - -        There are generally two types of modules Jamfiles might want to -        use: -        - Core Boost.Build. Those are imported using plain names, e.g. -        'toolset', so this function checks if we have module named -        b2.package.module already. -        - Python modules in the same directory as Jamfile. We don't -        want to even temporary add Jamfile's directory to sys.path, -        since then we might get naming conflicts between standard -        Python modules and those. -        """ - -        # See if we loaded module of this name already -        existing = self.loaded_tool_modules_.get(name) -        if existing: -            return existing - -        # See if we have a module b2.whatever.<name>, where <name> -        # is what is passed to this function -        modules = sys.modules -        for class_name in modules: -            parts = class_name.split('.') -            if name is class_name or parts[0] == "b2" \ -            and parts[-1] == name.replace("-", "_"): -                module = modules[class_name] -                self.loaded_tool_modules_[name] = module -                return module - -        # Lookup a module in BOOST_BUILD_PATH -        path = extra_path -        if not path: -            path = [] -        path.extend(self.manager.boost_build_path()) -        location = None -        for p in path: -            l = os.path.join(p, name + ".py") -            if os.path.exists(l): -                location = l -                break - -        if not location: -            self.manager.errors()("Cannot find module '%s'" % name) - -        mname = name + "__for_jamfile" -        file = open(location) -        try:             -            # TODO: this means we'll never make use of .pyc module, -            # which might be a problem, or not. -            self.loaded_tool_module_path_[mname] = location -            module = imp.load_module(mname, file, os.path.basename(location), -                                     (".py", "r", imp.PY_SOURCE)) -            self.loaded_tool_modules_[name] = module -            return module -        finally: -            file.close() -         - - -# FIXME: -# Defines a Boost.Build extension project. Such extensions usually -# contain library targets and features that can be used by many people. -# Even though extensions are really projects, they can be initialize as -# a module would be with the "using" (project.project-rules.using) -# mechanism. -#rule extension ( id : options * : * ) -#{ -#    # The caller is a standalone module for the extension. -#    local mod = [ CALLER_MODULE ] ; -#     -#    # We need to do the rest within the extension module. -#    module $(mod) -#    { -#        import path ; -#         -#        # Find the root project. -#        local root-project = [ project.current ] ; -#        root-project = [ $(root-project).project-module ] ; -#        while -#            [ project.attribute $(root-project) parent-module ] && -#            [ project.attribute $(root-project) parent-module ] != user-config -#        { -#            root-project = [ project.attribute $(root-project) parent-module ] ; -#        } -#         -#        # Create the project data, and bring in the project rules -#        # into the module. -#        project.initialize $(__name__) : -#            [ path.join [ project.attribute $(root-project) location ] ext $(1:L) ] ; -#         -#        # Create the project itself, i.e. the attributes. -#        # All extensions are created in the "/ext" project space. -#        project /ext/$(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ; -#        local attributes = [ project.attributes $(__name__) ] ; -#         -#        # Inherit from the root project of whomever is defining us. -#        project.inherit-attributes $(__name__) : $(root-project) ; -#        $(attributes).set parent-module : $(root-project) : exact ; -#    } -#} -         - -class ProjectAttributes: -    """Class keeping all the attributes of a project. - -    The standard attributes are 'id', "location", "project-root", "parent" -    "requirements", "default-build", "source-location" and "projects-to-build". -    """ -         -    def __init__(self, manager, location, project_module): -        self.manager = manager -        self.location = location -        self.project_module = project_module -        self.attributes = {} -        self.usage_requirements = None -         -    def set(self, attribute, specification, exact=False): -        """Set the named attribute from the specification given by the user. -        The value actually set may be different.""" - -        if exact: -            self.__dict__[attribute] = specification -             -        elif attribute == "requirements": -            self.requirements = property_set.refine_from_user_input( -                self.requirements, specification, -                self.project_module, self.location) -             -        elif attribute == "usage-requirements": -            unconditional = [] -            for p in specification: -                split = property.split_conditional(p) -                if split: -                    unconditional.append(split[1]) -                else: -                    unconditional.append(p) - -            non_free = property.remove("free", unconditional) -            if non_free:                 -                get_manager().errors()("usage-requirements %s have non-free properties %s" \ -                                       % (specification, non_free)) - -            t = property.translate_paths( -                    property.create_from_strings(specification, allow_condition=True), -                    self.location) - -            existing = self.__dict__.get("usage-requirements") -            if existing: -                new = property_set.create(existing.all() +  t) -            else: -                new = property_set.create(t) -            self.__dict__["usage-requirements"] = new - -                 -        elif attribute == "default-build": -            self.__dict__["default-build"] = property_set.create(specification) -             -        elif attribute == "source-location": -            source_location = [] -            for path in specification: -                source_location.append(os.path.join(self.location, path)) -            self.__dict__["source-location"] = source_location -                 -        elif attribute == "build-dir": -            self.__dict__["build-dir"] = os.path.join(self.location, specification[0]) - -        elif attribute == "id": -            id = specification[0] -            if id[0] != '/': -                id = "/" + id -            self.manager.projects().register_id(id, self.project_module) -            self.__dict__["id"] = id -                 -        elif not attribute in ["default-build", "location", -                               "source-location", "parent", -                               "projects-to-build", "project-root"]: -            self.manager.errors()( -"""Invalid project attribute '%s' specified -for project at '%s'""" % (attribute, self.location)) -        else: -            self.__dict__[attribute] = specification - -    def get(self, attribute): -        return self.__dict__[attribute] - -    def getDefault(self, attribute, default): -        return self.__dict__.get(attribute, default) - -    def dump(self): -        """Prints the project attributes.""" -        id = self.get("id") -        if not id: -            id = "(none)" -        else: -            id = id[0] - -        parent = self.get("parent") -        if not parent: -            parent = "(none)" -        else: -            parent = parent[0] - -        print "'%s'" % id -        print "Parent project:%s", parent -        print "Requirements:%s", self.get("requirements") -        print "Default build:%s", string.join(self.get("debuild-build")) -        print "Source location:%s", string.join(self.get("source-location")) -        print "Projects to build:%s", string.join(self.get("projects-to-build").sort()); - -class ProjectRules: -    """Class keeping all rules that are made available to Jamfile.""" - -    def __init__(self, registry): -        self.registry = registry -        self.manager_ = registry.manager -        self.rules = {} -        self.local_names = [x for x in self.__class__.__dict__ -                            if x not in ["__init__", "init_project", "add_rule", -                                         "error_reporting_wrapper", "add_rule_for_type", "reverse"]] -        self.all_names_ = [x for x in self.local_names] - -    def _import_rule(self, bjam_module, name, callable): -        if hasattr(callable, "bjam_signature"): -            bjam.import_rule(bjam_module, name, self.make_wrapper(callable), callable.bjam_signature) -        else: -            bjam.import_rule(bjam_module, name, self.make_wrapper(callable)) -         - -    def add_rule_for_type(self, type): -        rule_name = type.lower().replace("_", "-") - -        def xpto (name, sources = [], requirements = [], default_build = [], usage_requirements = []): -            return self.manager_.targets().create_typed_target( -                type, self.registry.current(), name[0], sources, -                requirements, default_build, usage_requirements)  - -        self.add_rule(rule_name, xpto) -     -    def add_rule(self, name, callable): -        self.rules[name] = callable -        self.all_names_.append(name) - -        # Add new rule at global bjam scope. This might not be ideal, -        # added because if a jamroot does 'import foo' where foo calls -        # add_rule, we need to import new rule to jamroot scope, and -        # I'm lazy to do this now. -        self._import_rule("", name, callable) - -    def all_names(self): -        return self.all_names_ - -    def call_and_report_errors(self, callable, *args, **kw): -        result = None -        try: -            self.manager_.errors().push_jamfile_context() -            result = callable(*args, **kw) -        except ExceptionWithUserContext, e: -            e.report() -        except Exception, e: -            try: -                self.manager_.errors().handle_stray_exception (e) -            except ExceptionWithUserContext, e: -                e.report() -        finally:                 -            self.manager_.errors().pop_jamfile_context() - -        return result - -    def make_wrapper(self, callable): -        """Given a free-standing function 'callable', return a new -        callable that will call 'callable' and report all exceptins, -        using 'call_and_report_errors'.""" -        def wrapper(*args, **kw): -            return self.call_and_report_errors(callable, *args, **kw) -        return wrapper - -    def init_project(self, project_module, python_standalone=False): - -        if python_standalone: -            m = sys.modules[project_module] - -            for n in self.local_names: -                if n != "import_": -                    setattr(m, n, getattr(self, n)) -                             -            for n in self.rules: -                setattr(m, n, self.rules[n]) - -            return -                         -        for n in self.local_names:             -            # Using 'getattr' here gives us a bound method, -            # while using self.__dict__[r] would give unbound one. -            v = getattr(self, n) -            if callable(v): -                if n == "import_": -                    n = "import" -                else: -                    n = string.replace(n, "_", "-") -                     -                self._import_rule(project_module, n, v) - -        for n in self.rules: -            self._import_rule(project_module, n, self.rules[n]) - -    def project(self, *args): - -        jamfile_module = self.registry.current().project_module() -        attributes = self.registry.attributes(jamfile_module) -         -        id = None -        if args and args[0]: -            id = args[0][0] -            args = args[1:] - -        if id: -            attributes.set('id', [id]) - -        explicit_build_dir = None -        for a in args: -            if a: -                attributes.set(a[0], a[1:], exact=0) -                if a[0] == "build-dir": -                    explicit_build_dir = a[1] -         -        # If '--build-dir' is specified, change the build dir for the project. -        if self.registry.global_build_dir: - -            location = attributes.get("location") -            # Project with empty location is 'standalone' project, like -            # user-config, or qt.  It has no build dir. -            # If we try to set build dir for user-config, we'll then -            # try to inherit it, with either weird, or wrong consequences. -            if location and location == attributes.get("project-root"): -                # Re-read the project id, since it might have been changed in -                # the project's attributes. -                id = attributes.get('id') - -                # This is Jamroot. -                if id: -                    if explicit_build_dir and os.path.isabs(explicit_build_dir): -                        self.registry.manager.errors()( -"""Absolute directory specified via 'build-dir' project attribute -Don't know how to combine that with the --build-dir option.""") - -                    rid = id -                    if rid[0] == '/': -                        rid = rid[1:] -                     -                    p = os.path.join(self.registry.global_build_dir, rid) -                    if explicit_build_dir: -                        p = os.path.join(p, explicit_build_dir) -                    attributes.set("build-dir", p, exact=1) -            elif explicit_build_dir: -                self.registry.manager.errors()( -"""When --build-dir is specified, the 'build-dir' -attribute is allowed only for top-level 'project' invocations""") - -    def constant(self, name, value): -        """Declare and set a project global constant. -        Project global constants are normal variables but should -        not be changed. They are applied to every child Jamfile.""" -        m = "Jamfile</home/ghost/Work/Boost/boost-svn/tools/build/v2_python/python/tests/bjam/make>" -        self.registry.current().add_constant(name[0], value) - -    def path_constant(self, name, value): -        """Declare and set a project global constant, whose value is a path. The -        path is adjusted to be relative to the invocation directory. The given -        value path is taken to be either absolute, or relative to this project -        root.""" -        if len(value) > 1: -            self.registry.manager.error()("path constant should have one element") -        self.registry.current().add_constant(name[0], value[0], path=1) - -    def use_project(self, id, where): -        # See comment in 'load' for explanation why we record the -        # parameters as opposed to loading the project now. -        m = self.registry.current().project_module(); -        self.registry.used_projects[m].append((id[0], where[0])) -         -    def build_project(self, dir): -        assert(isinstance(dir, list)) -        jamfile_module = self.registry.current().project_module() -        attributes = self.registry.attributes(jamfile_module) -        now = attributes.get("projects-to-build") -        attributes.set("projects-to-build", now + dir, exact=True) - -    def explicit(self, target_names): -        self.registry.current().mark_targets_as_explicit(target_names) - -    def always(self, target_names): -        self.registry.current().mark_targets_as_alays(target_names) - -    def glob(self, wildcards, excludes=None): -        return self.registry.glob_internal(self.registry.current(), -                                           wildcards, excludes, "glob") - -    def glob_tree(self, wildcards, excludes=None): -        bad = 0 -        for p in wildcards: -            if os.path.dirname(p): -                bad = 1 - -        if excludes: -            for p in excludes: -                if os.path.dirname(p): -                    bad = 1 - -        if bad: -            self.registry.manager.errors()( -"The patterns to 'glob-tree' may not include directory") -        return self.registry.glob_internal(self.registry.current(), -                                           wildcards, excludes, "glob_tree") -     - -    def using(self, toolset, *args): -        # The module referred by 'using' can be placed in -        # the same directory as Jamfile, and the user -        # will expect the module to be found even though -        # the directory is not in BOOST_BUILD_PATH. -        # So temporary change the search path. -        current = self.registry.current() -        location = current.get('location') - -        m = self.registry.load_module(toolset[0], [location]) -        if not m.__dict__.has_key("init"): -            self.registry.manager.errors()( -                "Tool module '%s' does not define the 'init' method" % toolset[0]) -        m.init(*args) - -        # The above might have clobbered .current-project. Restore the correct -        # value. -        self.registry.set_current(current) - -    def import_(self, name, names_to_import=None, local_names=None): - -        name = name[0] -        py_name = name -        if py_name == "os": -            py_name = "os_j" -        jamfile_module = self.registry.current().project_module() -        attributes = self.registry.attributes(jamfile_module) -        location = attributes.get("location") - -        saved = self.registry.current() - -        m = self.registry.load_module(py_name, [location]) - -        for f in m.__dict__: -            v = m.__dict__[f] -            f = f.replace("_", "-") -            if callable(v): -                qn = name + "." + f -                self._import_rule(jamfile_module, qn, v) -                record_jam_to_value_mapping(qualify_jam_action(qn, jamfile_module), v) - - -        if names_to_import: -            if not local_names: -                local_names = names_to_import - -            if len(names_to_import) != len(local_names): -                self.registry.manager.errors()( -"""The number of names to import and local names do not match.""") - -            for n, l in zip(names_to_import, local_names): -                self._import_rule(jamfile_module, l, m.__dict__[n]) -                 -        self.registry.set_current(saved) -         -    def conditional(self, condition, requirements): -        """Calculates conditional requirements for multiple requirements -        at once. This is a shorthand to be reduce duplication and to -        keep an inline declarative syntax. For example: - -            lib x : x.cpp : [ conditional <toolset>gcc <variant>debug : -                <define>DEBUG_EXCEPTION <define>DEBUG_TRACE ] ; -        """ - -        c = string.join(condition, ",") -        if c.find(":") != -1: -            return [c + r for r in requirements] -        else: -            return [c + ":" + r for r in requirements] - -    def option(self, name, value): -        name = name[0] -        if not name in ["site-config", "user-config", "project-config"]: -            get_manager().errors()("The 'option' rule may be used only in site-config or user-config") - -        option.set(name, value[0]) diff --git a/jam-files/boost-build/build/property-set.jam b/jam-files/boost-build/build/property-set.jam deleted file mode 100644 index 70fd90cd..00000000 --- a/jam-files/boost-build/build/property-set.jam +++ /dev/null @@ -1,481 +0,0 @@ -# Copyright 2003 Dave Abrahams -# Copyright 2003, 2004, 2005, 2006 Vladimir Prus -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - -import "class" : new ; -import feature ; -import path ; -import project ; -import property ; -import sequence ; -import set ; -import option ; - -# Class for storing a set of properties. -# -#   There is 1<->1 correspondence between identity and value. No two instances -# of the class are equal. To maintain this property, the 'property-set.create' -# rule should be used to create new instances. Instances are immutable. -# -#   Each property is classified with regard to its effect on build results. -# Incidental properties have no effect on build results, from Boost.Build's -# point of view. Others are either free, or non-free and we refer to non-free -# ones as 'base'. Each property belongs to exactly one of those categories. -# -#   It is possible to get a list of properties belonging to each category as -# well as a list of properties with a specific attribute. -# -#   Several operations, like and refine and as-path are provided. They all use -# caching whenever possible. -# -class property-set -{ -    import errors ; -    import feature ; -    import path ; -    import property ; -    import property-set ; -    import set ; -     -    rule __init__ ( raw-properties * ) -    { -        self.raw = $(raw-properties) ; - -        for local p in $(raw-properties) -        { -            if ! $(p:G) -            { -                errors.error "Invalid property: '$(p)'" ; -            } - -            local att = [ feature.attributes $(p:G) ] ; -            # A feature can be both incidental and free, in which case we add it -            # to incidental. -            if incidental in $(att) -            { -                self.incidental += $(p) ; -            } -            else if free in $(att) -            { -                self.free += $(p) ; -            } -            else -            { -                self.base += $(p) ; -            } - -            if dependency in $(att) -            { -                self.dependency += $(p) ; -            } -            else -            { -                self.non-dependency += $(p) ; -            } - -            if [ MATCH (:) : $(p:G=) ] -            { -                self.conditional += $(p) ; -            } -            else -            { -                self.non-conditional += $(p) ; -            } - -            if propagated in $(att) -            { -                self.propagated += $(p) ; -            } -            if link-incompatible in $(att) -            { -                self.link-incompatible += $(p) ; -            } -        } -    } - -    # Returns Jam list of stored properties. -    # -    rule raw ( ) -    { -        return $(self.raw) ; -    } - -    rule str ( ) -    { -        return "[" $(self.raw) "]" ; -    } - -    # Returns properties that are neither incidental nor free. -    # -    rule base ( ) -    { -        return $(self.base) ; -    } - -    # Returns free properties which are not incidental. -    # -    rule free ( ) -    { -        return $(self.free) ; -    } - -    # Returns dependency properties. -    # -    rule dependency ( ) -    { -        return $(self.dependency) ; -    } - -    rule non-dependency ( ) -    { -        return $(self.non-dependency) ; -    } - -    rule conditional ( ) -    { -        return $(self.conditional) ; -    } - -    rule non-conditional ( ) -    { -        return $(self.non-conditional) ; -    } - -    # Returns incidental properties. -    # -    rule incidental ( ) -    { -        return $(self.incidental) ; -    } - -    rule refine ( ps ) -    { -        if ! $(self.refined.$(ps)) -        { -            local r = [ property.refine $(self.raw) : [ $(ps).raw ] ] ; -            if $(r[1]) != "@error" -            { -                self.refined.$(ps) = [ property-set.create $(r) ] ; -            } -            else -            { -                self.refined.$(ps) = $(r) ; -            } -        } -        return $(self.refined.$(ps)) ; -    } - -    rule expand ( ) -    { -        if ! $(self.expanded) -        { -            self.expanded = [ property-set.create [ feature.expand $(self.raw) ] ] ; -        } -        return $(self.expanded) ; -    } - -    rule expand-composites ( ) -    { -        if ! $(self.composites) -        { -            self.composites = [ property-set.create -                [ feature.expand-composites $(self.raw) ] ] ; -        } -        return $(self.composites) ; -    } - -    rule evaluate-conditionals ( context ? ) -    { -        context ?= $(__name__) ; -        if ! $(self.evaluated.$(context)) -        { -            self.evaluated.$(context) = [ property-set.create -                [ property.evaluate-conditionals-in-context $(self.raw) : [ $(context).raw ] ] ] ; -        } -        return $(self.evaluated.$(context)) ; -    } - -    rule propagated ( ) -    { -        if ! $(self.propagated-ps) -        { -            self.propagated-ps = [ property-set.create $(self.propagated) ] ; -        } -        return $(self.propagated-ps) ; -    } - -    rule link-incompatible ( ) -    { -        if ! $(self.link-incompatible-ps) -        { -            self.link-incompatible-ps = -              [ property-set.create $(self.link-incompatible) ] ; -        } -        return $(self.link-incompatible-ps) ; -    } - -    rule run-actions ( ) -    { -        if ! $(self.run) -        { -            self.run = [ property-set.create [ feature.run-actions $(self.raw) ] ] ; -        } -        return $(self.run) ; -    } - -    rule add-defaults ( ) -    { -        if ! $(self.defaults) -        { -            self.defaults = [ property-set.create -                [ feature.add-defaults $(self.raw) ] ] ; -        } -        return $(self.defaults) ; -    } - -    rule as-path ( ) -    { -        if ! $(self.as-path) -        { -            self.as-path = [ property.as-path $(self.base) ] ; -        } -        return $(self.as-path) ; -    } - -    # Computes the path to be used for a target with the given properties. -    # Returns a list of -    #   - the computed path -    #   - if the path is relative to the build directory, a value of 'true'. -    # -    rule target-path ( ) -    { -        if ! $(self.target-path) -        { -            # The <location> feature can be used to explicitly change the -            # location of generated targets. -            local l = [ get <location> ] ; -            if $(l) -            { -                self.target-path = $(l) ; -            } -            else -            { -                local p = [ as-path ] ; -                p = [ property-set.hash-maybe $(p) ] ; -                 -                # A real ugly hack. Boost regression test system requires -                # specific target paths, and it seems that changing it to handle -                # other directory layout is really hard. For that reason, we -                # teach V2 to do the things regression system requires. The -                # value of '<location-prefix>' is prepended to the path. -                local prefix = [ get <location-prefix> ] ; -                if $(prefix) -                { -                    self.target-path = [ path.join $(prefix) $(p) ] ; -                } -                else -                { -                    self.target-path = $(p) ; -                } -                if ! $(self.target-path) -                { -                    self.target-path = . ; -                } -                # The path is relative to build dir. -                self.target-path += true ; -            } -        } -        return $(self.target-path) ; -    } - -    rule add ( ps ) -    { -        if ! $(self.added.$(ps)) -        { -            self.added.$(ps) = [ property-set.create $(self.raw) [ $(ps).raw ] ] ; -        } -        return $(self.added.$(ps)) ; -    } - -    rule add-raw ( properties * ) -    { -        return [ add [ property-set.create $(properties) ] ] ; -    } - -    rule link-incompatible-with ( ps ) -    { -        if ! $(.li.$(ps)) -        { -            local li1 = [ $(__name__).link-incompatible ] ; -            local li2 = [ $(ps).link-incompatible ] ; -            if [ set.equal $(li1) : $(li2) ] -            { -                .li.$(ps) = false ; -            } -            else -            { -                .li.$(ps) = true ; -            } -        } -        if $(.li.$(ps)) = true -        { -            return true ; -        } -        else -        { -            return ; -        } -    } - -    # Returns all values of 'feature'. -    # -    rule get ( feature ) -    { -        if ! $(self.map-built) -        { -            # For each feature, create a member var and assign all values to it. -            # Since all regular member vars start with 'self', there will be no -            # conflicts between names. -            self.map-built = true ; -            for local v in $(self.raw) -            { -                $(v:G) += $(v:G=) ; -            } -        } -        return $($(feature)) ; -    } -} - - -# Creates a new 'property-set' instance for the given raw properties or returns -# an already existing ones. -# -rule create ( raw-properties * ) -{ -    raw-properties = [ sequence.unique -        [ sequence.insertion-sort $(raw-properties) ] ] ; - -    local key = $(raw-properties:J=-:E=) ; - -    if ! $(.ps.$(key)) -    { -        .ps.$(key) = [ new property-set $(raw-properties) ] ; -    } -    return $(.ps.$(key)) ; -} -NATIVE_RULE property-set : create ; - - -# Creates a new 'property-set' instance after checking that all properties are -# valid and converting incidental properties into gristed form. -# -rule create-with-validation ( raw-properties * ) -{ -    property.validate $(raw-properties) ; -    return [ create [ property.make $(raw-properties) ] ] ; -} - - -# Creates a property-set from the input given by the user, in the context of -# 'jamfile-module' at 'location'. -# -rule create-from-user-input ( raw-properties * : jamfile-module location ) -{ -    local specification = [ property.translate-paths $(raw-properties) -        : $(location) ] ; -    specification = [ property.translate-indirect $(specification) -        : $(jamfile-module) ] ; -    local project-id = [ project.attribute $(jamfile-module) id ] ; -    project-id ?= [ path.root $(location) [ path.pwd ] ] ; -    specification = [ property.translate-dependencies -                      $(specification) : $(project-id) : $(location) ] ; -    specification = -        [ property.expand-subfeatures-in-conditions $(specification) ] ; -    specification = [ property.make $(specification) ] ; -    return [ property-set.create $(specification) ] ; -} - - -# Refines requirements with requirements provided by the user. Specially handles -# "-<property>value" syntax in specification to remove given requirements. -# - parent-requirements -- property-set object with requirements to refine. -# - specification       -- string list of requirements provided by the user. -# - project-module      -- module to which context indirect features will be -#                          bound. -# - location            -- path to which path features are relative. -# -rule refine-from-user-input ( parent-requirements : specification * : -    project-module : location ) -{ -    if ! $(specification) -    { -        return $(parent-requirements) ; -    } -    else -    { -        local add-requirements ; -        local remove-requirements ; - -        for local r in $(specification) -        { -            local m = [ MATCH "^-(.*)" : $(r) ] ; -            if $(m) -            { -                remove-requirements += $(m) ; -            } -            else -            { -                add-requirements += $(r) ; -            } -        } - -        if $(remove-requirements) -        { -            # Need to create a property set, so that path features and indirect -            # features are translated just like they are in project -            # requirements. -            local ps = [ property-set.create-from-user-input -                $(remove-requirements) : $(project-module) $(location) ] ; - -            parent-requirements = [ property-set.create -                [ set.difference [ $(parent-requirements).raw ] -                : [ $(ps).raw ] ] ] ; -            specification = $(add-requirements) ; -        } - -        local requirements = [ property-set.create-from-user-input -            $(specification) : $(project-module) $(location) ] ; - -        return [ $(parent-requirements).refine $(requirements) ] ; -    } -} - - -# Returns a property-set with an empty set of properties. -# -rule empty ( ) -{ -    if ! $(.empty) -    { -        .empty = [ create ] ; -    } -    return $(.empty) ; -} - -if [ option.get hash : : yes ] = yes -{     -    rule hash-maybe ( path ? ) -    { -        path ?= "" ; -        return [ MD5 $(path) ] ; -    } -} -else -{ -    rule hash-maybe ( path ? ) -    { -        return $(path) ; -    }     -} - diff --git a/jam-files/boost-build/build/property.jam b/jam-files/boost-build/build/property.jam deleted file mode 100644 index a2ad5226..00000000 --- a/jam-files/boost-build/build/property.jam +++ /dev/null @@ -1,788 +0,0 @@ -# Copyright 2001, 2002, 2003 Dave Abrahams -# Copyright 2006 Rene Rivera -# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - -import errors ; -import feature ; -import indirect ; -import path ; -import regex ; -import string ; -import sequence ; -import set ; -import utility ; - - -# Refines 'properties' by overriding any non-free and non-conditional properties -# for which a different value is specified in 'requirements'. Returns the -# resulting list of properties. -# -rule refine ( properties * : requirements * ) -{ -    local result ; -    local error ; - -    # All the 'requirements' elements should be present in the result. Record -    # them so that we can handle 'properties'. -    for local r in $(requirements) -    { -        # Do not consider conditional requirements. -        if ! [ MATCH (:) : $(r:G=) ] -        { -            # Note: cannot use a local variable here, so use an ugly name. -            __require__$(r:G) = $(r:G=) ; -        } -    } - -    for local p in $(properties) -    { -        if [ MATCH (:) : $(p:G=) ] -        { -            # Do not modify conditional properties. -            result += $(p) ; -        } -        else if free in [ feature.attributes $(p:G) ] -        { -            # Do not modify free properties. -            result += $(p) ; -        } -        else -        { -            local required-value = $(__require__$(p:G)) ; -            if $(required-value) -            { -                if $(p:G=) != $(required-value) -                { -                    result += $(p:G)$(required-value) ; -                } -                else -                { -                    result += $(p) ; -                } -            } -            else -            { -                result += $(p) ; -            } -        } -    } - -    # Unset our ugly map. -    for local r in $(requirements) -    { -        __require__$(r:G) = ; -    } - -    if $(error) -    { -        return $(error) ; -    } -    else -    { -        return [ sequence.unique $(result) $(requirements) ] ; -    } -} - - -# Removes all conditional properties whose conditions are not met. For those -# with met conditions, removes the condition. Properties in conditions are -# looked up in 'context'. -# -rule evaluate-conditionals-in-context ( properties * : context * ) -{ -    local base ; -    local conditionals ; -    for local p in $(properties) -    { -        if [ MATCH (:<) : $(p) ] -        { -            conditionals += $(p) ; -        } -        else -        { -            base += $(p) ; -        } -    } - -    local result = $(base) ; -    for local p in $(conditionals) -    { -        # Separate condition and property. -        local s = [ MATCH (.*):(<.*) : $(p) ] ; -        # Split condition into individual properties. -        local condition = [ regex.split $(s[1]) "," ] ; -        # Evaluate condition. -        if ! [ MATCH (!).* : $(condition:G=) ] -        { -            # Only positive checks -            if $(condition) in $(context) -            { -                result += $(s[2]) ; -            } -        } -        else -        { -            # Have negative checks -            local fail ; -            while $(condition) -            { -                local c = $(condition[1]) ; -                local m = [ MATCH !(.*) : $(c) ] ; -                if $(m) -                { -                    local p = $(m:G=$(c:G)) ; -                    if $(p) in $(context) -                    { -                        fail = true ; -                        c = ; -                    }                     -                }     -                else -                { -                    if ! $(c) in $(context) -                    { -                        fail = true ; -                        c = ; -                    }                     -                } -                condition = $(condition[2-]) ; -            } -            if ! $(fail) -            { -                result += $(s[2]) ; -            }             -        }                 -    } -    return $(result) ; -} - - -rule expand-subfeatures-in-conditions ( properties * ) -{ -    local result ; -    for local p in $(properties) -    { -        local s = [ MATCH (.*):(<.*) : $(p) ] ; -        if ! $(s) -        { -            result += $(p) ; -        } -        else -        { -            local condition = $(s[1]) ; -            local value     = $(s[2]) ; -            # Condition might include several elements. -            condition = [ regex.split $(condition) "," ] ; -            local e ; -            for local c in $(condition) -            { -                # It is common for a condition to include a toolset or -                # subfeatures that have not been defined. In that case we want -                # the condition to simply 'never be satisfied' and validation -                # would only produce a spurious error so we prevent it by -                # passing 'true' as the second parameter. -                e += [ feature.expand-subfeatures $(c) : true ] ; -            } -            if $(e) = $(condition) -            { -                # (todo) -                #   This is just an optimization and possibly a premature one at -                # that. -                #                             (todo) (12.07.2008.) (Jurko) -                result += $(p) ; -            } -            else -            { -                result += $(e:J=,):$(value) ; -            } -        } -    } -    return $(result) ; -} - - -# Helper for as-path, below. Orders properties with the implicit ones first, and -# within the two sections in alphabetical order of feature name. -# -local rule path-order ( x y ) -{ -    if $(y:G) && ! $(x:G) -    { -        return true ; -    } -    else if $(x:G) && ! $(y:G) -    { -        return ; -    } -    else -    { -        if ! $(x:G) -        { -            x = [ feature.expand-subfeatures $(x) ] ; -            y = [ feature.expand-subfeatures $(y) ] ; -        } - -        if $(x[1]) < $(y[1]) -        { -            return true ; -        } -    } -} - - -local rule abbreviate-dashed ( string ) -{ -    local r ; -    for local part in [ regex.split $(string) - ] -    { -        r += [ string.abbreviate $(part) ] ; -    } -    return $(r:J=-) ; -} - - -local rule identity ( string ) -{ -    return $(string) ; -} - - -if --abbreviate-paths in [ modules.peek : ARGV ] -{ -    .abbrev = abbreviate-dashed ; -} -else -{ -    .abbrev = identity ; -} - - -# Returns a path representing the given expanded property set. -# -rule as-path ( properties * ) -{ -    local entry = .result.$(properties:J=-) ; - -    if ! $($(entry)) -    { -        # Trim redundancy. -        properties = [ feature.minimize $(properties) ] ; - -        # Sort according to path-order. -        properties = [ sequence.insertion-sort $(properties) : path-order ] ; - -        local components ; -        for local p in $(properties) -        { -            if $(p:G) -            { -                local f = [ utility.ungrist $(p:G) ] ; -                p = $(f)-$(p:G=) ; -            } -            components += [ $(.abbrev) $(p) ] ; -        } - -        $(entry) = $(components:J=/) ; -    } - -    return $($(entry)) ; -} - - -# Exit with error if property is not valid. -# -local rule validate1 ( property ) -{ -    local msg ; -    if $(property:G) -    { -        local feature = $(property:G) ; -        local value = $(property:G=) ; - -        if ! [ feature.valid $(feature) ] -        { -            # Ungrist for better error messages. -            feature = [ utility.ungrist $(property:G) ] ; -            msg = "unknown feature '$(feature)'" ; -        } -        else if $(value) && ! free in [ feature.attributes $(feature) ] -        { -            feature.validate-value-string $(feature) $(value) ; -        } -        else if ! ( $(value) || ( optional in [ feature.attributes $(feature) ] ) ) -        { -            # Ungrist for better error messages. -            feature = [ utility.ungrist $(property:G) ] ; -            msg = "No value specified for feature '$(feature)'" ; -        } -    } -    else -    { -        local feature = [ feature.implied-feature $(property) ] ; -        feature.validate-value-string $(feature) $(property) ; -    } -    if $(msg) -    { -        errors.error "Invalid property "'$(property:J=" ")'": "$(msg:J=" "). ; -    } -} - - -rule validate ( properties * ) -{ -    for local p in $(properties) -    { -        validate1 $(p) ; -    } -} - - -rule validate-property-sets ( property-sets * ) -{ -    for local s in $(property-sets) -    { -        validate [ feature.split $(s) ] ; -    } -} - - -# Expands any implicit property values in the given property 'specification' so -# they explicitly state their feature. -# -rule make ( specification * ) -{ -    local result ; -    for local e in $(specification) -    { -        if $(e:G) -        { -            result += $(e) ; -        } -        else if [ feature.is-implicit-value $(e) ] -        { -            local feature = [ feature.implied-feature $(e) ] ; -            result += $(feature)$(e) ; -        } -        else -        { -            errors.error "'$(e)' is not a valid property specification" ; -        } -    } -    return $(result) ; -} - - -# Returns a property set containing all the elements in 'properties' that do not -# have their attributes listed in 'attributes'. -# -rule remove ( attributes + : properties * ) -{ -    local result ; -    for local e in $(properties) -    { -        if ! [ set.intersection $(attributes) : [ feature.attributes $(e:G) ] ] -        { -            result += $(e) ; -        } -    } -    return $(result) ; -} - - -# Returns a property set containing all the elements in 'properties' that have -# their attributes listed in 'attributes'. -# -rule take ( attributes + : properties * ) -{ -    local result ; -    for local e in $(properties) -    { -        if [ set.intersection $(attributes) : [ feature.attributes $(e:G) ] ] -        { -            result += $(e) ; -        } -    } -    return $(result) ; -} - - -# Selects properties corresponding to any of the given features. -# -rule select ( features * : properties * ) -{ -    local result ; - -    # Add any missing angle brackets. -    local empty = "" ; -    features = $(empty:G=$(features)) ; - -    for local p in $(properties) -    { -        if $(p:G) in $(features) -        { -            result += $(p) ; -        } -    } -    return $(result) ; -} - - -# Returns a modified version of properties with all values of the given feature -# replaced by the given value. If 'value' is empty the feature will be removed. -# -rule change ( properties * : feature value ? ) -{ -    local result ; -    for local p in $(properties) -    { -        if $(p:G) = $(feature) -        { -            result += $(value:G=$(feature)) ; -        } -        else -        { -            result += $(p) ; -        } -    } -    return $(result) ; -} - - -# If 'property' is a conditional property, returns the condition and the -# property. E.g. <variant>debug,<toolset>gcc:<inlining>full will become -# <variant>debug,<toolset>gcc <inlining>full. Otherwise, returns an empty -# string. -# -rule split-conditional ( property ) -{ -    local m = [ MATCH "(.+):<(.+)" : $(property) ] ; -    if $(m) -    { -        return $(m[1]) <$(m[2]) ; -    } -} - - -# Interpret all path properties in 'properties' as relative to 'path'. The -# property values are assumed to be in system-specific form, and will be -# translated into normalized form. -# -rule translate-paths ( properties * : path ) -{ -    local result ; -    for local p in $(properties) -    { -        local split = [ split-conditional $(p) ] ; -        local condition = "" ; -        if $(split) -        { -            condition = $(split[1]): ; -            p = $(split[2]) ; -        } - -        if path in [ feature.attributes $(p:G) ] -        { -            local values = [ regex.split $(p:TG=) "&&" ] ; -            local t ; -            for local v in $(values) -            { -                t += [ path.root [ path.make $(v) ] $(path) ] ; -            } -            t = $(t:J="&&") ; -            result += $(condition)$(t:TG=$(p:G)) ; -        } -        else -        { -            result += $(condition)$(p) ; -        } -    } -    return $(result) ; -} - - -# Assumes that all feature values that start with '@' are names of rules, used -# in 'context-module'. Such rules can be either local to the module or global. -# Converts such values into 'indirect-rule' format (see indirect.jam), so they -# can be called from other modules. Does nothing for such values that are -# already in the 'indirect-rule' format. -# -rule translate-indirect ( specification * : context-module ) -{ -    local result ; -    for local p in $(specification) -    { -        local m = [ MATCH ^@(.+) : $(p:G=) ] ; -        if $(m) -        { -            local v ; -            if [ MATCH "^([^%]*)%([^%]+)$" : $(m) ] -            { -                # Rule is already in the 'indirect-rule' format. -                v = $(m) ; -            } -            else -            { -                if ! [ MATCH ".*([.]).*" : $(m) ] -                { -                    # This is an unqualified rule name. The user might want to -                    # set flags on this rule name and toolset.flag -                    # auto-qualifies it. Need to do the same here so flag -                    # setting works. We can arrange for toolset.flag to *not* -                    # auto-qualify the argument but then two rules defined in -                    # two Jamfiles would conflict. -                    m = $(context-module).$(m) ; -                } -                v = [ indirect.make $(m) : $(context-module) ] ; -            } - -            v = @$(v) ; -            result += $(v:G=$(p:G)) ; -        } -        else -        { -            result += $(p) ; -        } -    } -    return $(result) ; -} - - -# Binds all dependency properties in a list relative to the given project. -# Targets with absolute paths will be left unchanged and targets which have a -# project specified will have the path to the project interpreted relative to -# the specified location. -# -rule translate-dependencies ( specification * : project-id : location ) -{ -    local result ; -    for local p in $(specification) -    { -        local split = [ split-conditional $(p) ] ; -        local condition = "" ; -        if $(split) -        { -            condition = $(split[1]): ; -            p = $(split[2]) ; -        } -        if dependency in [ feature.attributes $(p:G) ] -        { -            local split-target = [ regex.match (.*)//(.*) : $(p:G=) ] ; -            if $(split-target) -            { -                local rooted = [ path.root [ path.make $(split-target[1]) ] -                     [ path.root $(location) [ path.pwd ] ] ] ; -                result += $(condition)$(p:G)$(rooted)//$(split-target[2]) ; -            } -            else if [ path.is-rooted $(p:G=) ] -            { -                result += $(condition)$(p) ; -            } -            else -            { -                result += $(condition)$(p:G)$(project-id)//$(p:G=) ; -            } -        } -        else -        { -            result += $(condition)$(p) ; -        } -    } -    return $(result) ; -} - - -# Class maintaining a property set -> string mapping. -# -class property-map -{ -    import errors ; -    import numbers ; -    import sequence ; - -    rule __init__ ( ) -    { -        self.next-flag = 1 ; -    } - -    # Associate 'value' with 'properties'. -    # -    rule insert ( properties + : value ) -    { -        self.all-flags += $(self.next-flag) ; -        self.properties.$(self.next-flag) = $(properties) ; -        self.value.$(self.next-flag) = $(value) ; - -        self.next-flag = [ numbers.increment $(self.next-flag) ] ; -    } - -    # Returns the value associated with 'properties' or any subset of it. If -    # more than one subset has a value assigned to it, returns the value for the -    # longest subset, if it is unique. -    # -    rule find ( properties + ) -    { -        return [ find-replace $(properties) ] ; -    } - -    # Returns the value associated with 'properties'. If 'value' parameter is -    # given, replaces the found value. -    # -    rule find-replace ( properties + : value ? ) -    { -        # First find all matches. -        local matches ; -        local match-ranks ; -        for local i in $(self.all-flags) -        { -            if $(self.properties.$(i)) in $(properties) -            { -                matches += $(i) ; -                match-ranks += [ sequence.length $(self.properties.$(i)) ] ; -            } -        } -        local best = [ sequence.select-highest-ranked $(matches) -            : $(match-ranks) ] ; -        if $(best[2]) -        {             -            errors.error "Ambiguous key $(properties:J= :E=)" ; -        } -        local original = $(self.value.$(best)) ; -        if $(value) -        { -            self.value.$(best) = $(value) ; -        } -        return $(original) ; -    } -} - - -rule __test__ ( ) -{ -    import assert ; -    import "class" : new ; -    import errors : try catch ; -    import feature ; - -    # Local rules must be explicitly re-imported. -    import property : path-order abbreviate-dashed ; - -    feature.prepare-test property-test-temp ; - -    feature.feature toolset : gcc : implicit symmetric ; -    feature.subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4 3.0 3.0.1 -        3.0.2 : optional ; -    feature.feature define : : free ; -    feature.feature runtime-link : dynamic static : symmetric link-incompatible ; -    feature.feature optimization : on off ; -    feature.feature variant : debug release : implicit composite symmetric ; -    feature.feature rtti : on off : link-incompatible ; - -    feature.compose <variant>debug : <define>_DEBUG <optimization>off ; -    feature.compose <variant>release : <define>NDEBUG <optimization>on ; - -    validate <toolset>gcc <toolset>gcc-3.0.1 : $(test-space) ; - -    assert.true  path-order $(test-space) debug <define>foo ; -    assert.false path-order $(test-space) <define>foo debug ; -    assert.true  path-order $(test-space) gcc debug ; -    assert.false path-order $(test-space) debug gcc ; -    assert.true  path-order $(test-space) <optimization>on <rtti>on ; -    assert.false path-order $(test-space) <rtti>on <optimization>on ; - -    assert.result-set-equal <toolset>gcc <rtti>off <define>FOO -        : refine <toolset>gcc <rtti>off -        : <define>FOO -        : $(test-space) ; - -    assert.result-set-equal <toolset>gcc <optimization>on -        : refine <toolset>gcc <optimization>off -        : <optimization>on -        : $(test-space) ; - -    assert.result-set-equal <toolset>gcc <rtti>off -        : refine <toolset>gcc : <rtti>off : $(test-space) ; - -    assert.result-set-equal <toolset>gcc <rtti>off <rtti>off:<define>FOO -        : refine <toolset>gcc : <rtti>off <rtti>off:<define>FOO -        : $(test-space) ; - -    assert.result-set-equal <toolset>gcc:<define>foo <toolset>gcc:<define>bar -        : refine <toolset>gcc:<define>foo : <toolset>gcc:<define>bar -        : $(test-space) ; - -    assert.result <define>MY_RELEASE -        : evaluate-conditionals-in-context -          <variant>release,<rtti>off:<define>MY_RELEASE -        : <toolset>gcc <variant>release <rtti>off ; - -    assert.result debug -        : as-path <optimization>off <variant>debug -        : $(test-space) ; - -    assert.result gcc/debug/rtti-off -        : as-path <toolset>gcc <optimization>off <rtti>off <variant>debug -        : $(test-space) ; - -    assert.result optmz-off : abbreviate-dashed optimization-off ; -    assert.result rntm-lnk-sttc : abbreviate-dashed runtime-link-static ; - -    try ; -        validate <feature>value : $(test-space) ; -    catch "Invalid property '<feature>value': unknown feature 'feature'." ; - -    try ; -        validate <rtti>default : $(test-space) ; -    catch \"default\" is not a known value of feature <rtti> ; - -    validate <define>WHATEVER : $(test-space) ; - -    try ; -        validate <rtti> : $(test-space) ; -    catch "Invalid property '<rtti>': No value specified for feature 'rtti'." ; - -    try ; -        validate value : $(test-space) ; -    catch "value" is not a value of an implicit feature ; - -    assert.result-set-equal <rtti>on -        : remove free implicit : <toolset>gcc <define>foo <rtti>on : $(test-space) ; - -    assert.result-set-equal <include>a -        : select include : <include>a <toolset>gcc ; - -    assert.result-set-equal <include>a -        : select include bar : <include>a <toolset>gcc ; - -    assert.result-set-equal <include>a <toolset>gcc -        : select include <bar> <toolset> : <include>a <toolset>gcc ; - -    assert.result-set-equal <toolset>kylix <include>a -        : change <toolset>gcc <include>a : <toolset> kylix ; - -    pm = [ new property-map ] ; -    $(pm).insert <toolset>gcc : o ; -    $(pm).insert <toolset>gcc <os>NT : obj ; -    $(pm).insert <toolset>gcc <os>CYGWIN : obj ; - -    assert.equal o : [ $(pm).find <toolset>gcc ] ; - -    assert.equal obj : [ $(pm).find <toolset>gcc <os>NT ] ; - -    try ; -        $(pm).find <toolset>gcc <os>NT <os>CYGWIN ; -    catch "Ambiguous key <toolset>gcc <os>NT <os>CYGWIN" ; - -    # Test ordinary properties. -    assert.result : split-conditional <toolset>gcc ; - -    # Test properties with ":". -    assert.result : split-conditional <define>FOO=A::B ; - -    # Test conditional feature. -    assert.result-set-equal <toolset>gcc,<toolset-gcc:version>3.0 <define>FOO -        : split-conditional <toolset>gcc,<toolset-gcc:version>3.0:<define>FOO ; - -    feature.finish-test property-test-temp ; -} diff --git a/jam-files/boost-build/build/property.py b/jam-files/boost-build/build/property.py deleted file mode 100644 index c4b13dbc..00000000 --- a/jam-files/boost-build/build/property.py +++ /dev/null @@ -1,593 +0,0 @@ -# Status: ported, except for tests and --abbreviate-paths. -# Base revision: 64070 -# -# Copyright 2001, 2002, 2003 Dave Abrahams  -# Copyright 2006 Rene Rivera  -# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus  -# Distributed under the Boost Software License, Version 1.0.  -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)  - -import re -from b2.util.utility import * -from b2.build import feature -from b2.util import sequence, qualify_jam_action -import b2.util.set -from b2.manager import get_manager - -__re_two_ampersands = re.compile ('&&') -__re_comma = re.compile (',') -__re_split_condition = re.compile ('(.*):(<.*)') -__re_split_conditional = re.compile (r'(.+):<(.+)') -__re_colon = re.compile (':') -__re_has_condition = re.compile (r':<') -__re_separate_condition_and_property = re.compile (r'(.*):(<.*)') - -class Property(object): - -    __slots__ = ('_feature', '_value', '_condition') - -    def __init__(self, f, value, condition = []): -        if type(f) == type(""): -            f = feature.get(f) -        # At present, single property has a single value. -        assert type(value) != type([]) -        assert(f.free() or value.find(':') == -1) -        self._feature = f -        self._value = value -        self._condition = condition -         -    def feature(self): -        return self._feature - -    def value(self): -        return self._value - -    def condition(self): -        return self._condition - -    def to_raw(self): -        result = "<" + self._feature.name() + ">" + str(self._value) -        if self._condition: -            result = ",".join(str(p) for p in self._condition) + ':' + result -        return result - -    def __str__(self): -        return self.to_raw() - -    def __hash__(self): -        # FIXME: consider if this class should be value-is-identity one -        return hash((self._feature, self._value, tuple(self._condition))) - -    def __cmp__(self, other): -        return cmp((self._feature, self._value, self._condition), -                   (other._feature, other._value, other._condition)) -                            - -def create_from_string(s, allow_condition=False): - -    condition = [] -    import types -    if not isinstance(s, types.StringType): -        print type(s) -    if __re_has_condition.search(s): - -        if not allow_condition: -            raise BaseException("Conditional property is not allowed in this context") - -        m = __re_separate_condition_and_property.match(s) -        condition = m.group(1) -        s = m.group(2) - -    # FIXME: break dependency cycle -    from b2.manager import get_manager - -    feature_name = get_grist(s) -    if not feature_name: -        if feature.is_implicit_value(s): -            f = feature.implied_feature(s) -            value = s -        else:         -            raise get_manager().errors()("Invalid property '%s' -- unknown feature" % s) -    else: -        f = feature.get(feature_name)         - -        value = get_value(s) -        if not value: -            get_manager().errors()("Invalid property '%s' -- no value specified" % s) - - -    if condition: -        condition = [create_from_string(x) for x in condition.split(',')] -                    -    return Property(f, value, condition) - -def create_from_strings(string_list, allow_condition=False): - -    return [create_from_string(s, allow_condition) for s in string_list] - -def reset (): -    """ Clear the module state. This is mainly for testing purposes. -    """ -    global __results - -    # A cache of results from as_path -    __results = {} -     -reset () - -         -def path_order (x, y): -    """ Helper for as_path, below. Orders properties with the implicit ones -        first, and within the two sections in alphabetical order of feature -        name. -    """ -    if x == y: -        return 0 -         -    xg = get_grist (x) -    yg = get_grist (y) - -    if yg and not xg: -        return -1 - -    elif xg and not yg: -        return 1 - -    else: -        if not xg:             -            x = feature.expand_subfeatures([x]) -            y = feature.expand_subfeatures([y]) -         -        if x < y: -            return -1 -        elif x > y: -            return 1 -        else: -            return 0 - -def identify(string): -    return string  - -# Uses Property -def refine (properties, requirements): -    """ Refines 'properties' by overriding any non-free properties  -        for which a different value is specified in 'requirements'.  -        Conditional requirements are just added without modification. -        Returns the resulting list of properties. -    """ -    # The result has no duplicates, so we store it in a set -    result = set() -     -    # Records all requirements. -    required = {} -     -    # All the elements of requirements should be present in the result -    # Record them so that we can handle 'properties'. -    for r in requirements: -        # Don't consider conditional requirements. -        if not r.condition(): -            required[r.feature()] = r - -    for p in properties: -        # Skip conditional properties -        if p.condition(): -            result.add(p) -        # No processing for free properties -        elif p.feature().free(): -            result.add(p) -        else: -            if required.has_key(p.feature()): -                result.add(required[p.feature()]) -            else: -                result.add(p) - -    return sequence.unique(list(result) + requirements) - -def translate_paths (properties, path): -    """ Interpret all path properties in 'properties' as relative to 'path' -        The property values are assumed to be in system-specific form, and -        will be translated into normalized form. -        """ -    result = [] - -    for p in properties: - -        if p.feature().path(): -            values = __re_two_ampersands.split(p.value()) -             -            new_value = "&&".join(os.path.join(path, v) for v in values) - -            if new_value != p.value(): -                result.append(Property(p.feature(), new_value, p.condition())) -            else: -                result.append(p) -             -        else: -            result.append (p) - -    return result - -def translate_indirect(properties, context_module): -    """Assumes that all feature values that start with '@' are -    names of rules, used in 'context-module'. Such rules can be -    either local to the module or global. Qualified local rules -    with the name of the module.""" -    result = [] -    for p in properties: -        if p.value()[0] == '@': -            q = qualify_jam_action(p.value()[1:], context_module) -            get_manager().engine().register_bjam_action(q) -            result.append(Property(p.feature(), '@' + q, p.condition())) -        else: -            result.append(p) - -    return result - -def validate (properties): -    """ Exit with error if any of the properties is not valid. -        properties may be a single property or a sequence of properties. -    """ -     -    if isinstance (properties, str): -        __validate1 (properties) -    else: -        for p in properties: -            __validate1 (p) - -def expand_subfeatures_in_conditions (properties): - -    result = [] -    for p in properties: - -        if not p.condition(): -            result.append(p) -        else: -            expanded = [] -            for c in p.condition(): - -                if c.feature().name().startswith("toolset") or c.feature().name() == "os": -                    # It common that condition includes a toolset which -                    # was never defined, or mentiones subfeatures which -                    # were never defined. In that case, validation will -                    # only produce an spirious error, so don't validate. -                    expanded.extend(feature.expand_subfeatures ([c], True)) -                else: -                    expanded.extend(feature.expand_subfeatures([c])) - -            result.append(Property(p.feature(), p.value(), expanded)) - -    return result - -# FIXME: this should go -def split_conditional (property): -    """ If 'property' is conditional property, returns -        condition and the property, e.g -        <variant>debug,<toolset>gcc:<inlining>full will become -        <variant>debug,<toolset>gcc <inlining>full. -        Otherwise, returns empty string. -    """ -    m = __re_split_conditional.match (property) -     -    if m: -        return (m.group (1), '<' + m.group (2)) - -    return None - - -def select (features, properties): -    """ Selects properties which correspond to any of the given features. -    """ -    result = [] -     -    # add any missing angle brackets -    features = add_grist (features) - -    return [p for p in properties if get_grist(p) in features] - -def validate_property_sets (sets): -    for s in sets: -        validate(s.all()) - -def evaluate_conditionals_in_context (properties, context): -    """ Removes all conditional properties which conditions are not met -        For those with met conditions, removes the condition. Properies -        in conditions are looked up in 'context' -    """ -    base = [] -    conditional = [] - -    for p in properties: -        if p.condition(): -            conditional.append (p) -        else: -            base.append (p) - -    result = base[:] -    for p in conditional: - -        # Evaluate condition -        # FIXME: probably inefficient -        if all(x in context for x in p.condition()): -            result.append(Property(p.feature(), p.value())) - -    return result - - -def change (properties, feature, value = None): -    """ Returns a modified version of properties with all values of the -        given feature replaced by the given value. -        If 'value' is None the feature will be removed. -    """ -    result = [] -     -    feature = add_grist (feature) - -    for p in properties: -        if get_grist (p) == feature: -            if value: -                result.append (replace_grist (value, feature)) - -        else: -            result.append (p) - -    return result - - -################################################################ -# Private functions - -def __validate1 (property): -    """ Exit with error if property is not valid. -    """         -    msg = None - -    if not property.feature().free(): -        feature.validate_value_string (property.feature(), property.value()) - - -################################################################### -# Still to port. -# Original lines are prefixed with "#   " -# -#    -#   import utility : ungrist ; -#   import sequence : unique ; -#   import errors : error ; -#   import feature ; -#   import regex ; -#   import sequence ; -#   import set ; -#   import path ; -#   import assert ; -#    -#    - - -#   rule validate-property-sets ( property-sets * ) -#   { -#       for local s in $(property-sets) -#       { -#           validate [ feature.split $(s) ] ; -#       } -#   } -# - -def remove(attributes, properties): -    """Returns a property sets which include all the elements -    in 'properties' that do not have attributes listed in 'attributes'.""" -     -    result = [] -    for e in properties: -        attributes_new = feature.attributes(get_grist(e)) -        has_common_features = 0 -        for a in attributes_new: -            if a in attributes: -                has_common_features = 1 -                break - -        if not has_common_features: -            result += e - -    return result - - -def take(attributes, properties): -    """Returns a property set which include all -    properties in 'properties' that have any of 'attributes'.""" -    result = [] -    for e in properties: -        if b2.util.set.intersection(attributes, feature.attributes(get_grist(e))): -            result.append(e) -    return result - -def translate_dependencies(properties, project_id, location): - -    result = [] -    for p in properties: - -        if not p.feature().dependency(): -            result.append(p) -        else: -            v = p.value() -            m = re.match("(.*)//(.*)", v) -            if m: -                rooted = m.group(1) -                if rooted[0] == '/': -                    # Either project id or absolute Linux path, do nothing. -                    pass -                else: -                    rooted = os.path.join(os.getcwd(), location, rooted) -                     -                result.append(Property(p.feature(), rooted + "//" + m.group(2), p.condition())) -                 -            elif os.path.isabs(v):                 -                result.append(p) -            else: -                result.append(Property(p.feature(), project_id + "//" + v, p.condition())) - -    return result - - -class PropertyMap: -    """ Class which maintains a property set -> string mapping. -    """ -    def __init__ (self): -        self.__properties = [] -        self.__values = [] -     -    def insert (self, properties, value): -        """ Associate value with properties. -        """ -        self.__properties.append(properties) -        self.__values.append(value) - -    def find (self, properties): -        """ Return the value associated with properties -        or any subset of it. If more than one -        subset has value assigned to it, return the -        value for the longest subset, if it's unique. -        """ -        return self.find_replace (properties) - -    def find_replace(self, properties, value=None): -        matches = [] -        match_ranks = [] -         -        for i in range(0, len(self.__properties)): -            p = self.__properties[i] -                         -            if b2.util.set.contains (p, properties): -                matches.append (i) -                match_ranks.append(len(p)) - -        best = sequence.select_highest_ranked (matches, match_ranks) - -        if not best: -            return None - -        if len (best) > 1: -            raise NoBestMatchingAlternative () - -        best = best [0] -             -        original = self.__values[best] - -        if value: -            self.__values[best] = value - -        return original - -#   local rule __test__ ( ) -#   { -#       import errors : try catch ; -#       import feature ; -#       import feature : feature subfeature compose ; -#        -#       # local rules must be explicitly re-imported -#       import property : path-order ; -#        -#       feature.prepare-test property-test-temp ; -#    -#       feature toolset : gcc : implicit symmetric ; -#       subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4 -#         3.0 3.0.1 3.0.2 : optional ; -#       feature define : : free ; -#       feature runtime-link : dynamic static : symmetric link-incompatible ; -#       feature optimization : on off ; -#       feature variant : debug release : implicit composite symmetric ; -#       feature rtti : on off : link-incompatible ; -#    -#       compose <variant>debug : <define>_DEBUG <optimization>off ; -#       compose <variant>release : <define>NDEBUG <optimization>on ; -#    -#       import assert ; -#       import "class" : new ; -#        -#       validate <toolset>gcc  <toolset>gcc-3.0.1 : $(test-space) ; -#        -#       assert.result <toolset>gcc <rtti>off <define>FOO -#           : refine <toolset>gcc <rtti>off -#           : <define>FOO -#           : $(test-space) -#           ; -#    -#       assert.result <toolset>gcc <optimization>on -#           : refine <toolset>gcc <optimization>off -#           : <optimization>on -#           : $(test-space) -#           ; -#    -#       assert.result <toolset>gcc <rtti>off -#           : refine <toolset>gcc : <rtti>off : $(test-space) -#           ; -#    -#       assert.result <toolset>gcc <rtti>off <rtti>off:<define>FOO -#           : refine <toolset>gcc : <rtti>off <rtti>off:<define>FOO  -#           : $(test-space) -#           ; -#        -#       assert.result <toolset>gcc:<define>foo <toolset>gcc:<define>bar  -#           : refine <toolset>gcc:<define>foo : <toolset>gcc:<define>bar  -#           : $(test-space) -#           ; -#    -#       assert.result <define>MY_RELEASE -#           : evaluate-conditionals-in-context  -#             <variant>release,<rtti>off:<define>MY_RELEASE -#             : <toolset>gcc <variant>release <rtti>off -#                     -#           ; -#    -#       try ; -#           validate <feature>value : $(test-space) ; -#       catch "Invalid property '<feature>value': unknown feature 'feature'." ; -#    -#       try ; -#           validate <rtti>default : $(test-space) ; -#       catch \"default\" is not a known value of feature <rtti> ; -#        -#       validate <define>WHATEVER : $(test-space) ; -#    -#       try ; -#           validate <rtti> : $(test-space) ; -#       catch "Invalid property '<rtti>': No value specified for feature 'rtti'." ; -#    -#       try ; -#           validate value : $(test-space) ; -#       catch "value" is not a value of an implicit feature ; -#               -#    -#       assert.result <rtti>on  -#           : remove free implicit : <toolset>gcc <define>foo <rtti>on : $(test-space) ; -#    -#       assert.result <include>a  -#           : select include : <include>a <toolset>gcc ; -#    -#       assert.result <include>a  -#           : select include bar : <include>a <toolset>gcc ; -#    -#       assert.result <include>a <toolset>gcc -#           : select include <bar> <toolset> : <include>a <toolset>gcc ; -#        -#       assert.result <toolset>kylix <include>a  -#           : change <toolset>gcc <include>a : <toolset> kylix ; -#    -#       # Test ordinary properties  -#       assert.result  -#         : split-conditional <toolset>gcc  -#         ; -#        -#       # Test properties with ":" -#       assert.result -#         : split-conditional <define>FOO=A::B -#         ; -#        -#       # Test conditional feature -#       assert.result <toolset>gcc,<toolset-gcc:version>3.0 <define>FOO -#         : split-conditional <toolset>gcc,<toolset-gcc:version>3.0:<define>FOO -#         ; -#        -#       feature.finish-test property-test-temp ; -#   } -#    -     diff --git a/jam-files/boost-build/build/property_set.py b/jam-files/boost-build/build/property_set.py deleted file mode 100644 index f12eb90c..00000000 --- a/jam-files/boost-build/build/property_set.py +++ /dev/null @@ -1,449 +0,0 @@ -# Status: ported. -# Base revision: 40480 - -#  Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and -#  distribute this software is granted provided this copyright notice appears in -#  all copies. This software is provided "as is" without express or implied -#  warranty, and with no claim as to its suitability for any purpose. - -from b2.util.utility import * -import property, feature, string -import b2.build.feature -from b2.exceptions import * -from b2.util.sequence import unique -from b2.util.set import difference -from b2.util import cached - -from b2.manager import get_manager - - -def reset (): -    """ Clear the module state. This is mainly for testing purposes. -    """ -    global __cache - -    # A cache of property sets -    # TODO: use a map of weak refs? -    __cache = {} -     -reset () - - -def create (raw_properties = []): -    """ Creates a new 'PropertySet' instance for the given raw properties, -        or returns an already existing one. -    """ -    # FIXME: propagate to callers. -    if len(raw_properties) > 0 and isinstance(raw_properties[0], property.Property): -        x = raw_properties -    else:         -        x = [property.create_from_string(ps) for ps in raw_properties] -    x.sort() -    x = unique (x) - -    # FIXME: can we do better, e.g. by directly computing -    # has value of the list? -    key = tuple(x) - -    if not __cache.has_key (key): -        __cache [key] = PropertySet(x) - -    return __cache [key] - -def create_with_validation (raw_properties): -    """ Creates new 'PropertySet' instances after checking -        that all properties are valid and converting incidental -        properties into gristed form. -    """ -    properties = [property.create_from_string(s) for s in raw_properties] -    property.validate(properties) -     -    return create(properties) - -def empty (): -    """ Returns PropertySet with empty set of properties. -    """ -    return create () - -def create_from_user_input(raw_properties, jamfile_module, location): -    """Creates a property-set from the input given by the user, in the -    context of 'jamfile-module' at 'location'""" - -    properties = property.create_from_strings(raw_properties, True) -    properties = property.translate_paths(properties, location) -    properties = property.translate_indirect(properties, jamfile_module) - -    project_id = get_manager().projects().attributeDefault(jamfile_module, 'id', None) -    if not project_id: -        project_id = os.path.abspath(location)     -    properties = property.translate_dependencies(properties, project_id, location) -    properties = property.expand_subfeatures_in_conditions(properties) -    return create(properties) - - -def refine_from_user_input(parent_requirements, specification, jamfile_module, -                           location): -    """Refines requirements with requirements provided by the user. -    Specially handles "-<property>value" syntax in specification -     to remove given requirements. -     - parent-requirements -- property-set object with requirements -       to refine -     - specification -- string list of requirements provided by the use -     - project-module -- the module to which context indirect features -       will be bound. -     - location -- the path to which path features are relative.""" - - -    if not specification: -        return parent_requirements - -     -    add_requirements = [] -    remove_requirements = [] - -    for r in specification: -        if r[0] == '-': -            remove_requirements.append(r[1:]) -        else: -            add_requirements.append(r) -         -    if remove_requirements: -        # Need to create property set, so that path features -        # and indirect features are translated just like they -        # are in project requirements. -        ps = create_from_user_input(remove_requirements, -                                    jamfile_module, location) -         -        parent_requirements = create(difference(parent_requirements.all(), -                                                ps.all())) -        specification = add_requirements - -    requirements = create_from_user_input(specification, -                                          jamfile_module, location) -         -    return parent_requirements.refine(requirements) -     -class PropertySet: -    """ Class for storing a set of properties. -        - there's 1<->1 correspondence between identity and value. No -          two instances of the class are equal. To maintain this property, -          the 'PropertySet.create' rule should be used to create new instances. -          Instances are immutable. - -        - each property is classified with regard to it's effect on build -          results. Incidental properties have no effect on build results, from -          Boost.Build point of view. Others are either free, or non-free, which we -          call 'base'. Each property belong to exactly one of those categories and -          it's possible to get list of properties in each category. - -          In addition, it's possible to get list of properties with specific -          attribute. - -        - several operations, like and refine and as_path are provided. They all use -          caching whenever possible. -    """ -    def __init__ (self, properties = []): - - -        raw_properties = [] -        for p in properties: -            raw_properties.append(p.to_raw()) - -        self.all_ = properties -        self.all_raw_ = raw_properties -        self.all_set_ = set(properties) -         -        self.incidental_ = [] -        self.free_ = [] -        self.base_ = [] -        self.dependency_ = [] -        self.non_dependency_ = [] -        self.conditional_ = [] -        self.non_conditional_ = [] -        self.propagated_ = [] -        self.link_incompatible = [] -         -        # A cache of refined properties. -        self.refined_ = {} -         -        # A cache of property sets created by adding properties to this one. -        self.added_ = {} - -        # Cache for the default properties. -        self.defaults_ = None - -        # Cache for the expanded properties. -        self.expanded_ = None - -        # Cache for the expanded composite properties -        self.composites_ = None - -        # Cache for property set with expanded subfeatures -        self.subfeatures_ = None - -        # Cache for the property set containing propagated properties. -        self.propagated_ps_ = None -         -        # A map of features to its values. -        self.feature_map_ = None -         -        # A tuple (target path, is relative to build directory) -        self.target_path_ = None -         -        self.as_path_ = None -         -        # A cache for already evaluated sets. -        self.evaluated_ = {} -         -        for p in raw_properties: -            if not get_grist (p): -                raise BaseException ("Invalid property: '%s'" % p) -             -            att = feature.attributes (get_grist (p)) -                                                                    -            if 'propagated' in att: -                self.propagated_.append (p) - -            if 'link_incompatible' in att: -                self.link_incompatible.append (p) - -        for p in properties: - -            # A feature can be both incidental and free, -            # in which case we add it to incidental. -            if p.feature().incidental(): -                self.incidental_.append(p) -            elif p.feature().free(): -                self.free_.append(p) -            else: -                self.base_.append(p) - -            if p.condition(): -                self.conditional_.append(p) -            else: -                self.non_conditional_.append(p) - -            if p.feature().dependency(): -                self.dependency_.append (p) -            else: -                self.non_dependency_.append (p) -                 - -    def all(self): -        return self.all_ -     -    def raw (self): -        """ Returns the list of stored properties. -        """ -        return self.all_raw_ - -    def __str__(self): -        return ' '.join(str(p) for p in self.all_) -     -    def base (self): -        """ Returns properties that are neither incidental nor free. -        """ -        return self.base_ -     -    def free (self): -        """ Returns free properties which are not dependency properties. -        """ -        return self.free_ - -    def non_free(self): -        return self.base_ + self.incidental_ - -    def dependency (self): -        """ Returns dependency properties. -        """ -        return self.dependency_ -     -    def non_dependency (self): -        """ Returns properties that are not dependencies. -        """ -        return self.non_dependency_ -     -    def conditional (self): -        """ Returns conditional properties. -        """ -        return self.conditional_ -         -    def non_conditional (self): -        """ Returns properties that are not conditional. -        """ -        return self.non_conditional_ -               -    def incidental (self): -        """ Returns incidental properties. -        """ -        return self.incidental_ -     -    def refine (self, requirements): -        """ Refines this set's properties using the requirements passed as an argument. -        """ -        assert isinstance(requirements, PropertySet) -        if not self.refined_.has_key (requirements): -            r = property.refine(self.all_, requirements.all_) - -            self.refined_[requirements] = create(r) - -        return self.refined_[requirements] - -    def expand (self): -        if not self.expanded_: -            expanded = feature.expand(self.all_) -            self.expanded_ = create(expanded) -        return self.expanded_ - -    def expand_subfeatures(self): -        if not self.subfeatures_: -            self.subfeatures_ = create(feature.expand_subfeatures(self.all_)) -        return self.subfeatures_ - -    def evaluate_conditionals(self, context=None): -        if not context: -            context = self - -        if not self.evaluated_.has_key(context): -            # FIXME: figure why the call messes up first parameter -            self.evaluated_[context] = create( -                property.evaluate_conditionals_in_context(self.all(), context)) - -        return self.evaluated_[context] - -    def propagated (self): -        if not self.propagated_ps_: -            self.propagated_ps_ = create (self.propagated_) -        return self.propagated_ps_ - -    def add_defaults (self): -        # FIXME: this caching is invalidated when new features -        # are declare inside non-root Jamfiles. -        if not self.defaults_: -            expanded = feature.add_defaults(self.all_) -            self.defaults_ = create(expanded) -        return self.defaults_ - -    def as_path (self): -        if not self.as_path_: - -            def path_order (p1, p2): - -                i1 = p1.feature().implicit() -                i2 = p2.feature().implicit() - -                if i1 != i2: -                    return i2 - i1 -                else: -                    return cmp(p1.feature().name(), p2.feature().name()) - -            # trim redundancy -            properties = feature.minimize(self.base_) -                 -            # sort according to path_order -            properties.sort (path_order) -                 -            components = [] -            for p in properties: -                if p.feature().implicit(): -                    components.append(p.value()) -                else: -                    components.append(p.feature().name() + "-" + p.value()) - -            self.as_path_ = '/'.join (components) - -        return self.as_path_ - -    def target_path (self): -        """ Computes the target path that should be used for  -            target with these properties. -            Returns a tuple of -              - the computed path -              - if the path is relative to build directory, a value of -                'true'.  -        """ -        if not self.target_path_: -            # The <location> feature can be used to explicitly -            # change the location of generated targets -            l = self.get ('<location>') -            if l: -                computed = l[0] -                is_relative = False - -            else: -                p = self.as_path () -                 -                # Really, an ugly hack. Boost regression test system requires -                # specific target paths, and it seems that changing it to handle -                # other directory layout is really hard. For that reason, -                # we teach V2 to do the things regression system requires. -                # The value o '<location-prefix>' is predended to the path. -                prefix = self.get ('<location-prefix>') -                 -                if prefix: -                    if len (prefix) > 1: -                        raise AlreadyDefined ("Two <location-prefix> properties specified: '%s'" % prefix) -                         -                    computed = os.path.join(prefix[0], p) - -                else: -                    computed = p - -                if not computed: -                    computed = "." - -                is_relative = True - -            self.target_path_ = (computed, is_relative) - -        return self.target_path_ -                     -    def add (self, ps): -        """ Creates a new property set containing the properties in this one, -            plus the ones of the property set passed as argument. -        """ -        if not self.added_.has_key(ps): -            self.added_[ps] = create(self.all_ + ps.all()) -        return self.added_[ps] -     -    def add_raw (self, properties): -        """ Creates a new property set containing the properties in this one, -            plus the ones passed as argument. -        """ -        return self.add (create (properties)) - -     -    def get (self, feature): -        """ Returns all values of 'feature'. -        """ -        if type(feature) == type([]): -            feature = feature[0] -        if not isinstance(feature, b2.build.feature.Feature): -            feature = b2.build.feature.get(feature) -         -        if not self.feature_map_: -            self.feature_map_ = {} - -            for v in self.all_: -                if not self.feature_map_.has_key(v.feature()): -                    self.feature_map_[v.feature()] = [] -                self.feature_map_[v.feature()].append(v.value()) -         -        return self.feature_map_.get(feature, []) - -    @cached -    def get_properties(self, feature): -        """Returns all contained properties associated with 'feature'""" - -        if not isinstance(feature, b2.build.feature.Feature): -            feature = b2.build.feature.get(feature) - -        result = []         -        for p in self.all_: -            if p.feature() == feature: -                result.append(p) -        return result -     -    def __contains__(self, item): -        return item in self.all_set_ -     diff --git a/jam-files/boost-build/build/readme.txt b/jam-files/boost-build/build/readme.txt deleted file mode 100644 index c3dddd8d..00000000 --- a/jam-files/boost-build/build/readme.txt +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2001, 2002 Dave Abrahams  -Copyright 2002 Vladimir Prus  -Distributed under the Boost Software License, Version 1.0.  -(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)  - -Development code for new build system. To run unit tests for jam code, execute: - -  bjam --debug --build-system=test - -Comprehensive tests require Python. See ../test/readme.txt - - - diff --git a/jam-files/boost-build/build/scanner.jam b/jam-files/boost-build/build/scanner.jam deleted file mode 100644 index d6042ea2..00000000 --- a/jam-files/boost-build/build/scanner.jam +++ /dev/null @@ -1,153 +0,0 @@ -# Copyright 2003 Dave Abrahams  -# Copyright 2002, 2003, 2004, 2005 Vladimir Prus  -# Distributed under the Boost Software License, Version 1.0.  -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)  - -#  Implements scanners: objects that compute implicit dependencies for -#  files, such as includes in C++. -# -#  Scanner has a regular expression used to find dependencies, some -#  data needed to interpret those dependencies (for example, include -#  paths), and a code which actually established needed relationship -#  between actual jam targets. -# -#  Scanner objects are created by actions, when they try to actualize -#  virtual targets, passed to 'virtual-target.actualize' method and are -#  then associated with actual targets. It is possible to use -#  several scanners for a virtual-target. For example, a single source -#  might be used by to compile actions, with different include paths. -#  In this case, two different actual targets will be created, each  -#  having scanner of its own. -# -#  Typically, scanners are created from target type and action's  -#  properties, using the rule 'get' in this module. Directly creating -#  scanners is not recommended, because it might create many equvivalent -#  but different instances, and lead in unneeded duplication of -#  actual targets. However, actions can also create scanners in a special -#  way, instead of relying on just target type. - -import "class" : new ; -import property virtual-target property-set ; -import errors : error ; - -#  Base scanner class.  -class scanner  -{ -    rule __init__ ( ) -    { -    } -     -    # Returns a pattern to use for scanning -    rule pattern ( ) -    { -        error "method must be overriden" ; -    } - -    # Establish necessary relationship between targets, -    # given actual target beeing scanned, and a list of -    # pattern matches in that file. -    rule process ( target : matches * ) -    { -        error "method must be overriden" ; -    }         -} - -# Registers a new generator class, specifying a set of  -# properties relevant to this scanner.  Ctor for that class -# should have one parameter: list of properties. -rule register ( scanner-class : relevant-properties * ) -{ -    .registered += $(scanner-class) ; -    .relevant-properties.$(scanner-class) = $(relevant-properties) ; -} - -# Common scanner class, which can be used when there's only one -# kind of includes (unlike C, where "" and <> includes have different -# search paths). -class common-scanner : scanner  -{ -    import scanner ; -    rule __init__ ( includes * ) -    { -        scanner.__init__ ; -        self.includes = $(includes) ; -    } -             -    rule process ( target : matches * : binding ) -    { -        local target_path = [ NORMALIZE_PATH $(binding:D) ] ; - -        NOCARE $(matches) ; -        INCLUDES $(target) : $(matches) ; -        SEARCH on $(matches) = $(target_path) $(self.includes:G=) ; -        ISFILE $(matches) ; -     -        scanner.propagate $(__name__) : $(matches) : $(target) ;      -    } -} - - -# Returns an instance of previously registered scanner, -# with the specified properties. -rule get ( scanner-class : property-set )  -{ -    if ! $(scanner-class) in $(.registered) -    { -        error "attempt to get unregisted scanner" ; -    } -     -    local r = $(.rv-cache.$(property-set)) ; -    if ! $(r) -    { -        r = [ property-set.create  -            [ property.select $(.relevant-properties.$(scanner-class)) : -              [ $(property-set).raw ] ] ] ;         -        .rv-cache.$(property-set) = $(r) ; -    } -         -    if ! $(scanner.$(scanner-class).$(r:J=-)) -    { -        scanner.$(scanner-class).$(r:J=-) = [ new $(scanner-class) [ $(r).raw ] ] ; -    } -    return $(scanner.$(scanner-class).$(r:J=-)) ;     -} - - -# Installs the specified scanner on actual target 'target'.  -rule install ( scanner : target  -    vtarget # virtual target from which 'target' was actualized -) -{ -    HDRSCAN on $(target) = [ $(scanner).pattern ] ; -    SCANNER on $(target) = $(scanner) ; -    HDRRULE on $(target) = scanner.hdrrule ; -     -    # scanner reflects difference in properties affecting     -    # binding of 'target', which will be known when processing -    # includes for it, will give information on how to -    # interpret quoted includes. -    HDRGRIST on $(target) = $(scanner) ; -} - -# Propagate scanner setting from 'including-target' to 'targets'. -rule propagate ( scanner : targets * : including-target ) -{ -    HDRSCAN on $(targets) = [ on $(including-target) return $(HDRSCAN) ] ; -    SCANNER on $(targets) = $(scanner) ; -    HDRRULE on $(targets) = scanner.hdrrule ; -    HDRGRIST on $(targets) = [ on $(including-target) return $(HDRGRIST) ] ; -} - - -rule hdrrule ( target : matches * : binding ) -{ -    local scanner = [ on $(target) return $(SCANNER) ] ; -    $(scanner).process $(target) : $(matches) : $(binding) ; -} -# hdrrule must be available at global scope so that it can be invoked -# by header scanning -IMPORT scanner : hdrrule : : scanner.hdrrule ; - - - - diff --git a/jam-files/boost-build/build/scanner.py b/jam-files/boost-build/build/scanner.py deleted file mode 100644 index 19f1431d..00000000 --- a/jam-files/boost-build/build/scanner.py +++ /dev/null @@ -1,158 +0,0 @@ -# Status: ported. -# Base revision: 45462 -#  -# Copyright 2003 Dave Abrahams  -# Copyright 2002, 2003, 2004, 2005 Vladimir Prus  -# Distributed under the Boost Software License, Version 1.0.  -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)  - -#  Implements scanners: objects that compute implicit dependencies for -#  files, such as includes in C++. -# -#  Scanner has a regular expression used to find dependencies, some -#  data needed to interpret those dependencies (for example, include -#  paths), and a code which actually established needed relationship -#  between actual jam targets. -# -#  Scanner objects are created by actions, when they try to actualize -#  virtual targets, passed to 'virtual-target.actualize' method and are -#  then associated with actual targets. It is possible to use -#  several scanners for a virtual-target. For example, a single source -#  might be used by to compile actions, with different include paths. -#  In this case, two different actual targets will be created, each  -#  having scanner of its own. -# -#  Typically, scanners are created from target type and action's  -#  properties, using the rule 'get' in this module. Directly creating -#  scanners is not recommended, because it might create many equvivalent -#  but different instances, and lead in unneeded duplication of -#  actual targets. However, actions can also create scanners in a special -#  way, instead of relying on just target type. - -import property -import bjam -import os -from b2.exceptions import * -from b2.manager import get_manager - -def reset (): -    """ Clear the module state. This is mainly for testing purposes. -    """ -    global __scanners, __rv_cache, __scanner_cache - -    # Maps registered scanner classes to relevant properties -    __scanners = {} -     -    # A cache of scanners. -    # The key is: class_name.properties_tag, where properties_tag is the concatenation  -    # of all relevant properties, separated by '-' -    __scanner_cache = {} -     -reset () - - -def register(scanner_class, relevant_properties): -    """ Registers a new generator class, specifying a set of  -        properties relevant to this scanner.  Ctor for that class -        should have one parameter: list of properties. -    """ -    __scanners[str(scanner_class)] = relevant_properties - -def registered(scanner_class): -    """ Returns true iff a scanner of that class is registered -    """ -    return __scanners.has_key(str(scanner_class)) -     -def get(scanner_class, properties): -    """ Returns an instance of previously registered scanner -        with the specified properties. -    """ -    scanner_name = str(scanner_class) -     -    if not registered(scanner_name): -        raise BaseException ("attempt to get unregisted scanner: %s" % scanner_name) - -    relevant_properties = __scanners[scanner_name] -    r = property.select(relevant_properties, properties) - -    scanner_id = scanner_name + '.' + '-'.join(r) -     -    if not __scanner_cache.has_key(scanner_name): -        __scanner_cache[scanner_name] = scanner_class(r) - -    return __scanner_cache[scanner_name] - -class Scanner: -    """ Base scanner class. -    """ -    def __init__ (self): -        pass -     -    def pattern (self): -        """ Returns a pattern to use for scanning. -        """ -        raise BaseException ("method must be overriden") - -    def process (self, target, matches): -        """ Establish necessary relationship between targets, -            given actual target beeing scanned, and a list of -            pattern matches in that file. -        """ -        raise BaseException ("method must be overriden") - - -# Common scanner class, which can be used when there's only one -# kind of includes (unlike C, where "" and <> includes have different -# search paths). -class CommonScanner(Scanner): - -    def __init__ (self, includes): -        Scanner.__init__(self) -        self.includes = includes - -    def process(self, target, matches, binding): - -        target_path = os.path.normpath(os.path.dirname(binding[0])) -        bjam.call("mark-included", target, matches) - -        get_manager().engine().set_target_variable(matches, "SEARCH", -                                                   [target_path] + self.includes) -        get_manager().scanners().propagate(self, matches) - -class ScannerRegistry: -     -    def __init__ (self, manager): -        self.manager_ = manager -        self.count_ = 0 -        self.exported_scanners_ = {} - -    def install (self, scanner, target, vtarget): -        """ Installs the specified scanner on actual target 'target'.  -            vtarget: virtual target from which 'target' was actualized. -        """ -        engine = self.manager_.engine() -        engine.set_target_variable(target, "HDRSCAN", scanner.pattern()) -        if not self.exported_scanners_.has_key(scanner): -            exported_name = "scanner_" + str(self.count_) -            self.count_ = self.count_ + 1 -            self.exported_scanners_[scanner] = exported_name -            bjam.import_rule("", exported_name, scanner.process) -        else: -            exported_name = self.exported_scanners_[scanner] - -        engine.set_target_variable(target, "HDRRULE", exported_name) -         -        # scanner reflects difference in properties affecting     -        # binding of 'target', which will be known when processing -        # includes for it, will give information on how to -        # interpret quoted includes. -        engine.set_target_variable(target, "HDRGRIST", str(id(scanner))) -        pass - -    def propagate(self, scanner, targets): -        engine = self.manager_.engine() -        engine.set_target_variable(targets, "HDRSCAN", scanner.pattern()) -        engine.set_target_variable(targets, "HDRRULE", -                                   self.exported_scanners_[scanner]) -        engine.set_target_variable(targets, "HDRGRIST", str(id(scanner))) - diff --git a/jam-files/boost-build/build/targets.jam b/jam-files/boost-build/build/targets.jam deleted file mode 100644 index a70532ce..00000000 --- a/jam-files/boost-build/build/targets.jam +++ /dev/null @@ -1,1659 +0,0 @@ -# Copyright Vladimir Prus 2002. -# Copyright Rene Rivera 2006. -# -# Distributed under the Boost Software License, Version 1.0. -#    (See accompanying file LICENSE_1_0.txt or copy at -#          http://www.boost.org/LICENSE_1_0.txt) - -# Supports 'abstract' targets, which are targets explicitly defined in a -# Jamfile. -# -# Abstract targets are represented by classes derived from 'abstract-target' -# class. The first abstract target is 'project-target', which is created for -# each Jamfile, and can be obtained by the 'target' rule in the Jamfile's module -# (see project.jam). -# -# Project targets keep a list of 'main-target' instances. A main target is what -# the user explicitly defines in a Jamfile. It is possible to have several -# definitions for a main target, for example to have different lists of sources -# for different platforms. So, main targets keep a list of alternatives. -# -# Each alternative is an instance of 'abstract-target'. When a main target -# subvariant is defined by some rule, that rule will decide what class to use, -# create an instance of that class and add it to the list of alternatives for -# the main target. -# -# Rules supplied by the build system will use only targets derived from -# 'basic-target' class, which will provide some default behaviour. There will be -# different classes derived from it such as 'make-target', created by the 'make' -# rule, and 'typed-target', created by rules such as 'exe' and 'lib'. - -# -#                         +------------------------+ -#                         |abstract-target         | -#                         +========================+ -#                         |name                    | -#                         |project                 | -#                         |                        | -#                         |generate(properties) = 0| -#                         +-----------+------------+ -#                                     | -#                                     ^ -#                                    / \ -#                                   +-+-+ -#                                     | -#                                     | -#            +------------------------+------+------------------------------+ -#            |                               |                              | -#            |                               |                              | -# +----------+-----------+            +------+------+                +------+-------+ -# | project-target       |            | main-target |                | basic-target | -# +======================+ 1        * +=============+  alternatives  +==============+ -# | generate(properties) |o-----------+ generate    |<>------------->| generate     | -# | main-target          |            +-------------+                | construct = 0| -# +----------------------+                                           +--------------+ -#                                                                           | -#                                                                           ^ -#                                                                          / \ -#                                                                         +-+-+ -#                                                                           | -#                                                                           | -#                 ...--+----------------+------------------+----------------+---+ -#                      |                |                  |                    | -#                      |                |                  |                    | -#               ... ---+-----+   +------+-------+   +------+------+    +--------+-----+ -#                            |   | typed-target |   | make-target |    | stage-target | -#                            .   +==============+   +=============+    +==============+ -#                            .   | construct    |   | construct   |    | construct    | -#                                +--------------+   +-------------+    +--------------+ - -import assert ; -import "class" : new ; -import errors ; -import feature ; -import indirect ; -import path ; -import property ; -import property-set ; -import sequence ; -import set ; -import toolset ; -import build-request ; - - -# Base class for all abstract targets. -# -class abstract-target -{ -    import project ; -    import assert ; -    import "class" ; -    import errors ; - -    rule __init__ ( name  # Name of the target in Jamfile. -        : project-target  # The project target to which this one belongs. -    ) -    { -        # Note: it might seem that we don't need either name or project at all. -        # However, there are places where we really need it. One example is -        # error messages which should name problematic targets. Another is -        # setting correct paths for sources and generated files. - -        self.name = $(name) ; -        self.project = $(project-target) ; -        self.location = [ errors.nearest-user-location ] ; -    } - -    # Returns the name of this target. -    rule name ( ) -    { -        return $(self.name) ; -    } - -    # Returns the project for this target. -    rule project ( ) -    { -        return $(self.project) ; -    } - -    # Return the location where the target was declared. -    rule location ( ) -    { -        return $(self.location) ; -    } - -    # Returns a user-readable name for this target. -    rule full-name ( ) -    { -        local location = [ $(self.project).get location ] ; -        return $(location)/$(self.name) ; -    } - -    # Generates virtual targets for this abstract target using the specified -    # properties, unless a different value of some feature is required by the -    # target. -    # On success, returns: -    # - a property-set with the usage requirements to be applied to dependants -    # - a list of produced virtual targets, which may be empty. -    # If 'property-set' is empty, performs the default build of this target, in -    # a way specific to the derived class. -    # -    rule generate ( property-set ) -    { -        errors.error "method should be defined in derived classes" ; -    } - -    rule rename ( new-name ) -    { -        self.name = $(new-name) ; -    } -} - - -if --debug-building in [ modules.peek : ARGV ] -{ -    modules.poke : .debug-building : true ; -} - - -rule indent ( ) -{ -    return $(.indent:J="") ; -} - - -rule increase-indent ( ) -{ -    .indent += "    " ; -} - - -rule decrease-indent ( ) -{ -    .indent = $(.indent[2-]) ; -} - - -#  Project target class (derived from 'abstract-target'). -# -#  This class has the following responsibilities: -#  - Maintaining a list of main targets in this project and building them. -# -#  Main targets are constructed in two stages: -#  - When Jamfile is read, a number of calls to 'add-alternative' is made. At -#    that time, alternatives can also be renamed to account for inline targets. -#  - The first time 'main-target' or 'has-main-target' rule is called, all -#    alternatives are enumerated and main targets are created. -# -class project-target : abstract-target -{ -    import project ; -    import targets ; -    import path ; -    import print ; -    import property-set ; -    import set ; -    import sequence ; -    import "class" : new ; -    import errors ; - -    rule __init__ ( name : project-module parent-project ? -        : requirements * : default-build * ) -    { -        abstract-target.__init__ $(name) : $(__name__) ; - -        self.project-module = $(project-module) ; -        self.location = [ project.attribute $(project-module) location ] ; -        self.requirements = $(requirements) ; -        self.default-build = $(default-build) ; - -        if $(parent-project) -        { -            inherit $(parent-project) ; -        } -    } - -    # This is needed only by the 'make' rule. Need to find the way to make -    # 'make' work without this method. -    # -    rule project-module ( ) -    { -        return $(self.project-module) ; -    } - -    rule get ( attribute ) -    { -        return [ project.attribute $(self.project-module) $(attribute) ] ; -    } - -    rule build-dir ( ) -    { -        if ! $(self.build-dir) -        { -            self.build-dir = [ get build-dir ] ; -            if ! $(self.build-dir) -            { -                self.build-dir = [ path.join [ $(self.project).get location ] -                    bin ] ; -            } -        } -        return $(self.build-dir) ; -    } - -    # Generates all possible targets contained in this project. -    # -    rule generate ( property-set * ) -    { -        if [ modules.peek : .debug-building ] -        { -            ECHO [ targets.indent ] "building project" [ name ] " ('$(__name__)') with" [ $(property-set).raw ] ; -            targets.increase-indent ; -        } - -        local usage-requirements = [ property-set.empty ] ; -        local targets ; - -        for local t in [ targets-to-build ] -        { -            local g = [ $(t).generate $(property-set) ] ; -            usage-requirements = [ $(usage-requirements).add $(g[1]) ] ; -            targets += $(g[2-]) ; -        } -        targets.decrease-indent ; -        return $(usage-requirements) [ sequence.unique $(targets) ] ; -    } - -    # Computes and returns a list of abstract-target instances which must be -    # built when this project is built. -    # -    rule targets-to-build ( ) -    { -        local result ; - -        if ! $(self.built-main-targets) -        { -            build-main-targets ; -        } - -        # Collect all main targets here, except for "explicit" ones. -        for local t in $(self.main-targets) -        { -            if ! [ $(t).name ] in $(self.explicit-targets) -            { -                result += $(t) ; -            } -        } - -        # Collect all projects referenced via "projects-to-build" attribute. -        local self-location = [ get location ] ; -        for local pn in [ get projects-to-build ] -        { -            result += [ find $(pn)/ ] ; -        } - -        return $(result) ; -    } - -    # Add 'target' to the list of targets in this project that should be build -    # only by explicit request -    # -    rule mark-target-as-explicit ( target-name * ) -    { -        # Record the name of the target, not instance, since this rule is called -        # before main target instances are created. -        self.explicit-targets += $(target-name) ; -    } -     -    rule mark-target-as-always ( target-name * ) -    { -        # Record the name of the target, not instance, since this rule is called -        # before main target instances are created. -        self.always-targets += $(target-name) ; -    } - -    # Add new target alternative -    # -    rule add-alternative ( target-instance ) -    { -        if $(self.built-main-targets) -        { -            errors.error add-alternative called when main targets are already -                created. : in project [ full-name ] ; -        } -        self.alternatives += $(target-instance) ; -    } - -    # Returns a 'main-target' class instance corresponding to 'name'. -    # -    rule main-target ( name ) -    { -        if ! $(self.built-main-targets) -        { -            build-main-targets ; -        } -        return $(self.main-target.$(name)) ; -    } - -    # Returns whether a main target with the specified name exists. -    # -    rule has-main-target ( name ) -    { -        if ! $(self.built-main-targets) -        { -            build-main-targets ; -        } - -        if $(self.main-target.$(name)) -        { -            return true ; -        } -    } - -    # Worker function for the find rule not implementing any caching and simply -    # returning nothing in case the target can not be found. -    # -    rule find-really ( id ) -    { -        local result ; -        local current-location = [ get location ] ; - -        local split = [ MATCH (.*)//(.*) : $(id) ] ; -        local project-part = $(split[1]) ; -        local target-part = $(split[2]) ; - -        local extra-error-message ; -        if $(project-part) -        { -            # There is an explicitly specified project part in id. Looks up the -            # project and passes the request to it. -            local pm = [ project.find $(project-part) : $(current-location) ] ; -            if $(pm) -            { -                project-target = [ project.target $(pm) ] ; -                result = [ $(project-target).find $(target-part) : no-error ] ; -            } -            else -            { -                # TODO: This extra error message will not get displayed most -                # likely due to some buggy refactoring. Refactor the code so the -                # message gets diplayed again. -                extra-error-message = error: could not find project -                    '$(project-part)' ; -            } -        } -        else -        { -            # Interpret target-name as name of main target. Need to do this -            # before checking for file. Consider the following scenario with a -            # toolset not modifying its executable's names, e.g. gcc on -            # Unix-like platforms: -            # -            #  exe test : test.cpp ; -            #  install s : test : <location>. ; -            # -            # After the first build we would have a target named 'test' in the -            # Jamfile and a file named 'test' on the disk. We need the target to -            # override the file. -            result = [ main-target $(id) ] ; -             -            # Interpret id as an existing file reference. -            if ! $(result) -            { -                result = [ new file-reference [ path.make $(id) ] : -                    $(self.project) ] ; -                if ! [ $(result).exists ] -                { -                    result = ; -                } -            } - -            # Interpret id as project-id. -            if ! $(result) -            { -                local project-module = [ project.find $(id) : -                    $(current-location) ] ; -                if $(project-module) -                { -                    result = [ project.target $(project-module) ] ; -                } -            } -        } - -        return $(result) ; -    } - -    # Find and return the target with the specified id, treated relative to -    # self. Id may specify either a target or a file name with the target taking -    # priority. May report an error or return nothing if the target is not found -    # depending on the 'no-error' parameter. -    # -    rule find ( id : no-error ? ) -    { -        local v = $(.id.$(id)) ; -        if ! $(v) -        { -            v = [ find-really $(id) ] ; -            if ! $(v) -            { -                v = none ; -            } -            .id.$(id) = $(v) ; -        } - -        if $(v) != none -        { -            return $(v) ; -        } -        else -        { -            if ! $(no-error) -            { -                local current-location = [ get location ] ; -                ECHO "error: Unable to find file or target named" ; -                ECHO "error:     '$(id)'" ; -                ECHO "error: referred from project at" ; -                ECHO "error:     '$(current-location)'" ; -                ECHO $(extra-error-message) ; -                EXIT ; -            } -        } -    } - -    rule build-main-targets ( ) -    { -        self.built-main-targets = true ; -        for local a in $(self.alternatives) -        { -            local name = [ $(a).name ] ; -            local target = $(self.main-target.$(name)) ; -            if ! $(target) -            { -                local t = [ new main-target $(name) : $(self.project) ] ; -                self.main-target.$(name) = $(t) ; -                self.main-targets += $(t) ; -                target = $(self.main-target.$(name)) ; -            } -             -            if $(name) in $(self.always-targets) -            { -                $(a).always ; -            }                 - -            $(target).add-alternative $(a) ; -        } -    } - -    # Accessor, add a constant. -    # -    rule add-constant ( -        name       # Variable name of the constant. -        : value +  # Value of the constant. -        : type ?   # Optional type of value. -        ) -    { -        switch $(type) -        { -            case path : -              local r ; -              for local v in $(value) -              { -                local l = $(self.location) ; -                if ! $(l) -                { -                    # Project corresponding to config files do not have  -                    # 'location' attribute, but do have source location. -                    # It might be more reasonable to make every project have -                    # a location and use some other approach to prevent buildable -                    # targets in config files, but that's for later. -                    l = [ get source-location ] ; -                }                 -                v = [ path.root [ path.make $(v) ] $(l) ] ; -                # Now make the value absolute path. -                v = [ path.root $(v) [ path.pwd ] ] ; -                # Constants should be in platform-native form. -                v = [ path.native $(v) ] ; -                r += $(v) ; -              } -              value = $(r) ; -        } -        if ! $(name) in $(self.constants) -        { -            self.constants += $(name) ; -        } -        self.constant.$(name) = $(value) ; -        # Inject the constant in the scope of the Jamroot module. -        modules.poke $(self.project-module) : $(name) : $(value) ; -    } - -    rule inherit ( parent ) -    { -        for local c in [ modules.peek $(parent) : self.constants ] -        { -            # No need to pass the type. Path constants were converted to -            # absolute paths already by parent. -            add-constant $(c) -              : [ modules.peek $(parent) : self.constant.$(c) ] ; -        } - -        # Import rules from parent. -        local this-module = [ project-module ] ; -        local parent-module = [ $(parent).project-module ] ; -        # Do not import rules coming from 'project-rules' as they must be -        # imported localized. -        local user-rules = [ set.difference -            [ RULENAMES $(parent-module) ] : -            [ RULENAMES project-rules ] ] ; -        IMPORT $(parent-module) : $(user-rules) : $(this-module) : $(user-rules) ; -        EXPORT $(this-module) : $(user-rules) ; -    } -} - - -# Helper rules to detect cycles in main target references. -# -local rule start-building ( main-target-instance ) -{ -    if $(main-target-instance) in $(.targets-being-built) -    { -        local names ; -        for local t in $(.targets-being-built) $(main-target-instance) -        { -            names += [ $(t).full-name ] ; -        } - -        errors.error "Recursion in main target references" -          : "the following target are being built currently:" -          : $(names) ; -    } -    .targets-being-built += $(main-target-instance) ; -} - - -local rule end-building ( main-target-instance ) -{ -    .targets-being-built = $(.targets-being-built[1--2]) ; -} - - -# A named top-level target in Jamfile. -# -class main-target : abstract-target -{ -    import assert ; -    import errors ; -    import feature ; -    import print ; -    import property-set ; -    import sequence ; -    import targets : start-building end-building ; - -    rule __init__ ( name : project ) -    { -        abstract-target.__init__ $(name) : $(project) ; -    } - -    # Add a new alternative for this target -    rule add-alternative ( target ) -    { -        local d = [ $(target).default-build ] ; -        if $(self.alternatives) && ( $(self.default-build) != $(d) ) -        { -            errors.error "default build must be identical in all alternatives" -              : "main target is" [ full-name ] -              : "with" [ $(d).raw ] -              : "differing from previous default build" [ $(self.default-build).raw ] ; -        } -        else -        { -            self.default-build = $(d) ; -        } -        self.alternatives += $(target) ; -    } - -    # Returns the best viable alternative for this property-set. See the -    # documentation for selection rules. -    # -    local rule select-alternatives ( property-set debug ? ) -    { -        # When selecting alternatives we have to consider defaults, for example: -        #    lib l : l.cpp : <variant>debug ; -        #    lib l : l_opt.cpp : <variant>release ; -        # won't work unless we add default value <variant>debug. -        property-set = [ $(p).add-defaults ] ; - -        # The algorithm: we keep the current best viable alternative. When we've -        # got a new best viable alternative, we compare it with the current one. - -        local best ; -        local best-properties ; - -        if $(self.alternatives[2-]) -        { -            local bad ; -            local worklist = $(self.alternatives) ; -            while $(worklist) && ! $(bad) -            { -                local v = $(worklist[1]) ; -                local properties = [ $(v).match $(property-set) $(debug) ] ; - -                if $(properties) != no-match -                { -                    if ! $(best) -                    { -                        best = $(v) ; -                        best-properties = $(properties) ; -                    } -                    else -                    { -                        if $(properties) = $(best-properties) -                        { -                            bad = true ; -                        } -                        else if $(properties) in $(best-properties) -                        { -                            # Do nothing, this alternative is worse -                        } -                        else if $(best-properties) in $(properties) -                        { -                            best = $(v) ; -                            best-properties = $(properties) ; -                        } -                        else -                        { -                            bad = true ; -                        } -                    } -                } -                worklist = $(worklist[2-]) ; -            } -            if ! $(bad) -            { -                return $(best) ; -            } -        } -        else -        { -            return $(self.alternatives) ; -        } -    } - -    rule apply-default-build ( property-set ) -    { -        return [ targets.apply-default-build $(property-set)  -          : $(self.default-build) ] ; -    } - -    # Select an alternative for this main target, by finding all alternatives -    # which requirements are satisfied by 'properties' and picking the one with -    # the longest requirements set. Returns the result of calling 'generate' on -    # that alternative. -    # -    rule generate ( property-set ) -    { -        start-building $(__name__) ; - -        # We want composite properties in build request act as if all the -        # properties it expands too are explicitly specified. -        property-set = [ $(property-set).expand ] ; - -        local all-property-sets = [ apply-default-build $(property-set) ] ; -        local usage-requirements = [ property-set.empty ] ; -        local result ; -        for local p in $(all-property-sets) -        { -            local r = [ generate-really $(p) ] ; -            if $(r) -            { -                usage-requirements = [ $(usage-requirements).add $(r[1]) ] ; -                result += $(r[2-]) ; -            } -        } -        end-building $(__name__) ; -        return $(usage-requirements) [ sequence.unique $(result) ] ; -    } - -    # Generates the main target with the given property set and returns a list -    # which first element is property-set object containing usage-requirements -    # of generated target and with generated virtual target in other elements. -    # It is possible that no targets are generated. -    # -    local rule generate-really ( property-set ) -    { -        local best-alternatives = [ select-alternatives $(property-set) ] ; -        if ! $(best-alternatives) -        { -            ECHO "error: No best alternative for" [ full-name ] ; -            select-alternatives $(property-set) debug ; -            return [ property-set.empty ] ; -        } -        else -        { -            # Now return virtual targets for the only alternative. -            return [ $(best-alternatives).generate $(property-set) ] ; -        } -    } - -    rule rename ( new-name ) -    { -        abstract-target.rename $(new-name) ; -        for local a in $(self.alternatives) -        { -            $(a).rename $(new-name) ; -        } -    } -} - - -# Abstract target refering to a source file. This is an artificial entity -# allowing sources to a target to be represented using a list of abstract target -# instances. -# -class file-reference : abstract-target -{ -    import virtual-target ; -    import property-set ; -    import path ; - -    rule __init__ ( file : project ) -    { -        abstract-target.__init__ $(file) : $(project) ; -    } - -    rule generate ( properties ) -    { -        return [ property-set.empty ] [ virtual-target.from-file $(self.name) : -            [ location ] : $(self.project) ] ; -    } - -    # Returns true if the referred file really exists. -    rule exists ( ) -    { -        location ; -        return $(self.file-path) ; -    } - -    # Returns the location of target. Needed by 'testing.jam'. -    rule location ( ) -    { -        if ! $(self.file-location) -        { -            local source-location = [ $(self.project).get source-location ] ; -            for local src-dir in $(source-location) -            { -                if ! $(self.file-location) -                { -                    local location = [ path.root $(self.name) $(src-dir) ] ; -                    if [ CHECK_IF_FILE [ path.native $(location) ] ] -                    { -                         self.file-location = $(src-dir) ; -                         self.file-path = $(location) ; -                    } -                } -            } -        } -        return $(self.file-location) ; -    } -} - - -# Given a target-reference, made in context of 'project', returns the -# abstract-target instance that is referred to, as well as properties explicitly -# specified for this reference. -# -rule resolve-reference ( target-reference : project ) -{ -    # Separate target name from properties override. -    local split = [ MATCH "^([^<]*)(/(<.*))?$" : $(target-reference) ] ; -    local id = $(split[1]) ; -    local sproperties = ; -    if $(split[3]) -    { -        sproperties = [ property.make [ feature.split $(split[3]) ] ] ; -        sproperties = [ feature.expand-composites $(sproperties) ] ; -    } - -    # Find the target. -    local target = [ $(project).find $(id) ] ; - -    return $(target) [ property-set.create $(sproperties) ] ; -} - - -# Attempts to generate the target given by target reference, which can refer -# both to a main target or to a file. Returns a list consisting of -# - usage requirements -# - generated virtual targets, if any -# -rule generate-from-reference ( -    target-reference  # Target reference. -    : project         # Project where the reference is made. -    : property-set    # Properties of the main target that makes the reference. -) -{ -    local r = [ resolve-reference $(target-reference) : $(project) ] ; -    local target = $(r[1]) ; -    local sproperties = $(r[2]) ; - -    # Take properties which should be propagated and refine them with -    # source-specific requirements. -    local propagated = [ $(property-set).propagated ] ; -    local rproperties = [ $(propagated).refine $(sproperties) ] ; -    if $(rproperties[1]) = "@error" -    { -        errors.error -            "When building" [ full-name ] " with properties " $(properties) : -            "Invalid properties specified for " $(source) ":" -            $(rproperties[2-]) ; -    } -    return [ $(target).generate $(rproperties) ] ; -} - -rule apply-default-build ( property-set : default-build ) -{ -    # 1. First, see what properties from default-build are already present -    # in property-set. - -    local raw = [ $(property-set).raw ] ; -    local specified-features = $(raw:G) ; - -    local defaults-to-apply ; -    for local d in [ $(default-build).raw ] -    { -        if ! $(d:G) in $(specified-features) -        { -            defaults-to-apply += $(d) ; -        } -    } - -    # 2. If there are any defaults to be applied, form a new build request. -    # Pass it through to 'expand-no-defaults' since default-build might -    # contain "release debug" resulting in two property-sets. -    local result ; -    if $(defaults-to-apply) -    { -        properties = [ -          build-request.expand-no-defaults - -            # We have to compress subproperties here to prevent property -            # lists like: -            # -            #    <toolset>msvc <toolset-msvc:version>7.1 <threading>multi -            # -            # from being expanded into: -            # -            #    <toolset-msvc:version>7.1/<threading>multi -            #    <toolset>msvc/<toolset-msvc:version>7.1/<threading>multi -            # -            # due to a cross-product property combination. That may be an -            # indication that build-request.expand-no-defaults is the wrong -            # rule to use here. -            [ feature.compress-subproperties $(raw) ] -              $(defaults-to-apply) -        ] ; - -        if $(properties) -        { -            for local p in $(properties) -            { -                result += [ property-set.create -                    [ feature.expand [ feature.split $(p) ] ] ] ; -            } -        } -        else -        { -            result = [ property-set.empty ] ; -        } -    } -    else -    { -        result = $(property-set) ; -    } -    return $(result) ; -} - - -# Given a build request and requirements, return properties common to dependency -# build request and target requirements. -# -# TODO: Document exactly what 'common properties' are, whether they should -# include default property values, whether they should contain any conditional -# properties or should those be already processed, etc. See whether there are -# any differences between use cases with empty and non-empty build-request as -# well as with requirements containing and those not containing any non-free -# features. -# -rule common-properties ( build-request requirements ) -{ -    # For optimization, we add free requirements directly, without using a -    # complex algorithm. This gives the complex algorithm a better chance of -    # caching results. -    local free = [ $(requirements).free ] ; -    local non-free = [ property-set.create [ $(requirements).base ] -        [ $(requirements).incidental ] ] ; - -    local key = .rp.$(build-request)-$(non-free) ; -    if ! $($(key)) -    { -        $(key) = [ common-properties2 $(build-request) $(non-free) ] ; -    } -    result = [ $($(key)).add-raw $(free) ] ; -} - - -# Given a 'context' -- a set of already present properties, and 'requirements', -# decide which extra properties should be applied to 'context'. For conditional -# requirements, this means evaluating the condition. For indirect conditional -# requirements, this means calling a rule. Ordinary requirements are always -# applied. -# -# Handles the situation where evaluating one conditional requirement affects -# conditions of another conditional requirements, such as: -#     <toolset>gcc:<variant>release <variant>release:<define>RELEASE -# -# If 'what' is 'refined' returns context refined with new requirements. If -# 'what' is 'added' returns just the requirements to be applied. -# -rule evaluate-requirements ( requirements : context : what ) -{ -    # Apply non-conditional requirements. It is possible that further -    # conditional requirement change a value set by non-conditional -    # requirements. For example: -    # -    #    exe a : a.cpp : <threading>single <toolset>foo:<threading>multi ; -    # -    # I am not sure if this should be an error, or not, especially given that -    # -    #    <threading>single -    # -    # might come from project's requirements. - -    local unconditional = [ feature.expand [ $(requirements).non-conditional ] ] ; -  -    local raw = [ $(context).raw ] ; -    raw = [ property.refine $(raw) : $(unconditional) ] ; - -    # We have collected properties that surely must be present in common -    # properties. We now try to figure out what other properties should be added -    # in order to satisfy rules (4)-(6) from the docs. - -    local conditionals = [ $(requirements).conditional ] ; -    # The 'count' variable has one element for each conditional feature and for -    # each occurrence of '<indirect-conditional>' feature. It is used as a loop -    # counter: for each iteration of the loop before we remove one element and -    # the property set should stabilize before we are done. It is assumed that -    # #conditionals iterations should be enough for properties to propagate -    # along conditions in any direction. -    local count = $(conditionals) -                  [ $(requirements).get <conditional> ] -                  and-once-more ; - -    local added-requirements ; - -    local current = $(raw) ; - -    # It is assumed that ordinary conditional requirements can not add -    # <conditional> properties (a.k.a. indirect conditional properties), and -    # that rules referred to by <conditional> properties can not add new -    # <conditional> properties. So the list of indirect conditionals does not -    # change. -    local indirect = [ $(requirements).get <conditional> ] ; -    indirect = [ MATCH ^@(.*) : $(indirect) ] ; - -    local ok ; -    while $(count) -    { -        # Evaluate conditionals in context of current properties. -        local e = [ property.evaluate-conditionals-in-context $(conditionals) -            : $(current) ] ; - -        # Evaluate indirect conditionals. -        for local i in $(indirect) -        { -            e += [ indirect.call $(i) $(current) ] ; -        } - -        if $(e) = $(added-requirements) -        { -            # If we got the same result, we have found the final properties. -            count = ; -            ok = true ; -        } -        else -        { -            # Oops, conditional evaluation results have changed. Also 'current' -            # contains leftovers from a previous evaluation. Recompute 'current' -            # using initial properties and conditional requirements. -            added-requirements = $(e) ; -            current = [ property.refine $(raw) : [ feature.expand $(e) ] ] ; -        } -        count = $(count[2-]) ; -    } -    if ! $(ok) -    { -        errors.error "Can not evaluate conditional properties " $(conditionals) ; -    } - -    if $(what) = added -    { -        return [ property-set.create $(unconditional) $(added-requirements) ] ; -    } -    else if $(what) = refined -    { -        return [ property-set.create $(current) ] ; -    } -    else -    { -        errors.error "Invalid value of the 'what' parameter." ; -    } -} - - -rule common-properties2 ( build-request requirements ) -{ -    # This guarantees that default properties are present in the result, unless -    # they are overriden by some requirement. FIXME: There is possibility that -    # we have added <foo>bar, which is composite and expands to <foo2>bar2, but -    # default value of <foo2> is not bar2, in which case it is not clear what to -    # do. -    # -    build-request = [ $(build-request).add-defaults ] ; -    # Features added by 'add-default' can be composite and expand to features -    # without default values -- so they are not added yet. It could be clearer/ -    # /faster to expand only newly added properties but that is not critical. -    build-request = [ $(build-request).expand ] ; - -    return [ evaluate-requirements $(requirements) : $(build-request) : -        refined ] ; -} - -rule push-target ( target ) -{ -    .targets = $(target) $(.targets) ; -} - -rule pop-target ( ) -{ -    .targets = $(.targets[2-]) ; -} - -# Return the metatarget that is currently being generated. -rule current ( ) -{ -    return $(.targets[1]) ; -} - - -# Implements the most standard way of constructing main target alternative from -# sources. Allows sources to be either file or other main target and handles -# generation of those dependency targets. -# -class basic-target : abstract-target -{ -    import build-request ; -    import build-system ; -    import "class" : new ; -    import errors ; -    import feature ; -    import property ; -    import property-set ; -    import sequence ; -    import set ; -    import targets ; -    import virtual-target ; - -    rule __init__ ( name : project : sources * : requirements * -        : default-build * : usage-requirements * ) -    { -        abstract-target.__init__ $(name) : $(project) ; - -        self.sources = $(sources) ; -        if ! $(requirements) { -            requirements = [ property-set.empty ] ; -        } -        self.requirements = $(requirements) ; -        if ! $(default-build) -        { -            default-build = [ property-set.empty ] ; -        } -        self.default-build = $(default-build) ; -        if ! $(usage-requirements) -        { -            usage-requirements = [ property-set.empty ] ; -        } -        self.usage-requirements = $(usage-requirements) ; - -        if $(sources:G) -        { -            errors.user-error properties found in the 'sources' parameter for -                [ full-name ] ; -        } -    } -     -    rule always ( ) -    { -        self.always = 1 ; -    } -     -    # Returns the list of abstract-targets which are used as sources. The extra -    # properties specified for sources are not represented. The only user for -    # this rule at the moment is the "--dump-tests" feature of the test system. -    # -    rule sources ( ) -    { -        if ! $(self.source-targets) -        { -            for local s in $(self.sources) -            { -                self.source-targets += -                  [ targets.resolve-reference $(s) : $(self.project) ] ; -            } -        } -        return $(self.source-targets) ; -    } - -    rule requirements ( ) -    { -        return $(self.requirements) ; -    } - -    rule default-build ( ) -    { -        return $(self.default-build) ; -    } - -    # Returns the alternative condition for this alternative, if the condition -    # is satisfied by 'property-set'. -    # -    rule match ( property-set debug ? ) -    { -        # The condition is composed of all base non-conditional properties. It -        # is not clear if we should expand 'self.requirements' or not. For one -        # thing, it would be nice to be able to put -        #    <toolset>msvc-6.0 -        # in requirements. On the other hand, if we have <variant>release as a -        # condition it does not make sense to require <optimization>full to be -        # in the build request just to select this variant. -        local bcondition = [ $(self.requirements).base ] ; -        local ccondition = [ $(self.requirements).conditional ] ; -        local condition = [ set.difference $(bcondition) : $(ccondition) ] ; -        if $(debug) -        { -            ECHO "    next alternative: required properties:" $(condition:E=(empty)) ; -        } - -        if $(condition) in [ $(property-set).raw ] -        { -            if $(debug) -            { -                ECHO "        matched" ; -            } -            return $(condition) ; -        } -        else -        { -            if $(debug) -            { -                ECHO "        not matched" ; -            } -            return no-match ; -        } -    } - -    # Takes a target reference, which might be either target id or a dependency -    # property, and generates that target using 'property-set' as build request. -    # -    # The results are added to the variable called 'result-var'. Usage -    # requirements are added to the variable called 'usage-requirements-var'. -    # -    rule generate-dependencies ( dependencies * : property-set -        : result-var usage-requirements-var ) -    { -        for local dependency in $(dependencies) -        { -            local grist = $(dependency:G) ; -            local id = $(dependency:G=) ; - -            local result = [ targets.generate-from-reference $(id) : -                $(self.project) : $(property-set) ] ; - -            $(result-var) += $(result[2-]:G=$(grist)) ; -            $(usage-requirements-var) += [ $(result[1]).raw ] ; -        } -    } - -    # Determines final build properties, generates sources, and calls -    # 'construct'. This method should not be overridden. -    # -    rule generate ( property-set ) -    { -        if [ modules.peek : .debug-building ] -        { -            ECHO ; -            local fn = [ full-name ] ; -            ECHO [ targets.indent ] "Building target '$(fn)'" ; -            targets.increase-indent ; -            ECHO [ targets.indent ] "Build request: " $(property-set) [ $(property-set).raw ] ; -            local cf = [ build-system.command-line-free-features ] ; -            ECHO [ targets.indent ] "Command line free features: " [ $(cf).raw ] ; -            ECHO [ targets.indent ] "Target requirements: " [ $(self.requirements).raw ] ; -        } -        targets.push-target $(__name__) ; - -        if ! $(self.generated.$(property-set)) -        { -            # Apply free features from the command line. If user said -            #   define=FOO -            # he most likely wants this define to be set for all compiles. -            property-set = [ $(property-set).refine -                [ build-system.command-line-free-features ] ] ; -            local rproperties = [ targets.common-properties $(property-set) -                $(self.requirements) ] ; - -            if [ modules.peek : .debug-building ] -            { -                ECHO ; -                ECHO [ targets.indent ] "Common properties: " [ $(rproperties).raw ] ; -            } - -            if ( $(rproperties[1]) != "@error" ) && ( [ $(rproperties).get -                <build> ] != no ) -            { -                local source-targets ; -                local properties = [ $(rproperties).non-dependency ] ; -                local usage-requirements ; - -                generate-dependencies [ $(rproperties).dependency ] : -                    $(rproperties) : properties usage-requirements ; - -                generate-dependencies $(self.sources) : $(rproperties) : -                    source-targets usage-requirements ; - -                if [ modules.peek : .debug-building ] -                { -                    ECHO ; -                    ECHO [ targets.indent ] "Usage requirements for" -                        $(self.name)": " $(usage-requirements) ; -                } - -                rproperties = [ property-set.create $(properties) -                    $(usage-requirements) ] ; -                usage-requirements = [ property-set.create $(usage-requirements) ] ; - -                if [ modules.peek : .debug-building ] -                { -                    ECHO [ targets.indent ] "Build properties: " -                        [ $(rproperties).raw ] ; -                } - -                local extra = [ $(rproperties).get <source> ] ; -                source-targets += $(extra:G=) ; -                # We might get duplicate sources, for example if we link to two -                # libraries having the same <library> usage requirement. -                # Use stable sort, since for some targets the order is -                # important. E.g. RUN_PY target need python source to come -                # first. -                source-targets = [ sequence.unique $(source-targets) : stable ] ; - -                local result = [ construct $(self.name) : $(source-targets) : -                    $(rproperties) ] ; - -                if $(result) -                { -                    local gur = $(result[1]) ; -                    result = $(result[2-]) ; -                     -                    if $(self.always) -                    { -                        for local t in $(result) -                        { -                            $(t).always ; -                        }                         -                    } -                     -                    local s = [ create-subvariant $(result) -                        : [ virtual-target.recent-targets ] -                        : $(property-set) : $(source-targets) -                        : $(rproperties) : $(usage-requirements) ] ; -                    virtual-target.clear-recent-targets ; - -                    local ur = [ compute-usage-requirements $(s) ] ; -                    ur = [ $(ur).add $(gur) ] ; -                    $(s).set-usage-requirements $(ur) ; -                    if [ modules.peek : .debug-building ] -                    { -                        ECHO [ targets.indent ] "Usage requirements from" -                            $(self.name)": " [ $(ur).raw ] ; -                    } - -                    self.generated.$(property-set) = $(ur) $(result) ; -                } -            } -            else -            { -                if $(rproperties[1]) = "@error" -                { -                    ECHO [ targets.indent ] "Skipping build of:" [ full-name ] -                        "cannot compute common properties" ; -                } -                else if [ $(rproperties).get <build> ] = no -                { -                    # If we just see <build>no, we cannot produce any reasonable -                    # diagnostics. The code that adds this property is expected -                    # to explain why a target is not built, for example using -                    # the configure.log-component-configuration function. -                } -                else -                { -                    ECHO [ targets.indent ] "Skipping build of: " [ full-name ] -                        " unknown reason" ; -                } - -                # We are here either because there has been an error computing -                # properties or there is <build>no in properties. In the latter -                # case we do not want any diagnostic. In the former case, we -                # need diagnostics. FIXME - -                # If this target fails to build, add <build>no to properties to -                # cause any parent target to fail to build. Except that it -                # - does not work now, since we check for <build>no only in -                #   common properties, but not in properties that came from -                #   dependencies -                # - it is not clear if that is a good idea anyway. The alias -                #   target, for example, should not fail to build if a -                #   dependency fails. -                self.generated.$(property-set) = [ property-set.create <build>no ] ; -            } -        } -        else -        { -            if [ modules.peek : .debug-building ] -            { -                ECHO [ targets.indent ] "Already built" ; -                local ur = $(self.generated.$(property-set)) ; -                ur = $(ur[0]) ; -                targets.increase-indent ; -                ECHO [ targets.indent ] "Usage requirements from" -                    $(self.name)": " [ $(ur).raw ] ; -                targets.decrease-indent ; -            } -        } - -        targets.pop-target ; -        targets.decrease-indent ; -        return $(self.generated.$(property-set)) ; -    } - -    # Given the set of generated targets, and refined build properties, -    # determines and sets appropriate usage requirements on those targets. -    # -    rule compute-usage-requirements ( subvariant ) -    { -        local rproperties = [ $(subvariant).build-properties ] ; -        xusage-requirements = [ targets.evaluate-requirements -            $(self.usage-requirements) : $(rproperties) : added ] ; - -        # We generate all dependency properties and add them, as well as their -        # usage requirements, to the result. -        local extra ; -        generate-dependencies [ $(xusage-requirements).dependency ] : -            $(rproperties) : extra extra ; - -        local result = [ property-set.create -            [ $(xusage-requirements).non-dependency ] $(extra) ] ; - -        # Propagate usage requirements we got from sources, except for the -        # <pch-header> and <pch-file> features. -        # -        # That feature specifies which pch file to use, and should apply only to -        # direct dependents. Consider: -        # -        #   pch pch1 : ... -        #   lib lib1 : ..... pch1 ; -        #   pch pch2 : -        #   lib lib2 : pch2 lib1 ; -        # -        # Here, lib2 should not get <pch-header> property from pch1. -        # -        # Essentially, when those two features are in usage requirements, they -        # are propagated only to direct dependents. We might need a more general -        # mechanism, but for now, only those two features are special. -        # -        # TODO - Actually there are more possible candidates like for instance -        # when listing static library X as a source for another static library. -        # Then static library X will be added as a <source> property to the -        # second library's usage requirements but those requirements should last -        # only up to the first executable or shared library that actually links -        # to it. -        local raw = [ $(subvariant).sources-usage-requirements ] ; -        raw = [ $(raw).raw ] ; -        raw = [ property.change $(raw) : <pch-header> ] ; -        raw = [ property.change $(raw) : <pch-file> ] ; -        return [ $(result).add [ property-set.create $(raw) ] ] ; -    } - -    # Creates new subvariant instances for 'targets'. -    # 'root-targets'  - virtual targets to be returned to dependants -    # 'all-targets'   - virtual targets created while building this main target -    # 'build-request' - property-set instance with requested build properties -    # -    local rule create-subvariant ( root-targets * : all-targets * : -        build-request : sources * : rproperties : usage-requirements ) -    { -        for local e in $(root-targets) -        { -            $(e).root true ; -        } - -        # Process all virtual targets that will be created if this main target -        # is created. -        local s = [ new subvariant $(__name__) : $(build-request) : $(sources) : -            $(rproperties) : $(usage-requirements) : $(all-targets) ] ; -        for local v in $(all-targets) -        { -            if ! [ $(v).creating-subvariant ] -            { -                $(v).creating-subvariant $(s) ; -            } -        } -        return $(s) ; -    } - -    # Constructs virtual targets for this abstract target and the dependency -    # graph. Returns a usage-requirements property-set and a list of virtual -    # targets. Should be overriden in derived classes. -    # -    rule construct ( name : source-targets * : properties * ) -    { -        errors.error "method should be defined in derived classes" ; -    } -} - - -class typed-target : basic-target -{ -    import generators ; - -    rule __init__ ( name : project : type : sources * : requirements * : -         default-build * : usage-requirements * ) -    { -        basic-target.__init__ $(name) : $(project) : $(sources) : -            $(requirements) : $(default-build) : $(usage-requirements) ; - -        self.type = $(type) ; -    } - -    rule type ( ) -    { -        return $(self.type) ; -    } - -    rule construct ( name : source-targets * : property-set ) -    { -        local r = [ generators.construct $(self.project) $(name:S=) : $(self.type) -            : [ property-set.create [ $(property-set).raw ] -                <main-target-type>$(self.type) ] -            : $(source-targets) : true ] ; -        if ! $(r) -        { -            ECHO "warn: Unable to construct" [ full-name ] ; - -            # Are there any top-level generators for this type/property set. -            if ! [ generators.find-viable-generators $(self.type) -                : $(property-set) ] -            { -                ECHO "error: no generators were found for type '$(self.type)'" ; -                ECHO "error: and the requested properties" ; -                ECHO "error: make sure you've configured the needed tools" ; -                ECHO "See http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html" ; -                ECHO "To debug this problem, try the --debug-generators option." ; -                EXIT ; -            } -        } -        return $(r) ; -    } -} - - -# Return the list of sources to use, if main target rule is invoked with -# 'sources'. If there are any objects in 'sources', they are treated as main -# target instances, and the name of such targets are adjusted to be -# '<name_of_this_target>__<name_of_source_target>'. Such renaming is disabled if -# a non-empty value is passed as the 'no-renaming' parameter. -# -rule main-target-sources ( sources * : main-target-name : no-renaming ? ) -{ -    local result ; -    for local t in $(sources) -    { -        if [ class.is-instance $(t) ] -        { -            local name = [ $(t).name ] ; -            if ! $(no-renaming) -            { -                name = $(main-target-name)__$(name) ; -                $(t).rename $(name) ; -            } -            # Inline targets are not built by default. -            local p = [ $(t).project ] ; -            $(p).mark-target-as-explicit $(name) ; -            result += $(name) ; -        } -        else -        { -            result += $(t) ; -        } -    } -    return $(result) ; -} - - -# Returns the requirements to use when declaring a main target, obtained by -# translating all specified property paths and refining project requirements -# with the ones specified for the target. -# -rule main-target-requirements ( -    specification *  # Properties explicitly specified for the main target. -    : project        # Project where the main target is to be declared. -) -{ -    specification += [ toolset.requirements ] ; - -    local requirements = [ property-set.refine-from-user-input -        [ $(project).get requirements ] : $(specification) : -        [ $(project).project-module ] : [ $(project).get location ] ] ; -    if $(requirements[1]) = "@error" -    { -        errors.error "Conflicting requirements for target:" $(requirements) ; -    } -    return $(requirements) ; -} - - -# Returns the usage requirements to use when declaring a main target, which are -# obtained by translating all specified property paths and adding project's -# usage requirements. -# -rule main-target-usage-requirements ( -    specification *  # Use-properties explicitly specified for a main target. -    : project        # Project where the main target is to be declared. -) -{ -    local project-usage-requirements = [ $(project).get usage-requirements ] ; - -    # We do not use 'refine-from-user-input' because: -    # - I am not sure if removing parent's usage requirements makes sense -    # - refining usage requirements is not needed, since usage requirements are -    #   always free. -    local usage-requirements = [ property-set.create-from-user-input -        $(specification) -        : [ $(project).project-module ] [ $(project).get location ] ] ; - -    return [ $(project-usage-requirements).add $(usage-requirements) ] ; -} - - -# Return the default build value to use when declaring a main target, which is -# obtained by using the specified value if not empty and parent's default build -# attribute otherwise. -# -rule main-target-default-build ( -    specification *  # Default build explicitly specified for a main target. -    : project        # Project where the main target is to be declared. -) -{ -    local result ; -    if $(specification) -    { -        result = $(specification) ; -    } -    else -    { -        result = [ $(project).get default-build ] ; -    } -    return [ property-set.create-with-validation $(result) ] ; -} - - -# Registers the specified target as a main target alternative and returns it. -# -rule main-target-alternative ( target ) -{ -    local ptarget = [ $(target).project ] ; -    $(ptarget).add-alternative $(target) ; -    return $(target) ; -} - -# Creates a new metargets with the specified properties, using 'klass' as -# the class. The 'name', 'sources', -# 'requirements', 'default-build' and 'usage-requirements' are assumed to be in -# the form specified by the user in Jamfile corresponding to 'project'. -# -rule create-metatarget ( klass : project : name : sources * : requirements * : -    default-build * : usage-requirements * ) -{ -    return [ -        targets.main-target-alternative -        [ new $(klass) $(name) : $(project) -            : [ targets.main-target-sources $(sources) : $(name) ] -            : [ targets.main-target-requirements $(requirements) : $(project) ] -            : [ targets.main-target-default-build $(default-build) : $(project) ] -            : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ] -        ] ] ; -} - -# Creates a typed-target with the specified properties. The 'name', 'sources', -# 'requirements', 'default-build' and 'usage-requirements' are assumed to be in -# the form specified by the user in Jamfile corresponding to 'project'. -# -rule create-typed-target ( type : project : name : sources * : requirements * : -    default-build * : usage-requirements * ) -{ -    return [ -        targets.main-target-alternative -        [ new typed-target $(name) : $(project) : $(type) -            : [ targets.main-target-sources $(sources) : $(name) ] -            : [ targets.main-target-requirements $(requirements) : $(project) ] -            : [ targets.main-target-default-build $(default-build) : $(project) ] -            : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ] -        ] ] ; -} diff --git a/jam-files/boost-build/build/targets.py b/jam-files/boost-build/build/targets.py deleted file mode 100644 index a35612ce..00000000 --- a/jam-files/boost-build/build/targets.py +++ /dev/null @@ -1,1401 +0,0 @@ -# Status: ported. -# Base revision: 64488 - -# Copyright Vladimir Prus 2002-2007. -# Copyright Rene Rivera 2006. -# -# Distributed under the Boost Software License, Version 1.0. -#    (See accompanying file LICENSE_1_0.txt or copy at -#          http://www.boost.org/LICENSE_1_0.txt) - -#   Supports 'abstract' targets, which are targets explicitly defined in Jamfile. -# -#   Abstract targets are represented by classes derived from 'AbstractTarget' class.  -#   The first abstract target is 'project_target', which is created for each -#   Jamfile, and can be obtained by the 'target' rule in the Jamfile's module. -#   (see project.jam).  -# -#   Project targets keep a list of 'MainTarget' instances. -#   A main target is what the user explicitly defines in a Jamfile. It is -#   possible to have several definitions for a main target, for example to have -#   different lists of sources for different platforms. So, main targets -#   keep a list of alternatives. -# -#   Each alternative is an instance of 'AbstractTarget'. When a main target -#   subvariant is defined by some rule, that rule will decide what class to -#   use, create an instance of that class and add it to the list of alternatives -#   for the main target. -# -#   Rules supplied by the build system will use only targets derived -#   from 'BasicTarget' class, which will provide some default behaviour. -#   There will be two classes derived from it, 'make-target', created by the -#   'make' rule, and 'TypedTarget', created by rules such as 'exe' and 'dll'. - -# -#                         +------------------------+ -#                         |AbstractTarget          | -#                         +========================+ -#                         |name                    | -#                         |project                 |                                    -#                         |                        |                                    -#                         |generate(properties) = 0|                                    -#                         +-----------+------------+                                    -#                                     |                                                 -#                                     ^                                                 -#                                    / \                                                -#                                   +-+-+                                               -#                                     |                                                 -#                                     |                                                 -#            +------------------------+------+------------------------------+           -#            |                               |                              |           -#            |                               |                              |           -# +----------+-----------+            +------+------+                +------+-------+   -# | project_target       |            | MainTarget  |                | BasicTarget  |   -# +======================+ 1        * +=============+  alternatives  +==============+   -# | generate(properties) |o-----------+ generate    |<>------------->| generate     |   -# | main-target          |            +-------------+                | construct = 0| -# +----------------------+                                           +--------------+   -#                                                                           |           -#                                                                           ^           -#                                                                          / \          -#                                                                         +-+-+         -#                                                                           |           -#                                                                           |           -#                 ...--+----------------+------------------+----------------+---+       -#                      |                |                  |                    |       -#                      |                |                  |                    |       -#               ... ---+-----+   +------+-------+   +------+------+    +--------+-----+ -#                            |   | TypedTarget  |   | make-target |    | stage-target | -#                            .   +==============+   +=============+    +==============+ -#                            .   | construct    |   | construct   |    | construct    | -#                                +--------------+   +-------------+    +--------------+ - -import re -import os.path -import sys - -from b2.manager import get_manager - -from b2.util.utility import * -import property, project, virtual_target, property_set, feature, generators, toolset -from virtual_target import Subvariant -from b2.exceptions import * -from b2.util.sequence import unique -from b2.util import path, bjam_signature -from b2.build.errors import user_error_checkpoint - -import b2.build.build_request as build_request - -import b2.util.set -_re_separate_target_from_properties = re.compile (r'^([^<]*)(/(<.*))?$') - -class TargetRegistry: -     -    def __init__ (self): -        # All targets that are currently being built. -        # Only the key is id (target), the value is the actual object. -        self.targets_being_built_ = {} - -        # Current indent for debugging messages -        self.indent_ = "" - -        self.debug_building_ = "--debug-building" in bjam.variable("ARGV") - -        self.targets_ = [] - -    def main_target_alternative (self, target): -        """ Registers the specified target as a main target alternatives. -            Returns 'target'. -        """ -        target.project ().add_alternative (target) -        return target - -    def main_target_sources (self, sources, main_target_name, no_renaming=0): -        """Return the list of sources to use, if main target rule is invoked -        with 'sources'. If there are any objects in 'sources', they are treated -        as main target instances, and the name of such targets are adjusted to -        be '<name_of_this_target>__<name_of_source_target>'. Such renaming -        is disabled is non-empty value is passed for 'no-renaming' parameter.""" -        result = [] - -        for t in sources: - -            t = b2.util.jam_to_value_maybe(t) -             -            if isinstance (t, AbstractTarget): -                name = t.name () - -                if not no_renaming: -                    name = main_target_name + '__' + name -                    t.rename (name) - -                # Inline targets are not built by default. -                p = t.project() -                p.mark_targets_as_explicit([name])                     -                result.append(name) - -            else: -                result.append (t) - -        return result - - -    def main_target_requirements(self, specification, project): -        """Returns the requirement to use when declaring a main target, -         which are obtained by -         - translating all specified property paths, and -         - refining project requirements with the one specified for the target -         -         'specification' are the properties xplicitly specified for a -          main target -         'project' is the project where the main taret is to be declared.""" - -        specification.extend(toolset.requirements()) - -        requirements = property_set.refine_from_user_input( -            project.get("requirements"), specification, -            project.project_module(), project.get("location")) - -        return requirements - -    def main_target_usage_requirements (self, specification, project): -        """ Returns the use requirement to use when declaraing a main target, -            which are obtained by -            - translating all specified property paths, and -            - adding project's usage requirements -            specification:  Use-properties explicitly specified for a main target -            project:        Project where the main target is to be declared -        """ -        project_usage_requirements = project.get ('usage-requirements') - -        # We don't use 'refine-from-user-input' because I'm not sure if: -        # - removing of parent's usage requirements makes sense -        # - refining of usage requirements is not needed, since usage requirements -        #   are always free. -        usage_requirements = property_set.create_from_user_input( -            specification, project.project_module(), project.get("location")) -         -        return project_usage_requirements.add (usage_requirements) - -    def main_target_default_build (self, specification, project): -        """ Return the default build value to use when declaring a main target, -            which is obtained by using specified value if not empty and parent's -            default build attribute otherwise. -            specification:  Default build explicitly specified for a main target -            project:        Project where the main target is to be declared -        """ -        if specification: -            return property_set.create_with_validation(specification) -        else: -            return project.get ('default-build') - -    def start_building (self, main_target_instance): -        """ Helper rules to detect cycles in main target references. -        """ -        if self.targets_being_built_.has_key(id(main_target_instance)): -            names = [] -            for t in self.targets_being_built_.values() + [main_target_instance]: -                names.append (t.full_name()) -             -            get_manager().errors()("Recursion in main target references\n") -         -        self.targets_being_built_[id(main_target_instance)] = main_target_instance - -    def end_building (self, main_target_instance): -        assert (self.targets_being_built_.has_key (id (main_target_instance))) -        del self.targets_being_built_ [id (main_target_instance)] - -    def create_typed_target (self, type, project, name, sources, requirements, default_build, usage_requirements): -        """ Creates a TypedTarget with the specified properties. -            The 'name', 'sources', 'requirements', 'default_build' and -            'usage_requirements' are assumed to be in the form specified -            by the user in Jamfile corresponding to 'project'. -        """ -        return self.main_target_alternative (TypedTarget (name, project, type, -            self.main_target_sources (sources, name), -            self.main_target_requirements (requirements, project), -            self.main_target_default_build (default_build, project), -            self.main_target_usage_requirements (usage_requirements, project))) - -    def increase_indent(self): -        self.indent_ += "    " - -    def decrease_indent(self): -        self.indent_ = self.indent_[0:-4] - -    def logging(self): -        return self.debug_building_ - -    def log(self, message): -        if self.debug_building_: -            print self.indent_ + message - -    def push_target(self, target): -        self.targets_.append(target) - -    def pop_target(self): -        self.targets_ = self.targets_[:-1] - -    def current(self): -        return self.targets_[0] - - -class GenerateResult: -     -    def __init__ (self, ur=None, targets=None): -        if not targets: -            targets = [] -         -        self.__usage_requirements = ur -        self.__targets = targets -        assert all(isinstance(t, virtual_target.VirtualTarget) for t in targets) - -        if not self.__usage_requirements: -            self.__usage_requirements = property_set.empty () - -    def usage_requirements (self): -        return self.__usage_requirements - -    def targets (self): -        return self.__targets -     -    def extend (self, other): -        assert (isinstance (other, GenerateResult)) -         -        self.__usage_requirements = self.__usage_requirements.add (other.usage_requirements ()) -        self.__targets.extend (other.targets ()) - -class AbstractTarget: -    """ Base class for all abstract targets. -    """ -    def __init__ (self, name, project, manager = None): -        """ manager:     the Manager object -            name:        name of the target -            project:     the project target to which this one belongs -            manager:the manager object. If none, uses project.manager () -        """ -        assert (isinstance (project, ProjectTarget)) -        # Note: it might seem that we don't need either name or project at all. -        # However, there are places where we really need it. One example is error -        # messages which should name problematic targets. Another is setting correct -        # paths for sources and generated files. -         -        # Why allow manager to be specified? Because otherwise project target could not derive -        # from this class. -        if manager: -            self.manager_ = manager -        else: -            self.manager_ = project.manager () - -        self.name_ = name -        self.project_ = project         -     -    def manager (self): -        return self.manager_ -     -    def name (self): -        """ Returns the name of this target. -        """ -        return self.name_ -     -    def project (self): -        """ Returns the project for this target. -        """ -        return self.project_ -     -    def location (self): -        """ Return the location where the target was declared. -        """ -        return self.location_ -             -    def full_name (self): -        """ Returns a user-readable name for this target. -        """ -        location = self.project ().get ('location') -        return location + '/' + self.name_ -         -    def generate (self, property_set): -        """ Takes a property set.  Generates virtual targets for this abstract -            target, using the specified properties, unless a different value of some -            feature is required by the target.  -            On success, returns a GenerateResult instance with: -                - a property_set with the usage requirements to be -                  applied to dependents  -                - a list of produced virtual targets, which may be -                   empty.   -            If 'property_set' is empty, performs default build of this -            target, in a way specific to derived class. -        """ -        raise BaseException ("method should be defined in derived classes") -     -    def rename (self, new_name): -        self.name_ = new_name - -class ProjectTarget (AbstractTarget): -    """ Project target class (derived from 'AbstractTarget') - -        This class these responsibilities: -        - maintaining a list of main target in this project and -          building it - -        Main targets are constructed in two stages: -        - When Jamfile is read, a number of calls to 'add_alternative' is made. -          At that time, alternatives can also be renamed to account for inline -          targets. -        - The first time 'main-target' or 'has-main-target' rule is called, -          all alternatives are enumerated an main targets are created. -    """ -    def __init__ (self, manager, name, project_module, parent_project, requirements, default_build): -        AbstractTarget.__init__ (self, name, self, manager) -         -        self.project_module_ = project_module -        self.location_ = manager.projects().attribute (project_module, 'location') -        self.requirements_ = requirements -        self.default_build_ = default_build -        -        self.build_dir_ = None -         -        # A cache of IDs -        self.ids_cache_ = {} -         -        # True is main targets have already been built. -        self.built_main_targets_ = False -         -        # A list of the registered alternatives for this project. -        self.alternatives_ = [] - -        # A map from main target name to the target corresponding -        # to it. -        self.main_target_ = {} -         -        # Targets marked as explicit. -        self.explicit_targets_ = set() - -        # Targets marked as always -        self.always_targets_ = set() - -        # The constants defined for this project. -        self.constants_ = {} - -        # Whether targets for all main target are already created. -        self.built_main_targets_ = 0 - -        if parent_project: -            self.inherit (parent_project) - - -    # TODO: This is needed only by the 'make' rule. Need to find the -    # way to make 'make' work without this method. -    def project_module (self): -        return self.project_module_ -     -    def get (self, attribute): -        return self.manager().projects().attribute( -            self.project_module_, attribute) - -    def build_dir (self): -        if not self.build_dir_: -            self.build_dir_ = self.get ('build-dir') -            if not self.build_dir_: -                self.build_dir_ = os.path.join(self.project_.get ('location'), 'bin') - -        return self.build_dir_ - -    def generate (self, ps): -        """ Generates all possible targets contained in this project. -        """ -        self.manager_.targets().log( -            "Building project '%s' with '%s'" % (self.name (), str(ps))) -        self.manager_.targets().increase_indent () -         -        result = GenerateResult () -                 -        for t in self.targets_to_build (): -            g = t.generate (ps) -            result.extend (g) -             -        self.manager_.targets().decrease_indent () -        return result - -    def targets_to_build (self): -        """ Computes and returns a list of AbstractTarget instances which -            must be built when this project is built. -        """ -        result = [] -         -        if not self.built_main_targets_: -            self.build_main_targets () -         -        # Collect all main targets here, except for "explicit" ones. -        for n, t  in self.main_target_.iteritems (): -            if not t.name () in self.explicit_targets_: -                result.append (t) - -        # Collect all projects referenced via "projects-to-build" attribute. -        self_location = self.get ('location') -        for pn in self.get ('projects-to-build'): -            result.append (self.find(pn + "/")) -                         -        return result - -    def mark_targets_as_explicit (self, target_names): -        """Add 'target' to the list of targets in this project -        that should be build only by explicit request.""" -         -        # Record the name of the target, not instance, since this -        # rule is called before main target instaces are created. -        self.explicit_targets_.update(target_names) - -    def mark_targets_as_always(self, target_names): -        self.always_targets_.update(target_names) -     -    def add_alternative (self, target_instance): -        """ Add new target alternative. -        """ -        if self.built_main_targets_: -            raise IllegalOperation ("add-alternative called when main targets are already created for project '%s'" % self.full_name ()) - -        self.alternatives_.append (target_instance) - -    def main_target (self, name): -        if not self.built_main_targets_: -            self.build_main_targets() - -        return self.main_target_[name] - -    def has_main_target (self, name): -        """Tells if a main target with the specified name exists.""" -        if not self.built_main_targets_: -            self.build_main_targets() - -        return self.main_target_.has_key(name) -             -    def create_main_target (self, name): -        """ Returns a 'MainTarget' class instance corresponding to the 'name'. -        """ -        if not self.built_main_targets_: -            self.build_main_targets () -                         -        return self.main_targets_.get (name, None) - - -    def find_really(self, id): -        """ Find and return the target with the specified id, treated -            relative to self. -        """ -        result = None         -        current_location = self.get ('location') - -        __re_split_project_target = re.compile (r'(.*)//(.*)') -        split = __re_split_project_target.match (id) - -        project_part = None -        target_part = None - -        if split: -            project_part = split.group (1) -            target_part = split.group (2) - -        project_registry = self.project_.manager ().projects () -         -        extra_error_message = '' -        if project_part: -            # There's explicit project part in id. Looks up the -            # project and pass the request to it. -            pm = project_registry.find (project_part, current_location) -             -            if pm: -                project_target = project_registry.target (pm) -                result = project_target.find (target_part, no_error=1) - -            else: -                extra_error_message = "error: could not find project '$(project_part)'" - -        else: -            # Interpret target-name as name of main target -            # Need to do this before checking for file. Consider this: -            # -            #  exe test : test.cpp ; -            #  install s : test : <location>. ; -            # -            # After first build we'll have target 'test' in Jamfile and file -            # 'test' on the disk. We need target to override the file. -             -            result = None -            if self.has_main_target(id): -                result = self.main_target(id) - -            if not result: -                result = FileReference (self.manager_, id, self.project_) -                if not result.exists (): -                    # File actually does not exist. -                    # Reset 'target' so that an error is issued. -                    result = None -                     - -            if not result: -                # Interpret id as project-id -                project_module = project_registry.find (id, current_location) -                if project_module: -                    result = project_registry.target (project_module) -                                     -        return result - -    def find (self, id, no_error = False): -        v = self.ids_cache_.get (id, None) -         -        if not v: -            v = self.find_really (id) -            self.ids_cache_ [id] = v - -        if v or no_error: -            return v - -        raise BaseException ("Unable to find file or target named '%s'\nreferred from project at '%s'" % (id, self.get ('location'))) - -     -    def build_main_targets (self): -        self.built_main_targets_ = True -         -        for a in self.alternatives_: -            name = a.name () -            if not self.main_target_.has_key (name): -                t = MainTarget (name, self.project_) -                self.main_target_ [name] = t - -            if name in self.always_targets_: -                a.always() -             -            self.main_target_ [name].add_alternative (a) - -    def add_constant(self, name, value, path=0): -        """Adds a new constant for this project. - -        The constant will be available for use in Jamfile -        module for this project. If 'path' is true, -        the constant will be interpreted relatively -        to the location of project. -        """ - -        if path: -            l = self.location_ -            if not l: -                # Project corresponding to config files do not have  -                # 'location' attribute, but do have source location. -                # It might be more reasonable to make every project have -                # a location and use some other approach to prevent buildable -                # targets in config files, but that's for later. -                l = get('source-location') -                 -            value = os.path.join(l, value) -            # Now make the value absolute path -            value = os.path.join(os.getcwd(), value) - -        self.constants_[name] = value -        bjam.call("set-variable", self.project_module(), name, value) - -    def inherit(self, parent_project): -        for c in parent_project.constants_: -            # No need to pass the type. Path constants were converted to -            # absolute paths already by parent. -            self.add_constant(c, parent_project.constants_[c]) -         -        # Import rules from parent  -        this_module = self.project_module() -        parent_module = parent_project.project_module() - -        rules = bjam.call("RULENAMES", parent_module) -        if not rules: -            rules = [] -        user_rules = [x for x in rules -                      if x not in self.manager().projects().project_rules().all_names()] -        if user_rules: -            bjam.call("import-rules-from-parent", parent_module, this_module, user_rules) -         -class MainTarget (AbstractTarget): -    """ A named top-level target in Jamfile. -    """ -    def __init__ (self, name, project): -        AbstractTarget.__init__ (self, name, project)     -        self.alternatives_ = [] -        self.default_build_ = property_set.empty () -         -    def add_alternative (self, target): -        """ Add a new alternative for this target. -        """ -        d = target.default_build () -         -        if self.alternatives_ and self.default_build_ != d: -            get_manager().errors()("default build must be identical in all alternatives\n" -              "main target is '%s'\n" -              "with '%s'\n" -              "differing from previous default build: '%s'" % (self.full_name (), d.raw (), self.default_build_.raw ())) - -        else: -            self.default_build_ = d - -        self.alternatives_.append (target) - -    def __select_alternatives (self, property_set, debug): -        """ Returns the best viable alternative for this property_set -            See the documentation for selection rules. -            # TODO: shouldn't this be 'alternative' (singular)? -        """ -        # When selecting alternatives we have to consider defaults, -        # for example: -        #    lib l : l.cpp : <variant>debug ; -        #    lib l : l_opt.cpp : <variant>release ; -        # won't work unless we add default value <variant>debug. -        property_set = property_set.add_defaults () -         -        # The algorithm: we keep the current best viable alternative. -        # When we've got new best viable alternative, we compare it -        # with the current one.  -        best = None -        best_properties = None -                         -        if len (self.alternatives_) == 0: -            return None - -        if len (self.alternatives_) == 1: -            return self.alternatives_ [0] - -        if debug: -            print "Property set for selection:", property_set - -        for v in self.alternatives_: -            properties = v.match (property_set, debug) -                        -            if properties is not None: -                if not best: -                    best = v -                    best_properties = properties - -                else: -                    if b2.util.set.equal (properties, best_properties): -                        return None - -                    elif b2.util.set.contains (properties, best_properties): -                        # Do nothing, this alternative is worse -                        pass - -                    elif b2.util.set.contains (best_properties, properties): -                        best = v -                        best_properties = properties - -                    else: -                        return None - -        return best - -    def apply_default_build (self, property_set): -        return apply_default_build(property_set, self.default_build_) - -    def generate (self, ps): -        """ Select an alternative for this main target, by finding all alternatives -            which requirements are satisfied by 'properties' and picking the one with -            longest requirements set. -            Returns the result of calling 'generate' on that alternative. -        """ -        self.manager_.targets ().start_building (self) - -        # We want composite properties in build request act as if -        # all the properties it expands too are explicitly specified. -        ps = ps.expand () -         -        all_property_sets = self.apply_default_build (ps) - -        result = GenerateResult () -         -        for p in all_property_sets: -            result.extend (self.__generate_really (p)) - -        self.manager_.targets ().end_building (self) - -        return result -         -    def __generate_really (self, prop_set): -        """ Generates the main target with the given property set -            and returns a list which first element is property_set object -            containing usage_requirements of generated target and with -            generated virtual target in other elements. It's possible -            that no targets are generated. -        """ -        best_alternative = self.__select_alternatives (prop_set, debug=0) - -        if not best_alternative: -            # FIXME: revive. -            # self.__select_alternatives(prop_set, debug=1) -            self.manager_.errors()( -                "No best alternative for '%s'.\n" -                  % (self.full_name(),)) - -        result = best_alternative.generate (prop_set) -                     -        # Now return virtual targets for the only alternative -        return result -     -    def rename(self, new_name): -        AbstractTarget.rename(self, new_name) -        for a in self.alternatives_: -            a.rename(new_name) - -class FileReference (AbstractTarget): -    """ Abstract target which refers to a source file. -        This is artificial creature; it's usefull so that sources to  -        a target can be represented as list of abstract target instances. -    """ -    def __init__ (self, manager, file, project): -        AbstractTarget.__init__ (self, file, project) -        self.file_location_ = None -     -    def generate (self, properties): -         return GenerateResult (None, [ -             self.manager_.virtual_targets ().from_file ( -             self.name_, self.location(), self.project_) ]) - -    def exists (self): -        """ Returns true if the referred file really exists. -        """ -        if self.location (): -            return True -        else: -            return False - -    def location (self): -        # Returns the location of target. Needed by 'testing.jam' -        if not self.file_location_: -            source_location = self.project_.get('source-location') -             -            for src_dir in source_location: -                location = os.path.join(src_dir, self.name()) -                if os.path.isfile(location): -                    self.file_location_ = src_dir -                    self.file_path = location -                    break - -        return self.file_location_ - -def resolve_reference(target_reference, project): -    """ Given a target_reference, made in context of 'project', -    returns the AbstractTarget instance that is referred to, as well -    as properties explicitly specified for this reference. -    """ -    # Separate target name from properties override -    split = _re_separate_target_from_properties.match (target_reference) -    if not split: -        raise BaseException ("Invalid reference: '%s'" % target_reference) -     -    id = split.group (1) -     -    sproperties = [] -     -    if split.group (3): -        sproperties = property.create_from_strings(feature.split(split.group(3))) -        sproperties = feature.expand_composites(sproperties) -         -    # Find the target -    target = project.find (id) -     -    return (target, property_set.create(sproperties)) - -def generate_from_reference(target_reference, project, property_set): -    """ Attempts to generate the target given by target reference, which -    can refer both to a main target or to a file. -    Returns a list consisting of -    - usage requirements -    - generated virtual targets, if any -    target_reference:  Target reference -    project:           Project where the reference is made -    property_set:      Properties of the main target that makes the reference -    """ -    target, sproperties = resolve_reference(target_reference, project) -     -    # Take properties which should be propagated and refine them -    # with source-specific requirements. -    propagated = property_set.propagated() -    rproperties = propagated.refine(sproperties) -     -    return target.generate(rproperties) - - - -class BasicTarget (AbstractTarget): -    """ Implements the most standard way of constructing main target -        alternative from sources. Allows sources to be either file or -        other main target and handles generation of those dependency -        targets. -    """ -    def __init__ (self, name, project, sources, requirements = None, default_build = None, usage_requirements = None): -        AbstractTarget.__init__ (self, name, project) -     -        for s in sources: -            if get_grist (s): -                raise InvalidSource ("property '%s' found in the 'sources' parameter for '%s'" % (s, name)) -     -        self.sources_ = sources -         -        if not requirements: requirements = property_set.empty () -        self.requirements_ = requirements - -        if not default_build: default_build = property_set.empty () -        self.default_build_ = default_build - -        if not usage_requirements: usage_requirements = property_set.empty () -        self.usage_requirements_ = usage_requirements -         -        # A cache for resolved references -        self.source_targets_ = None -         -        # A cache for generated targets -        self.generated_ = {} -         -        # A cache for build requests -        self.request_cache = {} - -        # Result of 'capture_user_context' has everything. For example, if this -        # target is declare as result of loading Jamfile which was loaded when -        # building target B which was requested from A, then we'll have A, B and -        # Jamroot location in context. We only care about Jamroot location, most -        # of the times. -        self.user_context_ = self.manager_.errors().capture_user_context()[-1:] - -        self.always_ = False - -    def always(self): -        self.always_ = True -         -    def sources (self): -        """ Returns the list of AbstractTargets which are used as sources. -            The extra properties specified for sources are not represented. -            The only used of this rule at the moment is the '--dump-tests' -            feature of the test system.             -        """ -        if self.source_targets_ == None: -            self.source_targets_ = [] -            for s in self.sources_: -                self.source_targets_.append(resolve_reference(s, self.project_)[0]) - -        return self.source_targets_ - -    def requirements (self): -        return self.requirements_ -                         -    def default_build (self): -        return self.default_build_ - -    def common_properties (self, build_request, requirements): -        """ Given build request and requirements, return properties -            common to dependency build request and target build -            properties. -        """ -        # For optimization, we add free unconditional requirements directly, -        # without using complex algorithsm. -        # This gives the complex algorithm better chance of caching results.         -        # The exact effect of this "optimization" is no longer clear -        free_unconditional = [] -        other = [] -        for p in requirements.all(): -            if p.feature().free() and not p.condition() and p.feature().name() != 'conditional': -                free_unconditional.append(p) -            else: -                other.append(p) -        other = property_set.create(other) -                 -        key = (build_request, other) -        if not self.request_cache.has_key(key): -            self.request_cache[key] = self.__common_properties2 (build_request, other) - -        return self.request_cache[key].add_raw(free_unconditional) - -    # Given 'context' -- a set of already present properties, and 'requirements', -    # decide which extra properties should be applied to 'context'.  -    # For conditional requirements, this means evaluating condition. For  -    # indirect conditional requirements, this means calling a rule. Ordinary -    # requirements are always applied. -    # -    # Handles situation where evaluating one conditional requirements affects -    # condition of another conditional requirements, for example: -    # -    #     <toolset>gcc:<variant>release <variant>release:<define>RELEASE -    # -    # If 'what' is 'refined' returns context refined with new requirements.  -    # If 'what' is 'added' returns just the requirements that must be applied. -    def evaluate_requirements(self, requirements, context, what): -        # Apply non-conditional requirements.  -        # It's possible that that further conditional requirement change  -        # a value set by non-conditional requirements. For example: -        # -        #    exe a : a.cpp : <threading>single <toolset>foo:<threading>multi ; -        #  -        # I'm not sure if this should be an error, or not, especially given that -        # -        #    <threading>single  -        # -        # might come from project's requirements. -        unconditional = feature.expand(requirements.non_conditional()) - -        context = context.refine(property_set.create(unconditional)) - -        # We've collected properties that surely must be present in common -        # properties. We now try to figure out what other properties -        # should be added in order to satisfy rules (4)-(6) from the docs. -     -        conditionals = property_set.create(requirements.conditional()) - -        # It's supposed that #conditionals iterations -        # should be enough for properties to propagate along conditions in any -        # direction. -        max_iterations = len(conditionals.all()) +\ -                         len(requirements.get("<conditional>")) + 1 -     -        added_requirements = [] -        current = context -     -        # It's assumed that ordinary conditional requirements can't add -        # <indirect-conditional> properties, and that rules referred -        # by <indirect-conditional> properties can't add new  -        # <indirect-conditional> properties. So the list of indirect conditionals -        # does not change. -        indirect = requirements.get("<conditional>") -     -        ok = 0 -        for i in range(0, max_iterations): - -            e = conditionals.evaluate_conditionals(current).all()[:] -         -            # Evaluate indirect conditionals. -            for i in indirect: -                i = b2.util.jam_to_value_maybe(i) -                if callable(i): -                    # This is Python callable, yeah. -                    e.extend(i(current)) -                else: -                    # Name of bjam function. Because bjam is unable to handle -                    # list of Property, pass list of strings. -                    br = b2.util.call_jam_function(i[1:], [str(p) for p in current.all()]) -                    if br: -                        e.extend(property.create_from_strings(br)) - -            if e == added_requirements: -                # If we got the same result, we've found final properties. -                ok = 1 -                break -            else: -                # Oops, results of evaluation of conditionals has changed. -                # Also 'current' contains leftover from previous evaluation. -                # Recompute 'current' using initial properties and conditional -                # requirements. -                added_requirements = e -                current = context.refine(property_set.create(feature.expand(e))) - -        if not ok: -            self.manager().errors()("Can't evaluate conditional properties " -                                    + str(conditionals)) - -     -        if what == "added": -            return property_set.create(unconditional + added_requirements) -        elif what == "refined": -            return current -        else: -            self.manager().errors("Invalid value of the 'what' parameter") - -    def __common_properties2(self, build_request, requirements): -        # This guarantees that default properties are present -        # in result, unless they are overrided by some requirement. -        # TODO: There is possibility that we've added <foo>bar, which is composite -        # and expands to <foo2>bar2, but default value of <foo2> is not bar2, -        # in which case it's not clear what to do. -        # -        build_request = build_request.add_defaults() -        # Featured added by 'add-default' can be composite and expand -        # to features without default values -- so they are not added yet. -        # It could be clearer/faster to expand only newly added properties -        # but that's not critical. -        build_request = build_request.expand() -       -        return self.evaluate_requirements(requirements, build_request, -                                          "refined") -     -    def match (self, property_set, debug): -        """ Returns the alternative condition for this alternative, if -            the condition is satisfied by 'property_set'. -        """ -        # The condition is composed of all base non-conditional properties. -        # It's not clear if we should expand 'self.requirements_' or not. -        # For one thing, it would be nice to be able to put -        #    <toolset>msvc-6.0  -        # in requirements. -        # On the other hand, if we have <variant>release in condition it  -        # does not make sense to require <optimization>full to be in -        # build request just to select this variant. -        bcondition = self.requirements_.base () -        ccondition = self.requirements_.conditional () -        condition = b2.util.set.difference (bcondition, ccondition) - -        if debug: -            print "    next alternative: required properties:", [str(p) for p in condition] -         -        if b2.util.set.contains (condition, property_set.all()): - -            if debug: -                print "        matched" -             -            return condition - -        else: -            return None - - -    def generate_dependency_targets (self, target_ids, property_set): -        targets = [] -        usage_requirements = [] -        for id in target_ids: -                     -            result = generate_from_reference(id, self.project_, property_set) -            targets += result.targets() -            usage_requirements += result.usage_requirements().all() - -        return (targets, usage_requirements)         -     -    def generate_dependency_properties(self, properties, ps): -        """ Takes a target reference, which might be either target id -            or a dependency property, and generates that target using -            'property_set' as build request. - -            Returns a tuple (result, usage_requirements). -        """ -        result_properties = [] -        usage_requirements = [] -        for p in properties: -                    -            result = generate_from_reference(p.value(), self.project_, ps) - -            for t in result.targets(): -                result_properties.append(property.Property(p.feature(), t)) -             -            usage_requirements += result.usage_requirements().all() - -        return (result_properties, usage_requirements)         - -         - - -    @user_error_checkpoint -    def generate (self, ps): -        """ Determines final build properties, generates sources, -        and calls 'construct'. This method should not be -        overridden. -        """ -        self.manager_.errors().push_user_context( -            "Generating target " + self.full_name(), self.user_context_) -         -        if self.manager().targets().logging(): -            self.manager().targets().log( -                "Building target '%s'" % self.name_) -            self.manager().targets().increase_indent () -            self.manager().targets().log( -                "Build request: '%s'" % str (ps.raw ())) -            cf = self.manager().command_line_free_features() -            self.manager().targets().log( -                "Command line free features: '%s'" % str (cf.raw ()))             -            self.manager().targets().log( -                "Target requirements: %s'" % str (self.requirements().raw ())) -             -        self.manager().targets().push_target(self) - -        if not self.generated_.has_key(ps): - -            # Apply free features form the command line.  If user -            # said  -            #   define=FOO -            # he most likely want this define to be set for all compiles. -            ps = ps.refine(self.manager().command_line_free_features())             -            rproperties = self.common_properties (ps, self.requirements_) - -            self.manager().targets().log( -                "Common properties are '%s'" % str (rproperties)) -           -            if rproperties.get("<build>") != ["no"]: -                 -                result = GenerateResult () - -                properties = rproperties.non_dependency () - -                (p, u) = self.generate_dependency_properties (rproperties.dependency (), rproperties) -                properties += p -                assert all(isinstance(p, property.Property) for p in properties) -                usage_requirements = u - -                (source_targets, u) = self.generate_dependency_targets (self.sources_, rproperties) -                usage_requirements += u - -                self.manager_.targets().log( -                    "Usage requirements for '%s' are '%s'" % (self.name_, usage_requirements)) - -                # FIXME: - -                rproperties = property_set.create(properties + usage_requirements) -                usage_requirements = property_set.create (usage_requirements) - -                self.manager_.targets().log( -                    "Build properties: '%s'" % str(rproperties)) -                 -                source_targets += rproperties.get('<source>') -                 -                # We might get duplicate sources, for example if -                # we link to two library which have the same <library> in -                # usage requirements. -                # Use stable sort, since for some targets the order is -                # important. E.g. RUN_PY target need python source to come -                # first. -                source_targets = unique(source_targets, stable=True) - -                # FIXME: figure why this call messes up source_targets in-place -                result = self.construct (self.name_, source_targets[:], rproperties) - -                if result: -                    assert len(result) == 2 -                    gur = result [0] -                    result = result [1] - -                    if self.always_: -                        for t in result: -                            t.always() - -                    s = self.create_subvariant ( -                        result, -                        self.manager().virtual_targets().recent_targets(), ps, -                        source_targets, rproperties, usage_requirements) -                    self.manager().virtual_targets().clear_recent_targets() -                     -                    ur = self.compute_usage_requirements (s) -                    ur = ur.add (gur) -                    s.set_usage_requirements (ur) - -                    self.manager_.targets().log ( -                        "Usage requirements from '%s' are '%s'" % -                        (self.name(), str(rproperties))) -                     -                    self.generated_[ps] = GenerateResult (ur, result) -                else: -                    self.generated_[ps] = GenerateResult (property_set.empty(), []) -            else: -                # If we just see <build>no, we cannot produce any reasonable -                # diagnostics. The code that adds this property is expected -                # to explain why a target is not built, for example using -                # the configure.log-component-configuration function. - -                # If this target fails to build, add <build>no to properties -                # to cause any parent target to fail to build.  Except that it -                # - does not work now, since we check for <build>no only in -                #   common properties, but not in properties that came from -                #   dependencies -                # - it's not clear if that's a good idea anyway.  The alias -                #   target, for example, should not fail to build if a dependency -                #   fails.                 -                self.generated_[ps] = GenerateResult( -                    property_set.create(["<build>no"]), []) -        else: -            self.manager().targets().log ("Already built") - -        self.manager().targets().pop_target() -        self.manager().targets().decrease_indent() - -        return self.generated_[ps] -     -    def compute_usage_requirements (self, subvariant): -        """ Given the set of generated targets, and refined build  -            properties, determines and sets appripriate usage requirements -            on those targets. -        """ -        rproperties = subvariant.build_properties () -        xusage_requirements =self.evaluate_requirements( -            self.usage_requirements_, rproperties, "added") -         -        # We generate all dependency properties and add them, -        # as well as their usage requirements, to result. -        (r1, r2) = self.generate_dependency_properties(xusage_requirements.dependency (), rproperties) -        extra = r1 + r2 -                 -        result = property_set.create (xusage_requirements.non_dependency () + extra) - -        # Propagate usage requirements we've got from sources, except -        # for the <pch-header> and <pch-file> features. -        # -        # That feature specifies which pch file to use, and should apply -        # only to direct dependents. Consider: -        # -        #   pch pch1 : ... -        #   lib lib1 : ..... pch1 ; -        #   pch pch2 :  -        #   lib lib2 : pch2 lib1 ; -        # -        # Here, lib2 should not get <pch-header> property from pch1. -        # -        # Essentially, when those two features are in usage requirements, -        # they are propagated only to direct dependents. We might need -        # a more general mechanism, but for now, only those two -        # features are special. -        raw = subvariant.sources_usage_requirements().raw() -        raw = property.change(raw, "<pch-header>", None); -        raw = property.change(raw, "<pch-file>", None);               -        result = result.add(property_set.create(raw)) -         -        return result - -    def create_subvariant (self, root_targets, all_targets, -                           build_request, sources, -                           rproperties, usage_requirements): -        """Creates a new subvariant-dg instances for 'targets' -         - 'root-targets' the virtual targets will be returned to dependents -         - 'all-targets' all virtual  -              targets created while building this main target -         - 'build-request' is property-set instance with -         requested build properties""" -          -        for e in root_targets: -            e.root (True) - -        s = Subvariant (self, build_request, sources, -                        rproperties, usage_requirements, all_targets) -         -        for v in all_targets: -            if not v.creating_subvariant(): -                v.creating_subvariant(s) -                 -        return s -         -    def construct (self, name, source_targets, properties): -        """ Constructs the virtual targets for this abstract targets and -            the dependecy graph. Returns a tuple consisting of the properties and the list of virtual targets. -            Should be overrided in derived classes. -        """ -        raise BaseException ("method should be defined in derived classes") - - -class TypedTarget (BasicTarget): -    import generators -     -    def __init__ (self, name, project, type, sources, requirements, default_build, usage_requirements): -        BasicTarget.__init__ (self, name, project, sources, requirements, default_build, usage_requirements) -        self.type_ = type - -    def __jam_repr__(self): -        return b2.util.value_to_jam(self) -     -    def type (self): -        return self.type_ -             -    def construct (self, name, source_targets, prop_set): - -        r = generators.construct (self.project_, name, self.type_,  -                                  prop_set.add_raw(['<main-target-type>' + self.type_]), -                                  source_targets, True) - -        if not r: -            print "warning: Unable to construct '%s'" % self.full_name () - -            # Are there any top-level generators for this type/property set. -            if not generators.find_viable_generators (self.type_, prop_set): -                print "error: no generators were found for type '" + self.type_ + "'" -                print "error: and the requested properties" -                print "error: make sure you've configured the needed tools" -                print "See http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html" -                 -                print "To debug this problem, try the --debug-generators option." -                sys.exit(1) -         -        return r - -def apply_default_build(property_set, default_build): -    # 1. First, see what properties from default_build -    # are already present in property_set.  - -    specified_features = set(p.feature() for p in property_set.all()) - -    defaults_to_apply = [] -    for d in default_build.all(): -        if not d.feature() in specified_features: -            defaults_to_apply.append(d) - -    # 2. If there's any defaults to be applied, form the new -    # build request. Pass it throw 'expand-no-defaults', since -    # default_build might contain "release debug", which will -    # result in two property_sets. -    result = [] -    if defaults_to_apply: - -        # We have to compress subproperties here to prevent -        # property lists like: -        # -        #    <toolset>msvc <toolset-msvc:version>7.1 <threading>multi -        # -        # from being expanded into: -        # -        #    <toolset-msvc:version>7.1/<threading>multi -        #    <toolset>msvc/<toolset-msvc:version>7.1/<threading>multi -        # -        # due to cross-product property combination.  That may -        # be an indication that -        # build_request.expand-no-defaults is the wrong rule -        # to use here. -        compressed = feature.compress_subproperties(property_set.all()) - -        result = build_request.expand_no_defaults( -            b2.build.property_set.create([p]) for p in (compressed + defaults_to_apply)) - -    else: -        result.append (property_set) - -    return result - - -def create_typed_metatarget(name, type, sources, requirements, default_build, usage_requirements): -     -    from b2.manager import get_manager -    t = get_manager().targets() -     -    project = get_manager().projects().current() -         -    return t.main_target_alternative( -        TypedTarget(name, project, type, -                    t.main_target_sources(sources, name), -                    t.main_target_requirements(requirements, project), -                    t.main_target_default_build(default_build, project), -                    t.main_target_usage_requirements(usage_requirements, project))) - - -def create_metatarget(klass, name, sources, requirements=[], default_build=[], usage_requirements=[]): -    from b2.manager import get_manager -    t = get_manager().targets() -     -    project = get_manager().projects().current() -         -    return t.main_target_alternative( -        klass(name, project, -              t.main_target_sources(sources, name), -              t.main_target_requirements(requirements, project), -              t.main_target_default_build(default_build, project), -              t.main_target_usage_requirements(usage_requirements, project)))     - -def metatarget_function_for_class(class_): - -    @bjam_signature((["name"], ["sources", "*"], ["requirements", "*"], -                     ["default_build", "*"], ["usage_requirements", "*"])) -    def create_metatarget(name, sources, requirements = [], default_build = None, usage_requirements = []): - -        from b2.manager import get_manager -        t = get_manager().targets() - -        project = get_manager().projects().current() -         -        return t.main_target_alternative( -            class_(name, project, -                   t.main_target_sources(sources, name), -                   t.main_target_requirements(requirements, project), -                   t.main_target_default_build(default_build, project), -                   t.main_target_usage_requirements(usage_requirements, project))) - -    return create_metatarget diff --git a/jam-files/boost-build/build/toolset.jam b/jam-files/boost-build/build/toolset.jam deleted file mode 100644 index f2036d99..00000000 --- a/jam-files/boost-build/build/toolset.jam +++ /dev/null @@ -1,502 +0,0 @@ -# Copyright 2003 Dave Abrahams -# Copyright 2005 Rene Rivera -# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - -#  Support for toolset definition. - -import errors ; -import feature ; -import generators ; -import numbers ; -import path ; -import property ; -import regex ; -import sequence ; -import set ; - - -.flag-no = 1 ; - -.ignore-requirements = ; - -# This is used only for testing, to make sure we do not get random extra -# elements in paths. -if --ignore-toolset-requirements in [ modules.peek : ARGV ] -{ -    .ignore-requirements = 1 ; -} - - -# Initializes an additional toolset-like module. First load the 'toolset-module' -# and then calls its 'init' rule with trailing arguments. -# -rule using ( toolset-module : * ) -{ -    import $(toolset-module) ; -    $(toolset-module).init $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ; -} - - -# Expands subfeatures in each property sets, e.g. '<toolset>gcc-3.2' will be -# converted to '<toolset>gcc/<toolset-version>3.2'. -# -local rule normalize-condition ( property-sets * ) -{ -    local result ; -    for local p in $(property-sets) -    { -        local split = [ feature.split $(p) ] ; -        local expanded = [ feature.expand-subfeatures [ feature.split $(p) ] ] ; -        result += $(expanded:J=/) ; -    } -    return $(result) ; -} - - -# Specifies if the 'flags' rule should check that the invoking module is the -# same as the module we are setting the flag for. 'v' can be either 'checked' or -# 'unchecked'. Subsequent call to 'pop-checking-for-flags-module' will restore -# the setting that was in effect before calling this rule. -# -rule push-checking-for-flags-module ( v ) -{ -    .flags-module-checking = $(v) $(.flags-module-checking) ; -} - -rule pop-checking-for-flags-module ( ) -{ -    .flags-module-checking = $(.flags-module-checking[2-]) ; -} - - -# Specifies the flags (variables) that must be set on targets under certain -# conditions, described by arguments. -# -rule flags ( -    rule-or-module   # If contains a dot, should be a rule name. The flags will -                     # be applied when that rule is used to set up build -                     # actions. -                     # -                     # If does not contain dot, should be a module name. The -                     # flag will be applied for all rules in that module. If -                     # module for rule is different from the calling module, an -                     # error is issued. - -    variable-name    # Variable that should be set on target. -    condition * :    # A condition when this flag should be applied. Should be a -                     # set of property sets. If one of those property sets is -                     # contained in the build properties, the flag will be used. -                     # Implied values are not allowed: "<toolset>gcc" should be -                     # used, not just "gcc". Subfeatures, like in -                     # "<toolset>gcc-3.2" are allowed. If left empty, the flag -                     # will be used unconditionally. -                     # -                     # Propery sets may use value-less properties ('<a>'  vs. -                     # '<a>value') to match absent properties. This allows to -                     # separately match: -                     # -                     #   <architecture>/<address-model>64 -                     #   <architecture>ia64/<address-model> -                     # -                     # Where both features are optional. Without this syntax -                     # we would be forced to define "default" values. - -    values * :       # The value to add to variable. If <feature> is specified, -                     # then the value of 'feature' will be added. -    unchecked ?      # If value 'unchecked' is passed, will not test that flags -                     # are set for the calling module. -    : hack-hack ?    # For -                     #   flags rule OPTIONS <cxx-abi> : -model ansi -                     # Treat <cxx-abi> as condition -                     # FIXME: ugly hack. -) -{ -    local caller = [ CALLER_MODULE ] ; -    if ! [ MATCH ".*([.]).*" : $(rule-or-module) ] -       && [ MATCH "(Jamfile<.*)" : $(caller) ] -    { -        # Unqualified rule name, used inside Jamfile. Most likely used with -        # 'make' or 'notfile' rules. This prevents setting flags on the entire -        # Jamfile module (this will be considered as rule), but who cares? -        # Probably, 'flags' rule should be split into 'flags' and -        # 'flags-on-module'. -        rule-or-module = $(caller).$(rule-or-module) ; -    } -    else -    { -        local module_ = [ MATCH "([^.]*).*" : $(rule-or-module) ] ; -        if $(unchecked) != unchecked -            && $(.flags-module-checking[1]) != unchecked -            && $(module_) != $(caller) -        { -            errors.error "Module $(caller) attempted to set flags for module $(module_)" ; -        } -    } - -    if $(condition) && ! $(condition:G=) && ! $(hack-hack) -    { -        # We have condition in the form '<feature>', that is, without value. -        # That is an older syntax: -        #   flags gcc.link RPATH <dll-path> ; -        # for compatibility, convert it to -        #   flags gcc.link RPATH : <dll-path> ; -        values = $(condition) ; -        condition = ; -    } - -    if $(condition) -    { -        property.validate-property-sets $(condition) ; -        condition = [ normalize-condition $(condition) ] ; -    } - -    add-flag $(rule-or-module) : $(variable-name) : $(condition) : $(values) ; -} - - -# Adds a new flag setting with the specified values. Does no checking. -# -local rule add-flag ( rule-or-module : variable-name : condition * : values * ) -{ -    .$(rule-or-module).flags += $(.flag-no) ; - -    # Store all flags for a module. -    local module_ = [ MATCH "([^.]*).*" : $(rule-or-module) ] ; -    .module-flags.$(module_) += $(.flag-no) ; -    # Store flag-no -> rule-or-module mapping. -    .rule-or-module.$(.flag-no) = $(rule-or-module) ; - -    .$(rule-or-module).variable.$(.flag-no) += $(variable-name) ; -    .$(rule-or-module).values.$(.flag-no) += $(values) ; -    .$(rule-or-module).condition.$(.flag-no) += $(condition) ; - -    .flag-no = [ numbers.increment $(.flag-no) ] ; -} - - -# Returns the first element of 'property-sets' which is a subset of -# 'properties' or an empty list if no such element exists. -# -rule find-property-subset ( property-sets * : properties * ) -{ -    # Cut property values off. -    local prop-keys = $(properties:G) ; - -    local result ; -    for local s in $(property-sets) -    { -        if ! $(result) -        { -            # Handle value-less properties like '<architecture>' (compare with -            # '<architecture>x86'). - -            local set = [ feature.split $(s) ] ; - -            # Find the set of features that -            # - have no property specified in required property set -            # - are omitted in the build property set. -            local default-props ; -            for local i in $(set) -            { -                # If $(i) is a value-less property it should match default value -                # of an optional property. See the first line in the example -                # below: -                # -                #  property set     properties     result -                # <a> <b>foo      <b>foo           match -                # <a> <b>foo      <a>foo <b>foo    no match -                # <a>foo <b>foo   <b>foo           no match -                # <a>foo <b>foo   <a>foo <b>foo    match -                if ! ( $(i:G=) || ( $(i:G) in $(prop-keys) ) ) -                { -                    default-props += $(i) ; -                } -            } - -            if $(set) in $(properties) $(default-props) -            { -                result = $(s) ; -            } -        } -    } -    return $(result) ; -} - - -# Returns a value to be added to some flag for some target based on the flag's -# value definition and the given target's property set. -# -rule handle-flag-value ( value * : properties * ) -{ -    local result ; -    if $(value:G) -    { -        local matches = [ property.select $(value) : $(properties) ] ; -        for local p in $(matches) -        { -            local att = [ feature.attributes $(p:G) ] ; -            if dependency in $(att) -            { -                # The value of a dependency feature is a target and needs to be -                # actualized. -                result += [ $(p:G=).actualize ] ; -            } -            else if path in $(att) || free in $(att) -            { -                local values ; -                # Treat features with && in the value specially -- each -                # &&-separated element is considered a separate value. This is -                # needed to handle searched libraries or include paths, which -                # may need to be in a specific order. -                if ! [ MATCH (&&) : $(p:G=) ] -                { -                    values = $(p:G=) ; -                } -                else -                { -                    values = [ regex.split $(p:G=) "&&" ] ; -                } -                if path in $(att) -                { -                    result += [ sequence.transform path.native : $(values) ] ; -                } -                else -                { -                    result += $(values) ; -                } -            } -            else -            { -                result += $(p:G=) ; -            } -        } -    } -    else -    { -        result += $(value) ; -    } -    return $(result) ; -} - - -# Given a rule name and a property set, returns a list of interleaved variables -# names and values which must be set on targets for that rule/property-set -# combination. -# -rule set-target-variables-aux ( rule-or-module : property-set ) -{ -    local result ; -    properties = [ $(property-set).raw ] ; -    for local f in $(.$(rule-or-module).flags) -    { -        local variable = $(.$(rule-or-module).variable.$(f)) ; -        local condition = $(.$(rule-or-module).condition.$(f)) ; -        local values = $(.$(rule-or-module).values.$(f)) ; - -        if ! $(condition) || -            [ find-property-subset $(condition) : $(properties) ] -        { -            local processed ; -            for local v in $(values) -            { -                # The value might be <feature-name> so needs special treatment. -                processed += [ handle-flag-value $(v) : $(properties) ] ; -            } -            for local r in $(processed) -            { -                result += $(variable) $(r) ; -            } -        } -    } - -    # Strip away last dot separated part and recurse. -    local next = [ MATCH ^(.+)\\.([^\\.])* : $(rule-or-module) ] ; -    if $(next) -    { -        result += [ set-target-variables-aux $(next[1]) : $(property-set) ] ; -    } -    return $(result) ; -} - - -rule set-target-variables ( rule-or-module targets + : property-set ) -{ -    properties = [ $(property-set).raw ] ; -    local key = $(rule-or-module).$(property-set) ; -    local settings = $(.stv.$(key)) ; -    if ! $(settings) -    { -        settings = [ set-target-variables-aux $(rule-or-module) : -            $(property-set) ] ; - -        if ! $(settings) -        { -            settings = none ; -        } -        .stv.$(key) = $(settings) ; -    } - -    if $(settings) != none -    { -        local var-name = ; -        for local name-or-value in $(settings) -        { -            if $(var-name) -            { -                $(var-name) on $(targets) += $(name-or-value) ; -                var-name = ; -            } -            else -            { -                var-name = $(name-or-value) ; -            } -        } -    } -} - - -# Make toolset 'toolset', defined in a module of the same name, inherit from -# 'base'. -# 1. The 'init' rule from 'base' is imported into 'toolset' with full name. -#    Another 'init' is called, which forwards to the base one. -# 2. All generators from 'base' are cloned. The ids are adjusted and <toolset> -#    property in requires is adjusted too. -# 3. All flags are inherited. -# 4. All rules are imported. -# -rule inherit ( toolset : base ) -{ -    import $(base) ; -    inherit-generators $(toolset) : $(base) ; -    inherit-flags      $(toolset) : $(base) ; -    inherit-rules      $(toolset) : $(base) ; -} - - -rule inherit-generators ( toolset properties * : base : generators-to-ignore * ) -{ -    properties ?= <toolset>$(toolset) ; -    local base-generators = [ generators.generators-for-toolset $(base) ] ; -    for local g in $(base-generators) -    { -        local id = [ $(g).id ] ; - -        if ! $(id) in $(generators-to-ignore) -        { -            # Some generator names have multiple periods in their name, so -            # $(id:B=$(toolset)) does not generate the right new-id name. E.g. -            # if id = gcc.compile.c++ then $(id:B=darwin) = darwin.c++, which is -            # not what we want. Manually parse the base and suffix. If there is -            # a better way to do this, I would love to see it. See also the -            # register() rule in the generators module. -            local base = $(id) ; -            local suffix = "" ; -            while $(base:S) -            { -                suffix = $(base:S)$(suffix) ; -                base = $(base:B) ; -            } -            local new-id = $(toolset)$(suffix) ; - -            generators.register [ $(g).clone $(new-id) : $(properties) ] ; -        } -    } -} - - -# Brings all flag definitions from the 'base' toolset into the 'toolset' -# toolset. Flag definitions whose conditions make use of properties in -# 'prohibited-properties' are ignored. Do not confuse property and feature, for -# example <debug-symbols>on and <debug-symbols>off, so blocking one of them does -# not block the other one. -# -# The flag conditions are not altered at all, so if a condition includes a name, -# or version of a base toolset, it will not ever match the inheriting toolset. -# When such flag settings must be inherited, define a rule in base toolset -# module and call it as needed. -# -rule inherit-flags ( toolset : base : prohibited-properties * : prohibited-vars * ) -{ -    for local f in $(.module-flags.$(base)) -    { -        local rule-or-module = $(.rule-or-module.$(f)) ; -        if ( [ set.difference -            $(.$(rule-or-module).condition.$(f)) : -                  $(prohibited-properties) ]  -                  || ! $(.$(rule-or-module).condition.$(f))  -        ) && ( ! $(.$(rule-or-module).variable.$(f)) in $(prohibited-vars) ) -        { -            local rule_ = [ MATCH "[^.]*\.(.*)" : $(rule-or-module) ] ; -            local new-rule-or-module ; -            if $(rule_) -            { -                new-rule-or-module = $(toolset).$(rule_) ; -            } -            else -            { -                new-rule-or-module = $(toolset) ; -            } - -            add-flag -                $(new-rule-or-module) -                : $(.$(rule-or-module).variable.$(f)) -                : $(.$(rule-or-module).condition.$(f)) -                : $(.$(rule-or-module).values.$(f)) ; -        } -    } -} - - -rule inherit-rules ( toolset : base : localize ? ) -{ -    # It appears that "action" creates a local rule. -    local base-generators = [ generators.generators-for-toolset $(base) ] ; -    local rules ; -    for local g in $(base-generators) -    { -        rules += [ MATCH "[^.]*\.(.*)" : [ $(g).rule-name ] ] ; -    } -    rules = [ sequence.unique $(rules) ] ; -    IMPORT $(base) : $(rules) : $(toolset) : $(rules) : $(localize) ; -    IMPORT $(toolset) : $(rules) : : $(toolset).$(rules) ; -} - - -# Return the list of global 'toolset requirements'. Those requirements will be -# automatically added to the requirements of any main target. -# -rule requirements ( ) -{ -    return $(.requirements) ; -} - - -# Adds elements to the list of global 'toolset requirements'. The requirements -# will be automatically added to the requirements for all main targets, as if -# they were specified literally. For best results, all requirements added should -# be conditional or indirect conditional. -# -rule add-requirements ( requirements * ) -{ -    if ! $(.ignore-requirements) -    { -        .requirements += $(requirements) ; -    } -} - - -rule __test__ ( ) -{ -    import assert ; -    local p = <b>0 <c>1 <d>2 <e>3 <f>4 ; -    assert.result <c>1/<d>2/<e>3 : find-property-subset <c>1/<d>2/<e>3 <a>0/<b>0/<c>1 <d>2/<e>5 <a>9 : $(p) ; -    assert.result : find-property-subset <a>0/<b>0/<c>9/<d>9/<e>5 <a>9 : $(p) ; - -    local p-set = <a>/<b> <a>0/<b> <a>/<b>1 <a>0/<b>1 ; -    assert.result <a>/<b>   : find-property-subset $(p-set) :                ; -    assert.result <a>0/<b>  : find-property-subset $(p-set) : <a>0      <c>2 ; -    assert.result <a>/<b>1  : find-property-subset $(p-set) : <b>1      <c>2 ; -    assert.result <a>0/<b>1 : find-property-subset $(p-set) : <a>0 <b>1      ; -} diff --git a/jam-files/boost-build/build/toolset.py b/jam-files/boost-build/build/toolset.py deleted file mode 100644 index b4267987..00000000 --- a/jam-files/boost-build/build/toolset.py +++ /dev/null @@ -1,398 +0,0 @@ -# Status: being ported by Vladimir Prus -# Base revision:  40958 -# -# Copyright 2003 Dave Abrahams  -# Copyright 2005 Rene Rivera  -# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus  -# Distributed under the Boost Software License, Version 1.0.  -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)  - -""" Support for toolset definition. -""" - -import feature, property, generators, property_set -import b2.util.set -from b2.util import cached, qualify_jam_action -from b2.util.utility import * -from b2.util import bjam_signature -from b2.manager import get_manager - -__re_split_last_segment = re.compile (r'^(.+)\.([^\.])*') -__re_two_ampersands = re.compile ('(&&)') -__re_first_segment = re.compile ('([^.]*).*') -__re_first_group = re.compile (r'[^.]*\.(.*)') - -# Flag is a mechanism to set a value  -# A single toolset flag. Specifies that when certain -# properties are in build property set, certain values -# should be appended to some variable. -# -# A flag applies to a specific action in specific module. -# The list of all flags for a module is stored, and each -# flag further contains the name of the rule it applies -# for,  -class Flag: - -    def __init__(self, variable_name, values, condition, rule = None): -        self.variable_name = variable_name -        self.values = values -        self.condition = condition         -        self.rule = rule - -    def __str__(self): -        return("Flag(" + str(self.variable_name) + ", " + str(self.values) +\ -               ", " + str(self.condition) + ", " + str(self.rule) + ")") - -def reset (): -    """ Clear the module state. This is mainly for testing purposes. -    """ -    global __module_flags, __flags, __stv -     -    # Mapping from module name to a list of all flags that apply -    # to either that module directly, or to any rule in that module. -    # Each element of the list is Flag instance. -    # So, for module named xxx this might contain flags for 'xxx', -    # for 'xxx.compile', for 'xxx.compile.c++', etc. -    __module_flags = {} - -    # Mapping from specific rule or module name to a list of Flag instances -    # that apply to that name. -    # Say, it might contain flags for 'xxx.compile.c++'. If there are -    # entries for module name 'xxx', they are flags for 'xxx' itself, -    # not including any rules in that module. -    __flags = {} -     -    # A cache for varaible settings. The key is generated from the rule name and the properties. -    __stv = {} -     -reset () - -# FIXME: --ignore-toolset-requirements -# FIXME: using -     -# FIXME push-checking-for-flags-module .... -# FIXME: investigate existing uses of 'hack-hack' parameter -# in jam code. -     -@bjam_signature((["rule_or_module", "variable_name", "condition", "*"], -                 ["values", "*"])) -def flags(rule_or_module, variable_name, condition, values = []): -    """ Specifies the flags (variables) that must be set on targets under certain -        conditions, described by arguments. -        rule_or_module:   If contains dot, should be a rule name. -                          The flags will be applied when that rule is -                          used to set up build actions. -                           -                          If does not contain dot, should be a module name. -                          The flags will be applied for all rules in that -                          module. -                          If module for rule is different from the calling -                          module, an error is issued. - -         variable_name:   Variable that should be set on target -          -         condition        A condition when this flag should be applied. -                          Should be set of property sets. If one of -                          those property sets is contained in build -                          properties, the flag will be used. -                          Implied values are not allowed: -                          "<toolset>gcc" should be used, not just -                          "gcc". Subfeatures, like in "<toolset>gcc-3.2" -                          are allowed. If left empty, the flag will -                          always used. -                           -                          Propery sets may use value-less properties  -                          ('<a>'  vs. '<a>value') to match absent  -                          properties. This allows to separately match -                           -                             <architecture>/<address-model>64 -                             <architecture>ia64/<address-model> -                           -                          Where both features are optional. Without this -                          syntax we'd be forced to define "default" value. - -         values:          The value to add to variable. If <feature> -                          is specified, then the value of 'feature'  -                          will be added. -    """ -    caller = bjam.caller()[:-1] -    if not '.' in rule_or_module and caller.startswith("Jamfile"): -        # Unqualified rule name, used inside Jamfile. Most likely used with -        # 'make' or 'notfile' rules. This prevents setting flags on the entire -        # Jamfile module (this will be considered as rule), but who cares? -        # Probably, 'flags' rule should be split into 'flags' and -        # 'flags-on-module'. -        rule_or_module = qualify_jam_action(rule_or_module, caller) -    else: -        # FIXME: revive checking that we don't set flags for a different -        # module unintentionally -        pass -                           -    if condition and not replace_grist (condition, ''): -        # We have condition in the form '<feature>', that is, without -        # value. That's a previous syntax: -        # -        #   flags gcc.link RPATH <dll-path> ; -        # for compatibility, convert it to -        #   flags gcc.link RPATH : <dll-path> ;                 -        values = [ condition ] -        condition = None -     -    if condition: -        transformed = [] -        for c in condition: -            # FIXME: 'split' might be a too raw tool here. -            pl = [property.create_from_string(s) for s in c.split('/')] -            pl = feature.expand_subfeatures(pl); -            transformed.append(property_set.create(pl)) -        condition = transformed - -        property.validate_property_sets(condition) -     -    __add_flag (rule_or_module, variable_name, condition, values) - -def set_target_variables (manager, rule_or_module, targets, ps): -    """ -    """ -    settings = __set_target_variables_aux(manager, rule_or_module, ps) -         -    if settings: -        for s in settings: -            for target in targets: -                manager.engine ().set_target_variable (target, s [0], s[1], True) - -def find_satisfied_condition(conditions, ps): -    """Returns the first element of 'property-sets' which is a subset of -    'properties', or an empty list if no such element exists.""" - -    features = set(p.feature() for p in ps.all()) - -    for condition in conditions: - -        found_all = True -        for i in condition.all(): - -            found = False -            if i.value(): -                found = i.value() in ps.get(i.feature()) -            else:             -                # Handle value-less properties like '<architecture>' (compare with  -                # '<architecture>x86'). -                # If $(i) is a value-less property it should match default  -                # value of an optional property. See the first line in the  -                # example below: -                # -                #  property set     properties     result -                # <a> <b>foo      <b>foo           match -                # <a> <b>foo      <a>foo <b>foo    no match -                # <a>foo <b>foo   <b>foo           no match -                # <a>foo <b>foo   <a>foo <b>foo    match -                found = not i.feature() in features - -            found_all = found_all and found - -        if found_all: -            return condition - -    return None -     - -def register (toolset): -    """ Registers a new toolset. -    """ -    feature.extend('toolset', [toolset]) - -def inherit_generators (toolset, properties, base, generators_to_ignore = []): -    if not properties: -        properties = [replace_grist (toolset, '<toolset>')] -         -    base_generators = generators.generators_for_toolset(base) -     -    for g in base_generators: -        id = g.id() -         -        if not id in generators_to_ignore: -            # Some generator names have multiple periods in their name, so -            # $(id:B=$(toolset)) doesn't generate the right new_id name. -            # e.g. if id = gcc.compile.c++, $(id:B=darwin) = darwin.c++, -            # which is not what we want. Manually parse the base and suffix -            # (if there's a better way to do this, I'd love to see it.) -            # See also register in module generators. -            (base, suffix) = split_action_id(id) - -            new_id = toolset + '.' + suffix - -            generators.register(g.clone(new_id, properties)) - -def inherit_flags(toolset, base, prohibited_properties = []): -    """Brings all flag definitions from the 'base' toolset into the 'toolset' -    toolset. Flag definitions whose conditions make use of properties in -    'prohibited-properties' are ignored. Don't confuse property and feature, for -    example <debug-symbols>on and <debug-symbols>off, so blocking one of them does -    not block the other one. -     -    The flag conditions are not altered at all, so if a condition includes a name, -    or version of a base toolset, it won't ever match the inheriting toolset. When -    such flag settings must be inherited, define a rule in base toolset module and -    call it as needed.""" -    for f in __module_flags.get(base, []): -         -        if not f.condition or b2.util.set.difference(f.condition, prohibited_properties): -            match = __re_first_group.match(f.rule) -            rule_ = None -            if match: -                rule_ = match.group(1) - -            new_rule_or_module = '' - -            if rule_: -                new_rule_or_module = toolset + '.' + rule_ -            else: -                new_rule_or_module = toolset - -            __add_flag (new_rule_or_module, f.variable_name, f.condition, f.values) - -def inherit_rules (toolset, base): -    pass -    # FIXME: do something about this. -#    base_generators = generators.generators_for_toolset (base) - -#    import action - -#    ids = [] -#    for g in base_generators: -#        (old_toolset, id) = split_action_id (g.id ()) -#        ids.append (id) ; - -#    new_actions = [] - -#    engine = get_manager().engine() -    # FIXME: do this! -#    for action in engine.action.values(): -#        pass -#        (old_toolset, id) = split_action_id(action.action_name) -#     -#        if old_toolset == base: -#            new_actions.append ((id, value [0], value [1])) -# -#    for a in new_actions: -#        action.register (toolset + '.' + a [0], a [1], a [2]) -         -    # TODO: how to deal with this? -#       IMPORT $(base) : $(rules) : $(toolset) : $(rules) : localized ; -#       # Import the rules to the global scope -#       IMPORT $(toolset) : $(rules) : : $(toolset).$(rules) ; -#   } -#    - -###################################################################################### -# Private functions - -@cached -def __set_target_variables_aux (manager, rule_or_module, ps): -    """ Given a rule name and a property set, returns a list of tuples of -        variables names and values, which must be set on targets for that -        rule/properties combination.  -    """ -    result = [] - -    for f in __flags.get(rule_or_module, []): -            -        if not f.condition or find_satisfied_condition (f.condition, ps): -            processed = [] -            for v in f.values: -                # The value might be <feature-name> so needs special -                # treatment. -                processed += __handle_flag_value (manager, v, ps) - -            for r in processed: -                result.append ((f.variable_name, r)) -     -    # strip away last dot separated part and recurse. -    next = __re_split_last_segment.match(rule_or_module) -     -    if next: -        result.extend(__set_target_variables_aux( -            manager, next.group(1), ps)) - -    return result - -def __handle_flag_value (manager, value, ps): -    result = [] -     -    if get_grist (value): -        f = feature.get(value) -        values = ps.get(f) -         -        for value in values: - -            if f.dependency(): -                # the value of a dependency feature is a target -                # and must be actualized -                result.append(value.actualize()) - -            elif f.path() or f.free(): -                 -                # Treat features with && in the value -                # specially -- each &&-separated element is considered -                # separate value. This is needed to handle searched -                # libraries, which must be in specific order. -                if not __re_two_ampersands.search(value): -                    result.append(value) - -                else: -                    result.extend(value.split ('&&')) -            else: -                result.append (ungristed) -    else: -        result.append (value) - -    return result - -def __add_flag (rule_or_module, variable_name, condition, values): -    """ Adds a new flag setting with the specified values. -        Does no checking. -    """ -    f = Flag(variable_name, values, condition, rule_or_module) -     -    # Grab the name of the module -    m = __re_first_segment.match (rule_or_module) -    assert m -    module = m.group(1) - -    __module_flags.setdefault(m, []).append(f) -    __flags.setdefault(rule_or_module, []).append(f) - -__requirements = [] - -def requirements(): -    """Return the list of global 'toolset requirements'. -    Those requirements will be automatically added to the requirements of any main target.""" -    return __requirements - -def add_requirements(requirements): -    """Adds elements to the list of global 'toolset requirements'. The requirements -    will be automatically added to the requirements for all main targets, as if -    they were specified literally. For best results, all requirements added should -    be conditional or indirect conditional.""" -     -    #if ! $(.ignore-requirements) -    #{ -    print "XXXX", requirements -    __requirements.extend(requirements) -    #} -          -# Make toolset 'toolset', defined in a module of the same name, -# inherit from 'base' -# 1. The 'init' rule from 'base' is imported into 'toolset' with full -#    name. Another 'init' is called, which forwards to the base one. -# 2. All generators from 'base' are cloned. The ids are adjusted and  -#    <toolset> property in requires is adjusted too -# 3. All flags are inherited -# 4. All rules are imported. -def inherit(toolset, base): -    get_manager().projects().load_module(base, []); - -    inherit_generators(toolset, [], base) -    inherit_flags(toolset, base) -    inherit_rules(toolset, base) diff --git a/jam-files/boost-build/build/type.jam b/jam-files/boost-build/build/type.jam deleted file mode 100644 index 1a7a5782..00000000 --- a/jam-files/boost-build/build/type.jam +++ /dev/null @@ -1,425 +0,0 @@ -# Copyright 2002, 2003 Dave Abrahams -# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - -#  Deals with target type declaration and defines target class which supports -#  typed targets. - -import "class" : new ; -import errors ; -import feature ; -import generators : * ; -import project ; -import property ; -import scanner ; -import os ; - -# The following import would create a circular dependency: -# project -> project-root -> builtin -> type -> targets -> project -# import targets ; - -# The feature is optional so it would never get added implicitly. It is used -# only for internal purposes and in all cases we want to use it explicitly. -feature.feature target-type : : composite optional ; - -feature.feature main-target-type : : optional incidental ; -feature.feature base-target-type : : composite optional free ; - - -# Registers a target type, possible derived from a 'base-type'. Providing a list -# of 'suffixes' here is a shortcut for separately calling the register-suffixes -# rule with the given suffixes and the set-generated-target-suffix rule with the -# first given suffix. -# -rule register ( type : suffixes * : base-type ? ) -{ -    # Type names cannot contain hyphens, because when used as feature-values -    # they would be interpreted as composite features which need to be -    # decomposed. -    switch $(type) -    { -        case *-* : errors.error "type name \"$(type)\" contains a hyphen" ; -    } - -    if $(type) in $(.types) -    { -        errors.error "Type $(type) is already registered." ; -    } -    else -    { -        .types += $(type) ; -        .base.$(type) = $(base-type) ; -        .derived.$(base-type) += $(type) ; - -        if $(suffixes)-is-not-empty -        { -            # Specify mapping from suffixes to type. -            register-suffixes $(suffixes) : $(type) ; -            # By default generated targets of 'type' will use the first of -            #'suffixes'. This may be overriden. -            set-generated-target-suffix $(type) : : $(suffixes[1]) ; -        } - -        feature.extend target-type      : $(type) ; -        feature.extend main-target-type : $(type) ; -        feature.extend base-target-type : $(type) ; - -        feature.compose <target-type>$(type) : $(base-type:G=<base-target-type>) ; -        feature.compose <base-target-type>$(type) : <base-target-type>$(base-type) ; - -        # We used to declare the main target rule only when a 'main' parameter -        # has been specified. However, it is hard to decide that a type will -        # *never* need a main target rule and so from time to time we needed to -        # make yet another type 'main'. So now a main target rule is defined for -        # each type. -        main-rule-name = [ type-to-rule-name $(type) ] ; -        .main-target-type.$(main-rule-name) = $(type) ; -        IMPORT $(__name__) : main-target-rule : : $(main-rule-name) ; - -        # Adding a new derived type affects generator selection so we need to -        # make the generator selection module update any of its cached -        # information related to a new derived type being defined. -        generators.update-cached-information-with-a-new-type $(type) ; -    } -} - - -# Given a type, returns the name of the main target rule which creates targets -# of that type. -# -rule type-to-rule-name ( type ) -{ -    # Lowercase everything. Convert underscores to dashes. -    import regex ; -    local n = [ regex.split $(type:L) "_" ] ; -    return $(n:J=-) ; -} - - -# Given a main target rule name, returns the type for which it creates targets. -# -rule type-from-rule-name ( rule-name ) -{ -    return $(.main-target-type.$(rule-name)) ; -} - - -# Specifies that files with suffix from 'suffixes' be recognized as targets of -# type 'type'. Issues an error if a different type is already specified for any -# of the suffixes. -# -rule register-suffixes ( suffixes + : type ) -{ -    for local s in $(suffixes) -    { -        if ! $(.type.$(s)) -        { -            .type.$(s) = $(type) ; -        } -        else if $(.type.$(s)) != $(type) -        { -            errors.error Attempting to specify multiple types for suffix -                \"$(s)\" : "Old type $(.type.$(s)), New type $(type)" ; -        } -    } -} - - -# Returns true iff type has been registered. -# -rule registered ( type ) -{ -    if $(type) in $(.types) -    { -        return true ; -    } -} - - -# Issues an error if 'type' is unknown. -# -rule validate ( type ) -{ -    if ! [ registered $(type) ] -    { -        errors.error "Unknown target type $(type)" ; -    } -} - - -# Sets a scanner class that will be used for this 'type'. -# -rule set-scanner ( type : scanner ) -{ -    validate $(type) ; -    .scanner.$(type) = $(scanner) ; -} - - -# Returns a scanner instance appropriate to 'type' and 'properties'. -# -rule get-scanner ( type : property-set ) -{ -    if $(.scanner.$(type)) -    { -        return [ scanner.get $(.scanner.$(type)) : $(property-set) ] ; -    } -} - - -# Returns a base type for the given type or nothing in case the given type is -# not derived. -# -rule base ( type ) -{ -    return $(.base.$(type)) ; -} - - -# Returns the given type and all of its base types in order of their distance -# from type. -# -rule all-bases ( type ) -{ -    local result = $(type) ; -    while $(type) -    { -        type = [ base $(type) ] ; -        result += $(type) ; -    } -    return $(result) ; -} - - -# Returns the given type and all of its derived types in order of their distance -# from type. -# -rule all-derived ( type ) -{ -    local result = $(type) ; -    for local d in $(.derived.$(type)) -    { -        result += [ all-derived $(d) ] ; -    } -    return $(result) ; -} - - -# Returns true if 'type' is equal to 'base' or has 'base' as its direct or -# indirect base. -# -rule is-derived ( type base ) -{ -    if $(base) in [ all-bases $(type) ] -    { -        return true ; -    } -} - -# Returns true if 'type' is either derived from or is equal to 'base'. -# -# TODO: It might be that is-derived and is-subtype were meant to be different -# rules - one returning true for type = base and one not, but as currently -# implemented they are actually the same. Clean this up. -# -rule is-subtype ( type base ) -{ -    return [ is-derived $(type) $(base) ] ; -} - - -# Store suffixes for generated targets. -.suffixes = [ new property-map ] ; - -# Store prefixes for generated targets (e.g. "lib" for library). -.prefixes = [ new property-map ] ; - - -# Sets a file suffix to be used when generating a target of 'type' with the -# specified properties. Can be called with no properties if no suffix has -# already been specified for the 'type'. The 'suffix' parameter can be an empty -# string ("") to indicate that no suffix should be used. -# -# Note that this does not cause files with 'suffix' to be automatically -# recognized as being of 'type'. Two different types can use the same suffix for -# their generated files but only one type can be auto-detected for a file with -# that suffix. User should explicitly specify which one using the -# register-suffixes rule. -# -rule set-generated-target-suffix ( type : properties * : suffix ) -{ -    set-generated-target-ps suffix : $(type) : $(properties) : $(suffix) ; -} - - -# Change the suffix previously registered for this type/properties combination. -# If suffix is not yet specified, sets it. -# -rule change-generated-target-suffix ( type : properties * : suffix ) -{ -    change-generated-target-ps suffix : $(type) : $(properties) : $(suffix) ; -} - - -# Returns the suffix used when generating a file of 'type' with the given -# properties. -# -rule generated-target-suffix ( type : property-set ) -{ -    return [ generated-target-ps suffix : $(type) : $(property-set) ] ; -} - - -# Sets a target prefix that should be used when generating targets of 'type' -# with the specified properties. Can be called with empty properties if no -# prefix for 'type' has been specified yet. -# -# The 'prefix' parameter can be empty string ("") to indicate that no prefix -# should be used. -# -# Usage example: library names use the "lib" prefix on unix. -# -rule set-generated-target-prefix ( type : properties * : prefix ) -{ -    set-generated-target-ps prefix : $(type) : $(properties) : $(prefix) ; -} - - -# Change the prefix previously registered for this type/properties combination. -# If prefix is not yet specified, sets it. -# -rule change-generated-target-prefix ( type : properties * : prefix ) -{ -    change-generated-target-ps prefix : $(type) : $(properties) : $(prefix) ; -} - - -rule generated-target-prefix ( type : property-set ) -{ -    return [ generated-target-ps prefix : $(type) : $(property-set) ] ; -} - - -# Common rules for prefix/suffix provisioning follow. - -local rule set-generated-target-ps ( ps : type : properties * : psval ) -{ -    properties = <target-type>$(type) $(properties) ; -    $(.$(ps)es).insert $(properties) : $(psval) ; -} - - -local rule change-generated-target-ps ( ps : type : properties * : psval ) -{ -    properties = <target-type>$(type) $(properties) ; -    local prev = [ $(.$(ps)es).find-replace $(properties) : $(psval) ] ; -    if ! $(prev) -    { -        set-generated-target-ps $(ps) : $(type) : $(properties) : $(psval) ; -    } -} - - -# Returns either prefix or suffix (as indicated by 'ps') that should be used -# when generating a target of 'type' with the specified properties. Parameter -# 'ps' can be either "prefix" or "suffix".  If no prefix/suffix is specified for -# 'type', returns prefix/suffix for base type, if any. -# -local rule generated-target-ps-real ( ps : type : properties * ) -{ -    local result ; -    local found ; -    while $(type) && ! $(found) -    { -        result = [ $(.$(ps)es).find <target-type>$(type) $(properties) ] ; -        # If the prefix/suffix is explicitly set to an empty string, we consider -        # prefix/suffix to be found. If we were not to compare with "", there -        # would be no way to specify an empty prefix/suffix. -        if $(result)-is-not-empty -        { -            found = true ; -        } -        type = $(.base.$(type)) ; -    } -    if $(result) = "" -    { -        result = ; -    } -    return $(result) ; -} - - -local rule generated-target-ps ( ps : type : property-set ) -{ -    local key = .$(ps).$(type).$(property-set) ; -    local v = $($(key)) ; -    if ! $(v) -    { -        v = [ generated-target-ps-real $(ps) : $(type) : [ $(property-set).raw ] -            ] ; -        if ! $(v) -        { -            v = none ; -        } -        $(key) = $(v) ; -    } - -    if $(v) != none -    { -        return $(v) ; -    } -} - - -# Returns file type given its name. If there are several dots in filename, tries -# each suffix. E.g. for name of "file.so.1.2" suffixes "2", "1", and "so" will -# be tried. -# -rule type ( filename ) -{ -    if [ os.name ] in NT CYGWIN -    { -        filename = $(filename:L) ; -    }     -    local type ; -    while ! $(type) && $(filename:S) -    { -        local suffix = $(filename:S) ; -        type = $(.type$(suffix)) ; -        filename = $(filename:S=) ; -    } -    return $(type) ; -} - - -# Rule used to construct all main targets. Note that this rule gets imported -# into the global namespace under different alias names and the exact target -# type to construct is selected based on the alias used to actually invoke this -# rule. -# -rule main-target-rule ( name : sources * : requirements * : default-build * : -    usage-requirements * ) -{ -    # First discover the required target type based on the exact alias used to -    # invoke this rule. -    local bt = [ BACKTRACE 1 ] ; -    local rulename = $(bt[4]) ; -    local target-type = [ type-from-rule-name $(rulename) ] ; - -    # This is a circular module dependency and so must be imported here. -    import targets ; - -    return [ targets.create-typed-target $(target-type) : [ project.current ] : -        $(name) : $(sources) : $(requirements) : $(default-build) : -        $(usage-requirements) ] ; -} - - -rule __test__ ( ) -{ -    import assert ; - -    # TODO: Add tests for all the is-derived, is-base & related type relation -    # checking rules. -} diff --git a/jam-files/boost-build/build/type.py b/jam-files/boost-build/build/type.py deleted file mode 100644 index ddb7ba09..00000000 --- a/jam-files/boost-build/build/type.py +++ /dev/null @@ -1,313 +0,0 @@ -# Status: ported. -# Base revision: 45462. - -#  Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and -#  distribute this software is granted provided this copyright notice appears in -#  all copies. This software is provided "as is" without express or implied -#  warranty, and with no claim as to its suitability for any purpose. - - - -import re -import os -import os.path -from b2.util.utility import replace_grist, os_name -from b2.exceptions import * -from b2.build import feature, property, scanner -from b2.util import bjam_signature - - -__re_hyphen = re.compile ('-') - -def __register_features (): -    """ Register features need by this module. -    """ -    # The feature is optional so that it is never implicitly added. -    # It's used only for internal purposes, and in all cases we -    # want to explicitly use it. -    feature.feature ('target-type', [], ['composite', 'optional']) -    feature.feature ('main-target-type', [], ['optional', 'incidental']) -    feature.feature ('base-target-type', [], ['composite', 'optional', 'free']) - -def reset (): -    """ Clear the module state. This is mainly for testing purposes. -        Note that this must be called _after_ resetting the module 'feature'. -    """     -    global __prefixes_suffixes, __suffixes_to_types, __types, __rule_names_to_types, __target_suffixes_cache -     -    __register_features () - -    # Stores suffixes for generated targets. -    __prefixes_suffixes = [property.PropertyMap(), property.PropertyMap()] -     -    # Maps suffixes to types -    __suffixes_to_types = {} -     -    # A map with all the registered types, indexed by the type name -    # Each entry is a dictionary with following values: -    # 'base': the name of base type or None if type has no base -    # 'derived': a list of names of type which derive from this one -    # 'scanner': the scanner class registered for this type, if any -    __types = {} - -    # Caches suffixes for targets with certain properties. -    __target_suffixes_cache = {} -     -reset () - -@bjam_signature((["type"], ["suffixes", "*"], ["base_type", "?"])) -def register (type, suffixes = [], base_type = None): -    """ Registers a target type, possibly derived from a 'base-type'.  -        If 'suffixes' are provided, they list all the suffixes that mean a file is of 'type'. -        Also, the first element gives the suffix to be used when constructing and object of -        'type'. -        type: a string -        suffixes: None or a sequence of strings -        base_type: None or a string -    """ -    # Type names cannot contain hyphens, because when used as -    # feature-values they will be interpreted as composite features -    # which need to be decomposed. -    if __re_hyphen.search (type): -        raise BaseException ('type name "%s" contains a hyphen' % type) -     -    if __types.has_key (type): -        raise BaseException ('Type "%s" is already registered.' % type) - -    entry = {} -    entry ['base'] = base_type -    entry ['derived'] = [] -    entry ['scanner'] = None -    __types [type] = entry -     -    if base_type: -        __types [base_type]['derived'].append (type) - -    if len (suffixes) > 0: -        # Generated targets of 'type' will use the first of 'suffixes' -        # (this may be overriden) -        set_generated_target_suffix (type, [], suffixes [0]) -         -        # Specify mapping from suffixes to type -        register_suffixes (suffixes, type) -     -    feature.extend('target-type', [type]) -    feature.extend('main-target-type', [type]) -    feature.extend('base-target-type', [type]) - -    if base_type: -        feature.compose ('<target-type>' + type, replace_grist (base_type, '<base-target-type>')) -        feature.compose ('<base-target-type>' + type, '<base-target-type>' + base_type) - -    import b2.build.generators as generators -    # Adding a new derived type affects generator selection so we need to -    # make the generator selection module update any of its cached -    # information related to a new derived type being defined. -    generators.update_cached_information_with_a_new_type(type) - -    # FIXME: resolving recursive dependency. -    from b2.manager import get_manager -    get_manager().projects().project_rules().add_rule_for_type(type) - -# FIXME: quick hack. -def type_from_rule_name(rule_name): -    return rule_name.upper().replace("-", "_") - - -def register_suffixes (suffixes, type): -    """ Specifies that targets with suffix from 'suffixes' have the type 'type'.  -        If a different type is already specified for any of syffixes, issues an error. -    """ -    for s in suffixes: -        if __suffixes_to_types.has_key (s): -            old_type = __suffixes_to_types [s] -            if old_type != type: -                raise BaseException ('Attempting to specify type for suffix "%s"\nOld type: "%s", New type "%s"' % (s, old_type, type)) -        else: -            __suffixes_to_types [s] = type - -def registered (type): -    """ Returns true iff type has been registered. -    """ -    return __types.has_key (type) - -def validate (type): -    """ Issues an error if 'type' is unknown. -    """ -    if not registered (type): -        raise BaseException ("Unknown target type '%s'" % type) - -def set_scanner (type, scanner): -    """ Sets a scanner class that will be used for this 'type'. -    """ -    validate (type) -    __types [type]['scanner'] = scanner - -def get_scanner (type, prop_set): -    """ Returns a scanner instance appropriate to 'type' and 'property_set'. -    """ -    if registered (type): -        scanner_type = __types [type]['scanner'] -        if scanner_type: -            return scanner.get (scanner_type, prop_set.raw ()) -            pass -             -    return None - -def base(type): -    """Returns a base type for the given type or nothing in case the given type is -    not derived.""" - -    return __types[type]['base'] - -def all_bases (type): -    """ Returns type and all of its bases, in the order of their distance from type. -    """ -    result = [] -    while type: -        result.append (type) -        type = __types [type]['base'] - -    return result - -def all_derived (type): -    """ Returns type and all classes that derive from it, in the order of their distance from type. -    """ -    result = [type] -    for d in __types [type]['derived']: -        result.extend (all_derived (d)) - -    return result - -def is_derived (type, base): -    """ Returns true if 'type' is 'base' or has 'base' as its direct or indirect base. -    """ -    # TODO: this isn't very efficient, especially for bases close to type -    if base in all_bases (type): -        return True -    else:  -        return False - -def is_subtype (type, base): -    """ Same as is_derived. Should be removed. -    """ -    # TODO: remove this method -    return is_derived (type, base) - -@bjam_signature((["type"], ["properties", "*"], ["suffix"])) -def set_generated_target_suffix (type, properties, suffix): -    """ Sets a target suffix that should be used when generating target  -        of 'type' with the specified properties. Can be called with -        empty properties if no suffix for 'type' was specified yet. -        This does not automatically specify that files 'suffix' have -        'type' --- two different types can use the same suffix for -        generating, but only one type should be auto-detected for -        a file with that suffix. User should explicitly specify which -        one. - -        The 'suffix' parameter can be empty string ("") to indicate that -        no suffix should be used. -    """ -    set_generated_target_ps(1, type, properties, suffix) - - -     -def change_generated_target_suffix (type, properties, suffix): -    """ Change the suffix previously registered for this type/properties  -        combination. If suffix is not yet specified, sets it. -    """ -    change_generated_target_ps(1, type, properties, suffix) - -def generated_target_suffix(type, properties): -    return generated_target_ps(1, type, properties) - -# Sets a target prefix that should be used when generating targets of 'type' -# with the specified properties. Can be called with empty properties if no -# prefix for 'type' has been specified yet. -# -# The 'prefix' parameter can be empty string ("") to indicate that no prefix -# should be used. -# -# Usage example: library names use the "lib" prefix on unix. -@bjam_signature((["type"], ["properties", "*"], ["suffix"])) -def set_generated_target_prefix(type, properties, prefix): -    set_generated_target_ps(0, type, properties, prefix) - -# Change the prefix previously registered for this type/properties combination. -# If prefix is not yet specified, sets it. -def change_generated_target_prefix(type, properties, prefix): -    change_generated_target_ps(0, type, properties, prefix) - -def generated_target_prefix(type, properties): -    return generated_target_ps(0, type, properties) - -def set_generated_target_ps(is_suffix, type, properties, val): -    properties.append ('<target-type>' + type) -    __prefixes_suffixes[is_suffix].insert (properties, val) - -def change_generated_target_ps(is_suffix, type, properties, val): -    properties.append ('<target-type>' + type) -    prev = __prefixes_suffixes[is_suffix].find_replace(properties, val) -    if not prev: -        set_generated_target_ps(is_suffix, type, properties, val) - -# Returns either prefix or suffix (as indicated by 'is_suffix') that should be used -# when generating a target of 'type' with the specified properties. -# If no prefix/suffix is specified for 'type', returns prefix/suffix for -# base type, if any. -def generated_target_ps_real(is_suffix, type, properties): - -    result = '' -    found = False -    while type and not found: -        result = __prefixes_suffixes[is_suffix].find (['<target-type>' + type] + properties) - -        # Note that if the string is empty (""), but not null, we consider -        # suffix found.  Setting prefix or suffix to empty string is fine. -        if result is not None: -            found = True - -        type = __types [type]['base'] - -    if not result: -        result = '' -    return result - -def generated_target_ps(is_suffix, type, prop_set): -    """ Returns suffix that should be used when generating target of 'type', -        with the specified properties. If not suffix were specified for -        'type', returns suffix for base type, if any. -    """ -    key = (is_suffix, type, prop_set) -    v = __target_suffixes_cache.get(key, None) - -    if not v: -        v = generated_target_ps_real(is_suffix, type, prop_set.raw()) -        __target_suffixes_cache [key] = v - -    return v - -def type(filename): -    """ Returns file type given it's name. If there are several dots in filename, -        tries each suffix. E.g. for name of "file.so.1.2" suffixes "2", "1", and  -        "so"  will be tried. -    """ -    while 1: -        filename, suffix = os.path.splitext (filename) -        if not suffix: return None -        suffix = suffix[1:] -         -        if __suffixes_to_types.has_key(suffix): -            return __suffixes_to_types[suffix] - -# NOTE: moved from tools/types/register -def register_type (type, suffixes, base_type = None, os = []): -    """ Register the given type on the specified OSes, or on remaining OSes -        if os is not specified.  This rule is injected into each of the type -        modules for the sake of convenience. -    """ -    if registered (type): -        return - -    if not os or os_name () in os: -        register (type, suffixes, base_type) diff --git a/jam-files/boost-build/build/version.jam b/jam-files/boost-build/build/version.jam deleted file mode 100644 index 7626ddda..00000000 --- a/jam-files/boost-build/build/version.jam +++ /dev/null @@ -1,161 +0,0 @@ -# Copyright 2002, 2003, 2004, 2006 Vladimir Prus -# Copyright 2008 Jurko Gospodnetic -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - -import errors ; -import numbers ; - -major = "2011" ; -minor = "04" ; - -rule boost-build ( ) -{ -    return "$(major).$(minor)-svn" ; -} - -rule print ( ) -{ -    if [ verify-engine-version ] -    {         -        ECHO "Boost.Build" [ boost-build ] ; -    }     -} - -rule verify-engine-version ( ) -{ -    local v = [ modules.peek : JAM_VERSION ] ; -     -    if $(v[1]) != $(major) || $(v[2]) != $(minor) -    { -        local argv = [ modules.peek : ARGV ] ; -        local e = $(argv[1]) ; -        local l = [ modules.binding version ] ; -        l = $(l:D) ; -        l = $(l:D) ; -        ECHO "warning: mismatched versions of Boost.Build engine and core" ; -        ECHO "warning: Boost.Build engine ($(e)) is $(v:J=.)" ; -        ECHO "warning: Boost.Build core (at $(l)) is" [ boost-build ] ; -    } -    else -    { -        return true ; -    }     -} - - - -# Utility rule for testing whether all elements in a sequence are equal to 0. -# -local rule is-all-zeroes ( sequence * ) -{ -    local result = "true" ; -    for local e in $(sequence) -    { -        if $(e) != "0" -        { -            result = "" ; -        } -    } -    return $(result) ; -} - - -# Returns "true" if the first version is less than the second one. -# -rule version-less ( lhs + : rhs + ) -{ -    numbers.check $(lhs) ; -    numbers.check $(rhs) ; - -    local done ; -    local result ; - -    while ! $(done) && $(lhs) && $(rhs) -    { -        if [ numbers.less $(lhs[1]) $(rhs[1]) ] -        { -            done = "true" ; -            result = "true" ; -        } -        else if [ numbers.less $(rhs[1]) $(lhs[1])  ] -        { -            done = "true" ; -        } -        else -        { -            lhs = $(lhs[2-]) ; -            rhs = $(rhs[2-]) ; -        } -    } -    if ( ! $(done) && ! $(lhs) && ! [ is-all-zeroes $(rhs) ] ) -    { -        result = "true" ; -    } -     -    return $(result) ; -} - - -# Returns "true" if the current JAM version version is at least the given -# version. -# -rule check-jam-version ( version + ) -{ -    local version-tag = $(version:J=.) ; -    if ! $(version-tag) -    { -        errors.error Invalid version specifier: : $(version:E="(undefined)") ; -    } - -    if ! $(.jam-version-check.$(version-tag))-is-not-empty -    { -        local jam-version = [ modules.peek : JAM_VERSION ] ; -        if ! $(jam-version) -        { -            errors.error "Unable to deduce Boost Jam version. Your Boost Jam" -                "installation is most likely terribly outdated." ; -        } -        .jam-version-check.$(version-tag) = "true" ; -        if [ version-less [ modules.peek : JAM_VERSION ] : $(version) ] -        { -            .jam-version-check.$(version-tag) = "" ; -        } -    } -    return $(.jam-version-check.$(version-tag)) ; -} - - -rule __test__ ( ) -{ -    import assert ; -     -    local jam-version = [ modules.peek : JAM_VERSION ] ; -    local future-version = $(jam-version) ; -    future-version += "1" ; - -    assert.true  check-jam-version $(jam-version)    ; -    assert.false check-jam-version $(future-version) ; - -    assert.true  version-less  0          :  1          ; -    assert.false version-less  0          :  0          ; -    assert.true  version-less  1          :  2          ; -    assert.false version-less  1          :  1          ; -    assert.false version-less  2          :  1          ; -    assert.true  version-less  3 1 20     :  3 4 10     ; -    assert.false version-less  3 1 10     :  3 1 10     ; -    assert.false version-less  3 4 10     :  3 1 20     ; -    assert.true  version-less  3 1 20 5 1 :  3 4 10     ; -    assert.false version-less  3 1 10 5 1 :  3 1 10     ; -    assert.false version-less  3 4 10 5 1 :  3 1 20     ; -    assert.true  version-less  3 1 20     :  3 4 10 5 1 ; -    assert.true  version-less  3 1 10     :  3 1 10 5 1 ; -    assert.false version-less  3 4 10     :  3 1 20 5 1 ; -    assert.false version-less  3 1 10     :  3 1 10 0 0 ; -    assert.false version-less  3 1 10 0 0 :  3 1 10     ; -    assert.false version-less  3 1 10 0   :  3 1 10 0 0 ; -    assert.false version-less  3 1 10 0   : 03 1 10 0 0 ; -    assert.false version-less 03 1 10 0   :  3 1 10 0 0 ; - -    # TODO: Add tests for invalid input data being sent to version-less. -} diff --git a/jam-files/boost-build/build/virtual-target.jam b/jam-files/boost-build/build/virtual-target.jam deleted file mode 100644 index 2e8446bc..00000000 --- a/jam-files/boost-build/build/virtual-target.jam +++ /dev/null @@ -1,1317 +0,0 @@ -# Copyright 2003 Dave Abrahams -# Copyright 2005, 2006 Rene Rivera -# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - -# Implements virtual targets, which correspond to actual files created during a -# build, but are not yet targets in Jam sense. They are needed, for example, -# when searching for possible transformation sequences, when it is not yet known -# whether a particular target should be created at all. - -import "class" : new ; -import errors ; -import path ; -import sequence ; -import set ; -import type ; -import utility ; - - -#                       +--------------------------+ -#                       | virtual-target           | -#                       +==========================+ -#                       | actualize                | -#                       +--------------------------+ -#                       | actualize-action() = 0   | -#                       | actualize-location() = 0 | -#                       +----------------+---------+ -#                                        | -#                                        ^ -#                                       / \ -#                                      +-+-+ -#                                        | -#    +---------------------+     +-------+--------------+ -#    | action              |     | abstract-file-target | -#    +=====================|   * +======================+ -#    | action-name         |  +--+ action               | -#    | properties          |  |  +----------------------+ -#    +---------------------+--+  | actualize-action()   | -#    | actualize()         |0..1 +-----------+----------+ -#    | path()              |                 | -#    | adjust-properties() | sources         | -#    | actualize-sources() | targets         | -#    +------+--------------+                 ^ -#           |                               / \ -#           ^                              +-+-+ -#          / \                               | -#         +-+-+                +-------------+-------------+ -#           |                  |                           | -#           |           +------+---------------+  +--------+-------------+ -#           |           | file-target          |  | searched-lib-target  | -#           |           +======================+  +======================+ -#           |           | actualize-location() |  | actualize-location() | -#           |           +----------------------+  +----------------------+ -#           | -#         +-+------------------------------+ -#         |                                | -#    +----+----------------+     +---------+-----------+ -#    | compile-action      |     | link-action         | -#    +=====================+     +=====================+ -#    | adjust-properties() |     | adjust-properties() | -#    +---------------------+     | actualize-sources() | -#                                +---------------------+ -# -# The 'compile-action' and 'link-action' classes are not defined here but in -# builtin.jam modules. They are shown in the diagram to give the big picture. - - -# Models a potential target. It can be converted into a Jam target and used in -# building, if needed. However, it can be also dropped, which allows us to -# search for different transformations and select only one. -# -class virtual-target -{ -    import scanner ; -    import sequence ; -    import utility ; -    import virtual-target ; - -    rule __init__ ( -          name     # Target/project name. -        : project  # Project to which this target belongs. -    ) -    { -        self.name = $(name) ; -        self.project = $(project) ; -        self.dependencies = ; -    } - -    # Name of this target. -    # -    rule name ( ) -    { -        return $(self.name) ; -    } - -    # Project of this target. -    # -    rule project ( ) -    { -        return $(self.project) ; -    } - -    # Adds additional 'virtual-target' instances this one depends on. -    # -    rule depends ( d + ) -    { -        self.dependencies = [ sequence.merge $(self.dependencies) : -            [ sequence.insertion-sort $(d) ] ] ; -    } - -    rule dependencies ( ) -    { -        return $(self.dependencies) ; -    } -     -    rule always ( ) -    { -        .always = 1 ; -    } -     -    # Generates all the actual targets and sets up build actions for this -    # target. -    # -    # If 'scanner' is specified, creates an additional target with the same -    # location as the actual target, which will depend on the actual target and -    # be associated with a 'scanner'. That additional target is returned. See -    # the docs (#dependency_scanning) for rationale. Target must correspond to a -    # file if 'scanner' is specified. -    # -    # If scanner is not specified then the actual target is returned. -    # -    rule actualize ( scanner ? ) -    { -        local actual-name = [ actualize-no-scanner ] ; -         -        if $(.always) -        { -            ALWAYS $(actual-name) ; -        } -         -        if ! $(scanner) -        { -            return $(actual-name) ; -        } -        else -        { -            # Add the scanner instance to the grist for name. -            local g = [ sequence.join -                [ utility.ungrist $(actual-name:G) ] $(scanner) : - ] ; -            local name = $(actual-name:G=$(g)) ; - -            if ! $(self.made.$(name)) -            { -                self.made.$(name) = true ; - -                DEPENDS $(name) : $(actual-name) ; - -                actualize-location $(name) ; - -                scanner.install $(scanner) : $(name) $(__name__) ; -            } -            return $(name) ; -        } -    } - -# private: (overridables) - -    # Sets up build actions for 'target'. Should call appropriate rules and set -    # target variables. -    # -    rule actualize-action ( target ) -    { -        errors.error "method should be defined in derived classes" ; -    } - -    # Sets up variables on 'target' which specify its location. -    # -    rule actualize-location ( target ) -    { -        errors.error "method should be defined in derived classes" ; -    } - -    # If the target is a generated one, returns the path where it will be -    # generated. Otherwise, returns an empty list. -    # -    rule path ( ) -    { -        errors.error "method should be defined in derived classes" ; -    } - -    # Returns the actual target name to be used in case when no scanner is -    # involved. -    # -    rule actual-name ( ) -    { -        errors.error "method should be defined in derived classes" ; -    } - -# implementation -    rule actualize-no-scanner ( ) -    { -        # In fact, we just need to merge virtual-target with -        # abstract-file-target as the latter is the only class derived from the -        # former. But that has been left for later. -	 -        errors.error "method should be defined in derived classes" ; -    } -} - - -# Target corresponding to a file. The exact mapping for file is not yet -# specified in this class. (TODO: Actually, the class name could be better...) -# -# May be a source file (when no action is specified) or a derived file -# (otherwise). -# -# The target's grist is a concatenation of its project's location, action -# properties (for derived targets) and, optionally, value identifying the main -# target. -# -class abstract-file-target : virtual-target -{ -    import project ; -    import regex ; -    import sequence ; -    import path ; -    import type ; -    import property-set ; -    import indirect ; - -    rule __init__ ( -         name     # Target's name. -         exact ?  # If non-empty, the name is exactly the name created file -                  # should have. Otherwise, the '__init__' method will add a -                  # suffix obtained from 'type' by calling -                  # 'type.generated-target-suffix'. -        : type ?  # Target's type. -        : project -        : action ? -    ) -    { -        virtual-target.__init__ $(name) : $(project) ; - -        self.type = $(type) ; -        self.action = $(action) ; -        if $(action) -        { -            $(action).add-targets $(__name__) ; - -            if $(self.type) && ! $(exact) -            { -                _adjust-name $(name) ; -            } -        } -    } - -    rule type ( ) -    { -        return $(self.type) ; -    } - -    # Sets the path. When generating target name, it will override any path -    # computation from properties. -    # -    rule set-path ( path ) -    { -        self.path = [ path.native $(path) ] ; -    } - -    # Returns the currently set action. -    # -    rule action ( ) -    { -        return $(self.action) ; -    } - -    # Sets/gets the 'root' flag. Target is root if it directly corresponds to -    # some variant of a main target. -    # -    rule root ( set ? ) -    { -        if $(set) -        { -            self.root = true ; -        } -        return $(self.root) ; -    } - -    # Gets or sets the subvariant which created this target. Subvariant is set -    # when target is brought into existance and is never changed after that. In -    # particular, if a target is shared by a subvariant, only the first is -    # stored. -    # -    rule creating-subvariant ( s ?  # If specified, specifies the value to set, -                                    # which should be a 'subvariant' class -                                    # instance. -                             ) -    { -        if $(s) && ! $(self.creating-subvariant) -        { -            self.creating-subvariant = $(s) ; -        } -        return $(self.creating-subvariant) ; -    } - -    rule actualize-action ( target ) -    { -        if $(self.action) -        { -            $(self.action).actualize ; -        } -    } - -    # Return a human-readable representation of this target. If this target has -    # an action, that is: -    # -    #    { <action-name>-<self.name>.<self.type> <action-sources>... } -    # -    # otherwise, it is: -    # -    #    { <self.name>.<self.type> } -    # -    rule str ( ) -    { -        local action = [ action ] ; -        local name-dot-type = [ sequence.join $(self.name) "." $(self.type) ] ; - -        if $(action) -        { -            local sources     = [ $(action).sources     ] ; -            local action-name = [ $(action).action-name ] ; - -            local ss ; -            for local s in $(sources) -            { -                ss += [ $(s).str ] ; -            } - -            return "{" $(action-name)-$(name-dot-type) $(ss) "}" ; -        } -        else -        { -            return "{" $(name-dot-type) "}" ; -        } -    } - -    rule less ( a ) -    { -        if [ str ] < [ $(a).str ] -        { -            return true ; -        } -    } - -    rule equal ( a ) -    { -        if [ str ] = [ $(a).str ] -        { -            return true ; -        } -    } - -# private: -    rule actual-name ( ) -    { -        if ! $(self.actual-name) -        { -            local grist = [ grist ] ; -            local basename = [ path.native $(self.name) ] ; -            self.actual-name = <$(grist)>$(basename) ; -        } -        return $(self.actual-name) ; -    } - -    # Helper to 'actual-name', above. Computes a unique prefix used to -    # distinguish this target from other targets with the same name creating -    # different files. -    # -    rule grist ( ) -    { -        # Depending on target, there may be different approaches to generating -        # unique prefixes. We generate prefixes in the form: -        # <one letter approach code> <the actual prefix> -        local path = [ path ] ; -        if $(path) -        { -            # The target will be generated to a known path. Just use the path -            # for identification, since path is as unique as it can get. -            return p$(path) ; -        } -        else -        { -            # File is either source, which will be searched for, or is not a -            # file at all. Use the location of project for distinguishing. -            local project-location = [ $(self.project).get location ] ; -            local location-grist = [ sequence.join [ regex.split -                $(project-location) "/" ] : "!" ] ; - -            if $(self.action) -            { -                local ps = [ $(self.action).properties ] ; -                local property-grist = [ $(ps).as-path ] ; -                # 'property-grist' can be empty when 'ps' is an empty property -                # set. -                if $(property-grist) -                { -                    location-grist = $(location-grist)/$(property-grist) ; -                } -            } - -            return l$(location-grist) ; -        } -    } - -    # Given the target name specified in constructor, returns the name which -    # should be really used, by looking at the <tag> properties. Tag properties -    # need to be specified as <tag>@rule-name. This makes Boost Build call the -    # specified rule with the target name, type and properties to get the new -    # name. If no <tag> property is specified or the rule specified by <tag> -    # returns nothing, returns the result of calling -    # virtual-target.add-prefix-and-suffix. -    # -    rule _adjust-name ( specified-name ) -    { -        local ps ; -        if $(self.action) -        { -            ps = [ $(self.action).properties ] ; -        } -        else -        { -            ps = [ property-set.empty ] ; -        } - -        # We add ourselves to the properties so that any tag rule can get more -        # direct information about the target than just that available through -        # the properties. This is useful in implementing name changes based on -        # the sources of the target. For example to make unique names of object -        # files based on the source file.  --grafik -        ps = [ property-set.create [ $(ps).raw ] <target>$(__name__) ] ; - -        local tag = [ $(ps).get <tag> ] ; - -        if $(tag) -        { -            local rule-name = [ MATCH ^@(.*) : $(tag) ] ; -            if $(rule-name) -            { -                if $(tag[2]) -                { -                    errors.error "<tag>@rulename is present but is not the only" -                        "<tag> feature" ; -                } - -                self.name = [ indirect.call $(rule-name) $(specified-name) -                    : $(self.type) : $(ps) ] ; -            } -            else -            { -                errors.error -                    "The value of the <tag> feature must be '@rule-name'" ; -            } -        } - -        # If there is no tag or the tag rule returned nothing. -        if ! $(tag) || ! $(self.name) -        { -            self.name = [ virtual-target.add-prefix-and-suffix $(specified-name) -                : $(self.type) : $(ps) ] ; -        } -    } - -    rule actualize-no-scanner ( ) -    { -        local name = [ actual-name ] ; - -        # Do anything only on the first invocation. -        if ! $(self.made.$(name)) -        { -            self.made.$(name) = true ; - -            if $(self.action) -            { -                # For non-derived target, we do not care if there are several -                # virtual targets that refer to the same name. One case when -                # this is unavoidable is when the file name is main.cpp and two -                # targets have types CPP (for compiling) and MOCCABLE_CPP (for -                # conversion to H via Qt tools). -                virtual-target.register-actual-name $(name) : $(__name__) ; -            } - -            for local i in $(self.dependencies) -            { -                DEPENDS $(name) : [ $(i).actualize ] ; -            } - -            actualize-location $(name) ; -            actualize-action $(name) ; -        } -        return $(name) ; -    } -} - - -# Appends the suffix appropriate to 'type/property-set' combination to the -# specified name and returns the result. -# -rule add-prefix-and-suffix ( specified-name : type ? : property-set ) -{ -    local suffix = [ type.generated-target-suffix $(type) : $(property-set) ] ; - -    # Handle suffixes for which no leading dot is desired. Those are specified -    # by enclosing them in <...>.  Needed by python so it can create "_d.so" -    # extensions, for example. -    if $(suffix:G) -    { -        suffix = [ utility.ungrist $(suffix) ] ; -    } -    else -    { -        suffix = .$(suffix) ; -    } - -    local prefix = [ type.generated-target-prefix $(type) : $(property-set) ] ; - -    if  [ MATCH ^($(prefix)) : $(specified-name) ] -    { -        prefix = ; -    } -    return $(prefix:E="")$(specified-name)$(suffix:E="") ; -} - - -# File targets with explicitly known location. -# -# The file path is determined as -#    * Value passed to the 'set-path' method, if any. -#    * For derived files, project's build dir, joined with components that -#      describe action properties. If free properties are not equal to the -#      project's reference properties an element with the name of the main -#      target is added. -#    * For source files, project's source dir. -# -# The file suffix is determined as: -#     * The value passed to the 'suffix' method, if any. -#     * The suffix corresponding to the target's type. -# -class file-target : abstract-file-target -{ -    import "class" : new ; -    import common ; -    import errors ; - -    rule __init__ ( -        name exact ? -        : type ?  # Optional type for this target. -        : project -        : action ? -        : path ? -    ) -    { -        abstract-file-target.__init__ $(name) $(exact) : $(type) : $(project) : -            $(action) ; - -        self.path = $(path) ; -    } - -    rule clone-with-different-type ( new-type ) -    { -        return [ new file-target $(self.name) exact : $(new-type) : -            $(self.project) : $(self.action) : $(self.path) ] ; -    } - -    rule actualize-location ( target ) -    { -        if $(self.action) -        { -            # This is a derived file. -            local path = [ path ] ; -            LOCATE on $(target) = $(path) ; - -            # Make sure the path exists. -            DEPENDS $(target) : $(path) ; -            common.MkDir $(path) ; - -            # It is possible that the target name includes a directory too, for -            # example when installing headers. Create that directory. -            if $(target:D) -            { -                local d = $(target:D) ; -                d = $(d:R=$(path)) ; -                DEPENDS $(target) : $(d) ; -                common.MkDir $(d) ; -            } - -            # For a real file target, we create a fake target depending on the -            # real target. This allows us to run -            # -            #    bjam hello.o -            # -            # without trying to guess the name of the real target. Note that the -            # target has no directory name and uses a special <e> grist. -            # -            # First, that means that "bjam hello.o" will build all known hello.o -            # targets. Second, the <e> grist makes sure this target will not be -            # confused with other targets, for example, if we have subdir 'test' -            # with target 'test' in it that includes a 'test.o' file, then the -            # target for directory will be just 'test' the target for test.o -            # will be <ptest/bin/gcc/debug>test.o and the target we create below -            # will be <e>test.o -            DEPENDS $(target:G=e) : $(target) ; -            # Allow bjam <path-to-file>/<file> to work. This will not catch all -            # possible ways to refer to the path (relative/absolute, extra ".", -            # various "..", but should help in obvious cases. -            DEPENDS $(target:G=e:R=$(path)) : $(target) ; -        } -        else -        { -            SEARCH on $(target) = [ path.native $(self.path) ] ; -        } -    } - -    # Returns the directory for this target. -    # -    rule path ( ) -    { -        if ! $(self.path) -        { -            if $(self.action) -            { -                local p = [ $(self.action).properties ] ; -                local path,relative-to-build-dir = [ $(p).target-path ] ; -                local path = $(path,relative-to-build-dir[1]) ; -                local relative-to-build-dir = $(path,relative-to-build-dir[2]) ; - -                if $(relative-to-build-dir) -                { -                    path = [ path.join [ $(self.project).build-dir ] $(path) ] ; -                } - -                self.path = [ path.native $(path) ] ; -            } -        } -        return $(self.path) ; -     } -} - - -class notfile-target : abstract-file-target -{ -    rule __init__ ( name : project : action ? ) -    { -        abstract-file-target.__init__ $(name) : : $(project) : $(action) ; -    } - -    # Returns nothing to indicate that the target's path is not known. -    # -    rule path ( ) -    { -        return ; -    } - -    rule actualize-location ( target ) -    { -        NOTFILE $(target) ; -        ALWAYS $(target) ; -        # TEMPORARY $(target) ; -        NOUPDATE $(target) ; -    } -} - - -# Class representing an action. Both 'targets' and 'sources' should list -# instances of 'virtual-target'. Action name should name a rule with this -# prototype: -#     rule action-name ( targets + : sources * : properties * ) -# Targets and sources are passed as actual Jam targets. The rule may not -# establish additional dependency relationships. -# -class action -{ -    import "class" ; -    import errors ; -    import type ; -    import toolset ; -    import property-set ; -    import indirect ; -    import path ; -    import set : difference ; - -    rule __init__ ( sources * : action-name + : property-set ? ) -    { -        self.sources = $(sources) ; - -        self.action-name = [ indirect.make-qualified $(action-name) ] ; - -        if ! $(property-set) -        { -            property-set = [ property-set.empty ] ; -        } - -        if ! [ class.is-instance $(property-set) ] -        { -            errors.error "Property set instance required" ; -        } - -        self.properties = $(property-set) ; -    } - -    rule add-targets ( targets * ) -    { -        self.targets += $(targets) ; -    } - -    rule replace-targets ( old-targets * : new-targets * ) -    { -        self.targets = [ set.difference $(self.targets) : $(old-targets) ] ; -        self.targets += $(new-targets) ; -    } - -    rule targets ( ) -    { -        return $(self.targets) ; -    } - -    rule sources ( ) -    { -        return $(self.sources) ; -    } - -    rule action-name ( ) -    { -        return $(self.action-name) ; -    } - -    rule properties ( ) -    { -        return $(self.properties) ; -    } - -    # Generates actual build instructions. -    # -    rule actualize ( ) -    { -        if ! $(self.actualized) -        { -            self.actualized = true ; - -            local ps = [ properties ] ; -            local properties = [ adjust-properties $(ps) ] ; - -            local actual-targets ; -            for local i in [ targets ] -            { -                actual-targets += [ $(i).actualize ] ; -            } - -            actualize-sources [ sources ] : $(properties) ; - -            DEPENDS $(actual-targets) : $(self.actual-sources) -                $(self.dependency-only-sources) ; -             -            # This works around a bug with -j and actions that -            # produce multiple target, where: -            # - dependency on the first output is found, and -            #   the action is started -            # - dependency on the second output is found, and -            #   bjam noticed that command is already running -            # - instead of waiting for the command, dependents -            #   of the second targets are immediately updated. -            if $(actual-targets[2]) -            {                 -                INCLUDES $(actual-targets) : $(actual-targets) ; -            } -             -            # Action name can include additional argument to rule, which should -            # not be passed to 'set-target-variables' -            toolset.set-target-variables -                [ indirect.get-rule $(self.action-name[1]) ] $(actual-targets) -                : $(properties) ; - -            # Reflect ourselves in a variable for the target. This allows -            # looking up additional info for the action given the raw target. -            # For example to debug or output action information from action -            # rules. -            .action on $(actual-targets) = $(__name__) ; - -            indirect.call $(self.action-name) $(actual-targets) -                : $(self.actual-sources) : [ $(properties).raw ] ; - -            # Since we set up the creating action here, we set up the action for -            # cleaning up as well. -            common.Clean clean-all : $(actual-targets) ; -        } -    } - -    # Helper for 'actualize-sources'. For each passed source, actualizes it with -    # the appropriate scanner. Returns the actualized virtual targets. -    # -    rule actualize-source-type ( sources * : property-set ) -    { -        local result = ; -        for local i in $(sources) -        { -            local scanner ; -            if [ $(i).type ] -            { -                scanner = [ type.get-scanner [ $(i).type ] : $(property-set) ] ; -            } -            result += [ $(i).actualize $(scanner) ] ; -        } -        return $(result) ; -    } - -    # Creates actual Jam targets for sources. Initializes the following member -    # variables: -    #   'self.actual-sources'          -- sources passed to the updating action. -    #   'self.dependency-only-sources' -- sources marked as dependencies, but -    #                                     are not used otherwise. -    # -    # New values will be *appended* to the variables. They may be non-empty if -    # caller wants it. -    # -    rule actualize-sources ( sources * : property-set ) -    { -        local dependencies = [ $(self.properties).get <dependency> ] ; - -        self.dependency-only-sources += -            [ actualize-source-type $(dependencies) : $(property-set) ] ; -        self.actual-sources += -            [ actualize-source-type $(sources) : $(property-set) ] ; - -        # This is used to help bjam find dependencies in generated headers and -        # other main targets, e.g. in: -        # -        #   make a.h : ....... ; -        #   exe hello : hello.cpp : <implicit-dependency>a.h ; -        # -        # For bjam to find the dependency the generated target must be -        # actualized (i.e. have its Jam target constructed). In the above case, -        # if we are building just hello ("bjam hello"), 'a.h' will not be -        # actualized unless we do it here. -        local implicit = [ $(self.properties).get <implicit-dependency> ] ; -        for local i in $(implicit) -        { -            $(i:G=).actualize ; -        } -    } - -    # Determines real properties when trying to build with 'properties'. This is -    # the last chance to fix properties, for example to adjust includes to get -    # generated headers correctly. Default implementation simply returns its -    # argument. -    # -    rule adjust-properties ( property-set ) -    { -        return $(property-set) ; -    } -} - - -# Action class which does nothing --- it produces the targets with specific -# properties out of nowhere. It is needed to distinguish virtual targets with -# different properties that are known to exist and have no actions which create -# them. -# -class null-action : action -{ -    rule __init__ ( property-set ? ) -    { -        action.__init__ : .no-action : $(property-set) ; -    } - -    rule actualize ( ) -    { -        if ! $(self.actualized) -        { -            self.actualized = true ; -            for local i in [ targets ] -            { -                $(i).actualize ; -            } -        } -    } -} - - -# Class which acts exactly like 'action', except that its sources are not -# scanned for dependencies. -# -class non-scanning-action : action -{ -    rule __init__ ( sources * : action-name + : property-set ? ) -    { -        action.__init__ $(sources) : $(action-name) : $(property-set) ; -    } - -    rule actualize-source-type ( sources * : property-set ) -    { -        local result ; -        for local i in $(sources) -        { -            result += [ $(i).actualize ] ; -        } -        return $(result) ; -    } -} - - -# Creates a virtual target with an appropriate name and type from 'file'. If a -# target with that name in that project already exists, returns that already -# created target. -# -# FIXME: a more correct way would be to compute the path to the file, based on -# name and source location for the project, and use that path to determine if -# the target has already been created. This logic should be shared with how we -# usually find targets identified by a specific target id. It should also be -# updated to work correctly when the file is specified using both relative and -# absolute paths. -# -# TODO: passing a project with all virtual targets is starting to be annoying. -# -rule from-file ( file : file-loc : project ) -{ -    import type ;  # Had to do this here to break a circular dependency. - -    # Check whether we already created a target corresponding to this file. -    local path = [ path.root [ path.root $(file) $(file-loc) ] [ path.pwd ] ] ; - -    if $(.files.$(path)) -    { -        return $(.files.$(path)) ; -    } -    else -    { -        local name = [ path.make $(file) ] ; -        local type = [ type.type $(file) ] ; -        local result ; - -        result = [ new file-target $(file) : $(type) : $(project) : : -            $(file-loc) ] ; - -        .files.$(path) = $(result) ; -        return $(result) ; -    } -} - - -# Registers a new virtual target. Checks if there is already a registered target -# with the same name, type, project and subvariant properties as well as the -# same sources and equal action. If such target is found it is returned and a -# new 'target' is not registered. Otherwise, 'target' is registered and -# returned. -# -rule register ( target ) -{ -    local signature = [ sequence.join -        [ $(target).path ] [ $(target).name ] : - ] ; - -    local result ; -    for local t in $(.cache.$(signature)) -    { -        local a1 = [ $(t).action ] ; -        local a2 = [ $(target).action ] ; - -        if ! $(result) -        { -            if ! $(a1) && ! $(a2) -            { -                result = $(t) ; -            } -            else -            { -                if $(a1) && $(a2) && -                    ( [ $(a1).action-name ] = [ $(a2).action-name ] ) && -                    ( [ $(a1).sources     ] = [ $(a2).sources     ] ) -                { -                    local ps1 = [ $(a1).properties ] ; -                    local ps2 = [ $(a2).properties ] ; -                    local p1 = [ $(ps1).base ] [ $(ps1).free ] [ set.difference -                        [ $(ps1).dependency ] : [ $(ps1).incidental ] ] ; -                    local p2 = [ $(ps2).base ] [ $(ps2).free ] [ set.difference -                        [ $(ps2).dependency ] : [ $(ps2).incidental ] ] ; -                    if $(p1) = $(p2) -                    { -                        result = $(t) ; -                    } -                } -            } -        } -    } - -    if ! $(result) -    { -        .cache.$(signature) += $(target) ; -        result = $(target) ; -    } - -    .recent-targets += $(result) ; -    .all-targets += $(result) ; - -    return $(result) ; -} - - -# Each target returned by 'register' is added to the .recent-targets list, -# returned by this function. This allows us to find all virtual targets created -# when building a specific main target, even those constructed only as -# intermediate targets. -# -rule recent-targets ( ) -{ -    return $(.recent-targets) ; -} - - -rule clear-recent-targets ( ) -{ -    .recent-targets = ; -} - - -# Returns all virtual targets ever created. -# -rule all-targets ( ) -{ -    return $(.all-targets) ; -} - - -# Returns all targets from 'targets' with types equal to 'type' or derived from -# it. -# -rule select-by-type ( type : targets * ) -{ -    local result ; -    for local t in $(targets) -    { -        if [ type.is-subtype [ $(t).type ] $(type) ] -        { -            result += $(t) ; -        } -    } -    return $(result) ; -} - - -rule register-actual-name ( actual-name : virtual-target ) -{ -    if $(.actual.$(actual-name)) -    { -        local cs1 = [ $(.actual.$(actual-name)).creating-subvariant ] ; -        local cs2 = [ $(virtual-target).creating-subvariant ] ; -        local cmt1 = [ $(cs1).main-target ] ; -        local cmt2 = [ $(cs2).main-target ] ; - -        local action1 = [ $(.actual.$(actual-name)).action ] ; -        local action2 = [ $(virtual-target).action ] ; -        local properties-added ; -        local properties-removed ; -        if $(action1) && $(action2) -        { -            local p1 = [ $(action1).properties ] ; -            p1 = [ $(p1).raw ] ; -            local p2 = [ $(action2).properties ] ; -            p2 = [ $(p2).raw ] ; -            properties-removed = [ set.difference $(p1) : $(p2) ] ; -            properties-removed ?= "none" ; -            properties-added = [ set.difference $(p2) : $(p1) ] ; -            properties-added ?= "none" ; -        } -        errors.error "Duplicate name of actual target:" $(actual-name) -            : "previous virtual target" [ $(.actual.$(actual-name)).str ] -            : "created from"            [ $(cmt1).full-name ] -            : "another virtual target"  [ $(virtual-target).str ] -            : "created from"            [ $(cmt2).full-name ] -            : "added properties:"       $(properties-added) -            : "removed properties:"     $(properties-removed) ; -    } -    else -    { -        .actual.$(actual-name) = $(virtual-target) ; -    } -} - - -# Traverses the dependency graph of 'target' and return all targets that will be -# created before this one is created. If the root of some dependency graph is -# found during traversal, it is either included or not, depending on the -# 'include-roots' value. In either case traversal stops at root targets, i.e. -# root target sources are not traversed. -# -rule traverse ( target : include-roots ? : include-sources ? ) -{ -    local result ; -    if [ $(target).action ] -    { -        local action = [ $(target).action ] ; -        # This includes the 'target' as well. -        result += [ $(action).targets ] ; - -        for local t in [ $(action).sources ] -        { -            if ! [ $(t).root ] -            { -                result += [ traverse $(t) : $(include-roots) : $(include-sources) ] ; -            } -            else if $(include-roots) -            { -                result += $(t) ; -            } -        } -    } -    else if $(include-sources) -    { -        result = $(target) ; -    } -    return $(result) ; -} - - -# Takes an 'action' instance and creates a new instance of it and all targets -# produced by the action. The rule-name and properties are set to -# 'new-rule-name' and 'new-properties', if those are specified. Returns the -# cloned action. -# -rule clone-action ( action : new-project : new-action-name ? : new-properties ? ) -{ -    if ! $(new-action-name) -    { -        new-action-name = [ $(action).action-name ] ; -    } -    if ! $(new-properties) -    { -        new-properties = [ $(action).properties ] ; -    } - -    local action-class = [ modules.peek $(action) : __class__ ] ; -    local cloned-action = [ class.new $(action-class) -        [ $(action).sources ] : $(new-action-name) : $(new-properties) ] ; - -    local cloned-targets ; -    for local target in [ $(action).targets ] -    { -        local n = [ $(target).name ] ; -        # Do not modify produced target names. -        local cloned-target = [ class.new file-target $(n) exact : -            [ $(target).type ] : $(new-project) : $(cloned-action) ] ; -        local d = [ $(target).dependencies ] ; -        if $(d) -        { -            $(cloned-target).depends $(d) ; -        } -        $(cloned-target).root [ $(target).root ] ; -        $(cloned-target).creating-subvariant [ $(target).creating-subvariant ] ; - -        cloned-targets += $(cloned-target) ; -    } - -    return $(cloned-action) ; -} - - -class subvariant -{ -    import sequence ; -    import type ; - -    rule __init__ ( main-target       # The instance of main-target class. -        : property-set                # Properties requested for this target. -        : sources * -        : build-properties            # Actually used properties. -        : sources-usage-requirements  # Properties propagated from sources. -        : created-targets * )         # Top-level created targets. -    { -        self.main-target = $(main-target) ; -        self.properties = $(property-set) ; -        self.sources = $(sources) ; -        self.build-properties = $(build-properties) ; -        self.sources-usage-requirements = $(sources-usage-requirements) ; -        self.created-targets = $(created-targets) ; - -        # Pre-compose a list of other dependency graphs this one depends on. -        local deps = [ $(build-properties).get <implicit-dependency> ] ; -        for local d in $(deps) -        { -            self.other-dg += [ $(d:G=).creating-subvariant ] ; -        } - -        self.other-dg = [ sequence.unique $(self.other-dg) ] ; -    } - -    rule main-target ( ) -    { -        return $(self.main-target) ; -    } - -    rule created-targets ( ) -    { -        return $(self.created-targets) ; -    } - -    rule requested-properties ( ) -    { -        return $(self.properties) ; -    } - -    rule build-properties ( ) -    { -        return $(self.build-properties) ; -    } - -    rule sources-usage-requirements ( ) -    { -        return $(self.sources-usage-requirements) ; -    } - -    rule set-usage-requirements ( usage-requirements ) -    { -        self.usage-requirements = $(usage-requirements) ; -    } - -    rule usage-requirements ( ) -    { -        return $(self.usage-requirements) ; -    } - -    # Returns all targets referenced by this subvariant, either directly or -    # indirectly, and either as sources, or as dependency properties. Targets -    # referred to using the dependency property are returned as properties, not -    # targets. -    # -    rule all-referenced-targets ( theset ) -    { -        # Find directly referenced targets. -        local deps = [ $(self.build-properties).dependency ] ; -        local all-targets = $(self.sources) $(deps) ; - -        # Find other subvariants. -        local r ; -        for local t in $(all-targets) -        { -            if ! [ $(theset).contains $(t) ] -            { -                $(theset).add $(t) ; -                r += [ $(t:G=).creating-subvariant ] ; -            }             -        } -        r = [ sequence.unique $(r) ] ; -        for local s in $(r) -        { -            if $(s) != $(__name__) -            { -                $(s).all-referenced-targets $(theset) ; -            } -        } -    } - -    # Returns the properties specifying implicit include paths to generated -    # headers. This traverses all targets in this subvariant and subvariants -    # referred by <implcit-dependecy> properties. For all targets of type -    # 'target-type' (or for all targets, if 'target-type' is not specified), the -    # result will contain <$(feature)>path-to-that-target. -    # -    rule implicit-includes ( feature : target-type ? ) -    { -        local key = ii$(feature)-$(target-type:E="") ; -        if ! $($(key))-is-not-empty -        { -            local target-paths = [ all-target-directories $(target-type) ] ; -            target-paths = [ sequence.unique $(target-paths) ] ; -            local result = $(target-paths:G=$(feature)) ; -            if ! $(result) -            { -                result = "" ; -            } -            $(key) = $(result) ; -        } -        if $($(key)) = "" -        { -            return ; -        } -        else -        { -            return $($(key)) ; -        } -    } - -    rule all-target-directories ( target-type ? ) -    { -        if ! $(self.target-directories) -        { -            compute-target-directories $(target-type) ; -        } -        return $(self.target-directories) ; -    } - -    rule compute-target-directories ( target-type ? ) -    { -        local result ; -        for local t in $(self.created-targets) -        { -            # Skip targets of the wrong type. -            if ! $(target-type) || -                [ type.is-derived [ $(t).type ] $(target-type) ] -            { -                result = [ sequence.merge $(result) : [ $(t).path ] ] ; -            } -        } -        for local d in $(self.other-dg) -        { -            result += [ $(d).all-target-directories $(target-type) ] ; -        } -        self.target-directories = $(result) ; -    } -} diff --git a/jam-files/boost-build/build/virtual_target.py b/jam-files/boost-build/build/virtual_target.py deleted file mode 100644 index 51dff037..00000000 --- a/jam-files/boost-build/build/virtual_target.py +++ /dev/null @@ -1,1118 +0,0 @@ -# Status: ported. -# Base revision: 64488. -#  -#  Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and -#  distribute this software is granted provided this copyright notice appears in -#  all copies. This software is provided "as is" without express or implied -#  warranty, and with no claim as to its suitability for any purpose. - -#  Implements virtual targets, which correspond to actual files created during -#  build, but are not yet targets in Jam sense. They are needed, for example, -#  when searching for possible transormation sequences, when it's not known -#  if particular target should be created at all. -# -# -#                       +--------------------------+ -#                       | VirtualTarget           | -#                       +==========================+ -#                       | actualize                | -#                       +--------------------------+ -#                       | actualize_action() = 0   | -#                       | actualize_location() = 0 | -#                       +----------------+---------+ -#                                        | -#                                        ^ -#                                       / \ -#                                      +-+-+ -#                                        | -#    +---------------------+     +-------+--------------+ -#    | Action              |     | AbstractFileTarget   | -#    +=====================|   * +======================+ -#    | action_name         |  +--+ action               | -#    | properties          |  |  +----------------------+ -#    +---------------------+--+  | actualize_action()   | -#    | actualize()         |0..1 +-----------+----------+ -#    | path()              |                 | -#    | adjust_properties() | sources         | -#    | actualize_sources() | targets         | -#    +------+--------------+                 ^ -#           |                               / \ -#           ^                              +-+-+ -#          / \                               | -#         +-+-+                +-------------+-------------+ -#           |                  |                           | -#           |           +------+---------------+  +--------+-------------+ -#           |           | FileTarget           |  | SearchedLibTarget    | -#           |           +======================+  +======================+ -#           |           | actualize-location() |  | actualize-location() | -#           |           +----------------------+  +----------------------+ -#           | -#         +-+------------------------------+ -#         |                                | -#    +----+----------------+     +---------+-----------+ -#    | CompileAction       |     | LinkAction          | -#    +=====================+     +=====================+ -#    | adjust_properties() |     | adjust_properties() | -#    +---------------------+     | actualize_sources() | -#                                +---------------------+ -# -# The 'CompileAction' and 'LinkAction' classes are defined not here, -# but in builtin.jam modules. They are shown in the diagram to give -# the big picture. - -import bjam - -import re -import os.path -import string -import types - -from b2.util import path, utility, set -from b2.util.utility import add_grist, get_grist, ungrist, replace_grist, get_value -from b2.util.sequence import unique -from b2.tools import common -from b2.exceptions import * -import b2.build.type -import b2.build.property_set as property_set - -import b2.build.property as property - -from b2.manager import get_manager -from b2.util import bjam_signature - -__re_starts_with_at = re.compile ('^@(.*)') - -class VirtualTargetRegistry: -    def __init__ (self, manager): -        self.manager_ = manager -         -        # A cache for FileTargets -        self.files_ = {} - -        # A cache for targets. -        self.cache_ = {} - -        # A map of actual names to virtual targets. -        # Used to make sure we don't associate same -        # actual target to two virtual targets. -        self.actual_ = {} - -        self.recent_targets_ = [] -         -        # All targets ever registed -        self.all_targets_ = [] - -        self.next_id_ = 0 -         -    def register (self, target): -        """ Registers a new virtual target. Checks if there's already registered target, with the same -            name, type, project and subvariant properties, and also with the same sources -            and equal action. If such target is found it is retured and 'target' is not registered. -            Otherwise, 'target' is registered and returned. -        """ -        if target.path(): -            signature = target.path() + "-" + target.name() -        else: -            signature = "-" + target.name() - -        result = None -        if not self.cache_.has_key (signature): -            self.cache_ [signature] = [] - -        for t in self.cache_ [signature]: -            a1 = t.action () -            a2 = target.action () - -            # TODO: why are we checking for not result? -            if not result: -                if not a1 and not a2: -                    result = t -                else: -                    if a1 and a2 and a1.action_name () == a2.action_name () and a1.sources () == a2.sources (): -                        ps1 = a1.properties () -                        ps2 = a2.properties () -                        p1 = ps1.base () + ps1.free () +\ -                            b2.util.set.difference(ps1.dependency(), ps1.incidental()) -                        p2 = ps2.base () + ps2.free () +\ -                            b2.util.set.difference(ps2.dependency(), ps2.incidental()) -                        if p1 == p2: -                            result = t -         -        if not result: -            self.cache_ [signature].append (target) -            result = target - -        # TODO: Don't append if we found pre-existing target? -        self.recent_targets_.append(result) -        self.all_targets_.append(result) -     -        return result - -    def from_file (self, file, file_location, project): -        """ Creates a virtual target with appropriate name and type from 'file'. -            If a target with that name in that project was already created, returns that already -            created target. -            TODO: more correct way would be to compute path to the file, based on name and source location -            for the project, and use that path to determine if the target was already created. -            TODO: passing project with all virtual targets starts to be annoying. -        """ -        # Check if we've created a target corresponding to this file. -        path = os.path.join(os.getcwd(), file_location, file) -        path = os.path.normpath(path) - -        if self.files_.has_key (path): -            return self.files_ [path] - -        file_type = b2.build.type.type (file) - -        result = FileTarget (file, file_type, project, -                             None, file_location)        -        self.files_ [path] = result -                 -        return result - -    def recent_targets(self): -        """Each target returned by 'register' is added to a list of -        'recent-target', returned by this function. So, this allows -        us to find all targets created when building a given main -        target, even if the target.""" - -        return self.recent_targets_ - -    def clear_recent_targets(self): -        self.recent_targets_ = [] - -    def all_targets(self): -        # Returns all virtual targets ever created -        return self.all_targets_ - -    # Returns all targets from 'targets' with types -    # equal to 'type' or derived from it. -    def select_by_type(self, type, targets): -        return [t for t in targets if b2.build.type.is_sybtype(t.type(), type)] - -    def register_actual_name (self, actual_name, virtual_target): -        if self.actual_.has_key (actual_name): -            cs1 = self.actual_ [actual_name].creating_subvariant () -            cs2 = virtual_target.creating_subvariant () -            cmt1 = cs1.main_target () -            cmt2 = cs2.main_target ()             -             -            action1 = self.actual_ [actual_name].action () -            action2 = virtual_target.action () -             -            properties_added = [] -            properties_removed = [] -            if action1 and action2: -                p1 = action1.properties () -                p1 = p1.raw () -                p2 = action2.properties () -                p2 = p2.raw () -                 -                properties_removed = set.difference (p1, p2) -                if not properties_removed: properties_removed = "none" - -                properties_added = set.difference (p2, p1) -                if not properties_added: properties_added = "none" - -            # FIXME: Revive printing of real location. -            get_manager().errors()( -                "Duplicate name of actual target: '%s'\n"  -                "previous virtual target '%s'\n" -                "created from '%s'\n" -                "another virtual target '%s'\n" -                "created from '%s'\n" -                "added properties: '%s'\n" -                "removed properties: '%s'\n" -                % (actual_name, -                   self.actual_ [actual_name], "loc", #cmt1.location (), -                   virtual_target,  -                   "loc", #cmt2.location (), -                   properties_added, properties_removed)) - -        else: -            self.actual_ [actual_name] = virtual_target -     - -    def add_suffix (self, specified_name, file_type, prop_set): -        """ Appends the suffix appropriate to 'type/property_set' combination -            to the specified name and returns the result. -        """ -        suffix = b2.build.type.generated_target_suffix (file_type, prop_set) - -        if suffix: -            return specified_name + '.' + suffix - -        else: -            return specified_name -     -class VirtualTarget: -    """ Potential target. It can be converted into jam target and used in -        building, if needed. However, it can be also dropped, which allows -        to search for different transformation and select only one. -        name:    name of this target. -        project: project to which this target belongs. -    """ -    def __init__ (self, name, project): -        self.name_ = name -        self.project_ = project -        self.dependencies_ = [] -        self.always_ = False -         -        # Caches if dapendencies for scanners have already been set. -        self.made_ = {} - -    def manager(self): -        return self.project_.manager() - -    def virtual_targets(self): -        return self.manager().virtual_targets() - -    def name (self): -        """ Name of this target. -        """ -        return self.name_ - -    def project (self): -        """ Project of this target. -        """ -        return self.project_ - -    def depends (self, d): -        """ Adds additional instances of 'VirtualTarget' that this -            one depends on. -        """ -        self.dependencies_ = unique (self.dependencies_ + d).sort () - -    def dependencies (self): -        return self.dependencies_ - -    def always(self): -        self.always_ = True - -    def actualize (self, scanner = None): -        """ Generates all the actual targets and sets up build actions for -            this target. -             -            If 'scanner' is specified, creates an additional target -            with the same location as actual target, which will depend on the -            actual target and be associated with 'scanner'. That additional -            target is returned. See the docs (#dependency_scanning) for rationale. -            Target must correspond to a file if 'scanner' is specified. -             -            If scanner is not specified, then actual target is returned. -        """ -        actual_name = self.actualize_no_scanner () - -        if self.always_: -            bjam.call("ALWAYS", actual_name) - -        if not scanner: -            return actual_name - -        else: -            # Add the scanner instance to the grist for name. -            g = '-'.join ([ungrist(get_grist(actual_name)), str(id(scanner))]) - -            name = replace_grist (actual_name, '<' + g + '>') - -            if not self.made_.has_key (name): -                self.made_ [name] = True - -                self.project_.manager ().engine ().add_dependency (name, actual_name) - -                self.actualize_location (name) - -                self.project_.manager ().scanners ().install (scanner, name, str (self)) - -            return name - -# private: (overridables) - -    def actualize_action (self, target): -        """ Sets up build actions for 'target'. Should call appropriate rules -            and set target variables. -        """ -        raise BaseException ("method should be defined in derived classes") - -    def actualize_location (self, target): -        """ Sets up variables on 'target' which specify its location. -        """ -        raise BaseException ("method should be defined in derived classes") -     -    def path (self): -        """ If the target is generated one, returns the path where it will be -            generated. Otherwise, returns empty list. -        """ -        raise BaseException ("method should be defined in derived classes") -     -    def actual_name (self): -        """ Return that actual target name that should be used -            (for the case where no scanner is involved) -        """ -        raise BaseException ("method should be defined in derived classes") - - -class AbstractFileTarget (VirtualTarget): -    """ Target which correspond to a file. The exact mapping for file -        is not yet specified in this class. (TODO: Actually, the class name -        could be better...) -         -        May be a source file (when no action is specified), or -        derived file (otherwise). -         -        The target's grist is concatenation of project's location, -        properties of action (for derived files), and, optionally, -        value identifying the main target. -         -        exact:  If non-empty, the name is exactly the name -                created file should have. Otherwise, the '__init__' -                method will add suffix obtained from 'type' by -                calling 'type.generated-target-suffix'. -                   -        type:   optional type of this target. -    """ -    def __init__ (self, name, type, project, action = None, exact=False): -        VirtualTarget.__init__ (self, name, project) -             -        self.type_ = type - -        self.action_ = action -        self.exact_ = exact -         -        if action: -            action.add_targets ([self]) -  -            if self.type and not exact: -                self.__adjust_name (name) - -         -        self.actual_name_ = None -        self.path_ = None -        self.intermediate_ = False -        self.creating_subvariant_ = None -         -        # True if this is a root target. -        self.root_ = False - -    def type (self): -        return self.type_ - -    def set_path (self, path): -        """ Sets the path. When generating target name, it will override any path -            computation from properties. -        """ -        self.path_ = path - -    def action (self): -        """ Returns the action. -        """ -        return self.action_ - -    def root (self, set = None): -        """ Sets/gets the 'root' flag. Target is root is it directly correspods to some -            variant of a main target. -        """ -        if set: -            self.root_ = True -        return self.root_ - -    def creating_subvariant (self, s = None): -        """ Gets or sets the subvariant which created this target. Subvariant -        is set when target is brought into existance, and is never changed -        after that. In particual, if target is shared by subvariant, only  -        the first is stored. -        s:  If specified, specified the value to set, -                which should be instance of 'subvariant' class. -        """ -        if s and not self.creating_subvariant (): -            if self.creating_subvariant (): -                raise BaseException ("Attempt to change 'dg'") - -            else: -                self.creating_subvariant_ = s - -        return self.creating_subvariant_ - -    def actualize_action (self, target): -        if self.action_: -            self.action_.actualize () - -    # Return a human-readable representation of this target -    # -    # If this target has an action, that's: -    # -    #    { <action-name>-<self.name>.<self.type> <action-sources>... } -    # -    # otherwise, it's: -    # -    #    { <self.name>.<self.type> } -    # -    def str(self): -        a = self.action() - -        name_dot_type = self.name_ + "." + self.type_ - -        if a: -            action_name = a.action_name() -            ss = [ s.str() for s in a.sources()] -                        -            return "{ %s-%s %s}" % (action_name, name_dot_type, str(ss)) -        else: -            return "{ " + name_dot_type + " }" -         -# private: - -    def actual_name (self): -        if not self.actual_name_: -            self.actual_name_ = '<' + self.grist() + '>' + self.name_ - -        return self.actual_name_ - -    def grist (self): -        """Helper to 'actual_name', above. Compute unique prefix used to distinguish -            this target from other targets with the same name which create different -            file. -        """ -        # Depending on target, there may be different approaches to generating -        # unique prefixes. We'll generate prefixes in the form  -        # <one letter approach code> <the actual prefix> -        path = self.path () -         -        if path: -            # The target will be generated to a known path. Just use the path -            # for identification, since path is as unique as it can get. -            return 'p' + path - -        else: -            # File is either source, which will be searched for, or is not a file at -            # all. Use the location of project for distinguishing. -            project_location = self.project_.get ('location') -            path_components = b2.util.path.split(project_location) -            location_grist = '!'.join (path_components) -             -            if self.action_: -                ps = self.action_.properties () -                property_grist = ps.as_path () -                # 'property_grist' can be empty when 'ps' is an empty -                # property set. -                if property_grist: -                    location_grist = location_grist + '/' + property_grist -                         -            return 'l' + location_grist - -    def __adjust_name(self, specified_name): -        """Given the target name specified in constructor, returns the -        name which should be really used, by looking at the <tag> properties. -        The tag properties come in two flavour: -          - <tag>value,  -          - <tag>@rule-name -        In the first case, value is just added to name -        In the second case, the specified rule is called with specified name, -        target type and properties and should return the new name. -        If not <tag> property is specified, or the rule specified by -        <tag> returns nothing, returns the result of calling  -        virtual-target.add-suffix""" - -        if self.action_: -            ps = self.action_.properties() -        else: -            ps = property_set.empty() - -        # FIXME: I'm not sure how this is used, need to check with -        # Rene to figure out how to implement -        #~ We add ourselves to the properties so that any tag rule can get -        #~ more direct information about the target than just that available -        #~ through the properties. This is useful in implementing -        #~ name changes based on the sources of the target. For example to -        #~ make unique names of object files based on the source file. -        #~ --grafik -        #ps = property_set.create(ps.raw() + ["<target>%s" % "XXXX"]) -        #ps = [ property-set.create [ $(ps).raw ] <target>$(__name__) ] ; -         -        tag = ps.get("<tag>") -         -        if tag: - -            if len(tag) > 1: -                get_manager().errors()( -                    """<tag>@rulename is present but is not the only <tag> feature""") - -            tag = tag[0] -            if callable(tag): -                self.name_ = tag(specified_name, self.type_, ps) -            else: -                if not tag[0] == '@': -                    self.manager_.errors()("""The value of the <tag> feature must be '@rule-nane'""") - -                exported_ps = b2.util.value_to_jam(ps, methods=True) -                self.name_ = b2.util.call_jam_function( -                    tag[1:], specified_name, self.type_, exported_ps) -                if self.name_: -                    self.name_ = self.name_[0] -         -        # If there's no tag or the tag rule returned nothing. -        if not tag or not self.name_: -            self.name_ = add_prefix_and_suffix(specified_name, self.type_, ps) - -    def actualize_no_scanner(self): -        name = self.actual_name() - -        # Do anything only on the first invocation -        if not self.made_: -            self.made_[name] = True - -            if self.action_:   -                # For non-derived target, we don't care if there -                # are several virtual targets that refer to the same name. -                # One case when this is unavoidable is when file name is -                # main.cpp and two targets have types CPP (for compiling) -                # and MOCCABLE_CPP (for convertion to H via Qt tools). -                self.virtual_targets().register_actual_name(name, self) - -            for i in self.dependencies_: -                self.manager_.engine().add_dependency(name, i.actualize()) - -            self.actualize_location(name) -            self.actualize_action(name) -             -        return name - -@bjam_signature((["specified_name"], ["type"], ["property_set"])) -def add_prefix_and_suffix(specified_name, type, property_set): -    """Appends the suffix appropriate to 'type/property-set' combination -    to the specified name and returns the result.""" - -    property_set = b2.util.jam_to_value_maybe(property_set) - -    suffix = "" -    if type: -        suffix = b2.build.type.generated_target_suffix(type, property_set) -     -    # Handle suffixes for which no leading dot is desired.  Those are -    # specified by enclosing them in <...>.  Needed by python so it -    # can create "_d.so" extensions, for example. -    if get_grist(suffix): -        suffix = ungrist(suffix) -    elif suffix: -        suffix = "." + suffix - -    prefix = "" -    if type: -        prefix = b2.build.type.generated_target_prefix(type, property_set) - -    if specified_name.startswith(prefix): -        prefix = "" - -    if not prefix: -        prefix = "" -    if not suffix: -        suffix = "" -    return prefix + specified_name + suffix - - -class FileTarget (AbstractFileTarget): -    """ File target with explicitly known location. - -        The file path is determined as -           - value passed to the 'set_path' method, if any -           - for derived files, project's build dir, joined with components -             that describe action's properties. If the free properties -             are not equal to the project's reference properties -             an element with name of main target is added. -           - for source files, project's source dir -         -        The file suffix is -            - the value passed to the 'suffix' method, if any, or -            - the suffix which correspond to the target's type. -    """ -    def __init__ (self, name, type, project, action = None, path=None, exact=False): -        AbstractFileTarget.__init__ (self, name, type, project, action, exact) - -        self.path_ = path - -    def __str__(self): -        if self.type_: -            return self.name_ + "." + self.type_ -        else: -            return self.name_ - -    def clone_with_different_type(self, new_type): -        return FileTarget(self.name_, new_type, self.project_, -                          self.action_, self.path_, exact=True) -         -    def actualize_location (self, target): -        engine = self.project_.manager_.engine () - -        if self.action_: -            # This is a derived file. -            path = self.path () -            engine.set_target_variable (target, 'LOCATE', path) - -            # Make sure the path exists. -            engine.add_dependency (target, path) -            common.mkdir(engine, path) - -            # It's possible that the target name includes a directory -            # too, for example when installing headers. Create that -            # directory. -            d = os.path.dirname(get_value(target)) -            if d: -                d = os.path.join(path, d) -                engine.add_dependency(target, d) -                common.mkdir(engine, d) - -            # For real file target, we create a fake target that -            # depends on the real target. This allows to run -            # -            #    bjam hello.o -            # -            # without trying to guess the name of the real target.             -            # Note the that target has no directory name, and a special -            # grist <e>. -            # -            # First, that means that "bjam hello.o" will build all -            # known hello.o targets. -            # Second, the <e> grist makes sure this target won't be confused -            # with other targets, for example, if we have subdir 'test' -            # with target 'test' in it that includes 'test.o' file, -            # then the target for directory will be just 'test' the target -            # for test.o will be <ptest/bin/gcc/debug>test.o and the target -            # we create below will be <e>test.o -            engine.add_dependency("<e>%s" % get_value(target), target) - -            # Allow bjam <path-to-file>/<file> to work.  This won't catch all -            # possible ways to refer to the path (relative/absolute, extra ".", -            # various "..", but should help in obvious cases. -            engine.add_dependency("<e>%s" % (os.path.join(path, get_value(target))), target) -             -        else: -            # This is a source file. -            engine.set_target_variable (target, 'SEARCH', self.project_.get ('source-location')) -     - -    def path (self): -        """ Returns the directory for this target. -        """ -        if not self.path_: -            if self.action_: -                p = self.action_.properties ()             -                (target_path, relative_to_build_dir) = p.target_path () -                 -                if relative_to_build_dir: -                    # Indicates that the path is relative to -                    # build dir. -                    target_path = os.path.join (self.project_.build_dir (), target_path) -                                 -                # Store the computed path, so that it's not recomputed -                # any more -                self.path_ = target_path - -        return self.path_ - - -class NotFileTarget(AbstractFileTarget): - -    def __init__(self, name, project, action): -        AbstractFileTarget.__init__(self, name, None, project, action) - -    def path(self): -        """Returns nothing, to indicate that target path is not known.""" -        return None - -    def actualize_location(self, target): -        bjam.call("NOTFILE", target) -        bjam.call("ALWAYS", target) -        bjam.call("NOUPDATE", target) - - -class Action: -    """ Class which represents an action. -        Both 'targets' and 'sources' should list instances of 'VirtualTarget'. -        Action name should name a rule with this prototype -            rule action_name ( targets + : sources * : properties * ) -        Targets and sources are passed as actual jam targets. The rule may -        not establish dependency relationship, but should do everything else. -    """ -    def __init__ (self, manager, sources, action_name, prop_set): -        assert(isinstance(prop_set, property_set.PropertySet)) -        assert type(sources) == types.ListType -        self.sources_ = sources -        self.action_name_ = action_name -        if not prop_set: -            prop_set = property_set.empty() -        self.properties_ = prop_set -        if not all(isinstance(v, VirtualTarget) for v in prop_set.get('implicit-dependency')): -            import pdb -            pdb.set_trace() - -        self.manager_ = manager -        self.engine_ = self.manager_.engine () -        self.targets_ = [] - -        # Indicates whether this has been actualized or not. -        self.actualized_ = False -         -        self.dependency_only_sources_ = [] -        self.actual_sources_ = [] -         -         -    def add_targets (self, targets): -        self.targets_ += targets - - -    def replace_targets (old_targets, new_targets): -        self.targets_ = [t for t in targets if not t in old_targets] + new_targets - -    def targets (self): -        return self.targets_ - -    def sources (self): -        return self.sources_ - -    def action_name (self): -        return self.action_name_ - -    def properties (self): -        return self.properties_ - -    def actualize (self): -        """ Generates actual build instructions. -        """ -        if self.actualized_: -            return -             -        self.actualized_ = True - -        ps = self.properties () -        properties = self.adjust_properties (ps) - - -        actual_targets = [] -         -        for i in self.targets (): -            actual_targets.append (i.actualize ()) - -        self.actualize_sources (self.sources (), properties) - -        self.engine_.add_dependency (actual_targets, self.actual_sources_ + self.dependency_only_sources_) - -        # This works around a bug with -j and actions that -        # produce multiple target, where: -        # - dependency on the first output is found, and -        #   the action is started -        # - dependency on the second output is found, and -        #   bjam noticed that command is already running -        # - instead of waiting for the command, dependents -        #   of the second targets are immediately updated. -        if len(actual_targets) > 1: -            bjam.call("INCLUDES", actual_targets, actual_targets) - -        # FIXME: check the comment below. Was self.action_name_ [1] -        # Action name can include additional argument to rule, which should not -        # be passed to 'set-target-variables' -        # FIXME: breaking circular dependency -        import toolset -        toolset.set_target_variables (self.manager_, self.action_name_, actual_targets, properties) -              -        engine = self.manager_.engine () - -        # FIXME: this is supposed to help --out-xml option, but we don't -        # implement that now, and anyway, we should handle it in Python, -        # not but putting variables on bjam-level targets. -        bjam.call("set-target-variable", actual_targets, ".action", repr(self)) -         -        self.manager_.engine ().set_update_action (self.action_name_, actual_targets, self.actual_sources_, -                                                   properties) -         -        # Since we set up creating action here, we also set up -        # action for cleaning up -        self.manager_.engine ().set_update_action ('common.Clean', 'clean-all', -                                                   actual_targets) - -        return actual_targets - -    def actualize_source_type (self, sources, prop_set): -        """ Helper for 'actualize_sources'. -            For each passed source, actualizes it with the appropriate scanner. -            Returns the actualized virtual targets. -        """ -        result = [] -        for i in sources: -            scanner = None - -# FIXME: what's this? -#            if isinstance (i, str): -#                i = self.manager_.get_object (i) -                 -            if i.type (): -                scanner = b2.build.type.get_scanner (i.type (), prop_set) - -            r = i.actualize (scanner) -            result.append (r) -         -        return result -     -    def actualize_sources (self, sources, prop_set): -        """ Creates actual jam targets for sources. Initializes two member -            variables: -            'self.actual_sources_' -- sources which are passed to updating action -            'self.dependency_only_sources_' -- sources which are made dependencies, but -            are not used otherwise. -             -            New values will be *appended* to the variables. They may be non-empty, -            if caller wants it. -        """ -        dependencies = self.properties_.get ('<dependency>') -                 -        self.dependency_only_sources_ += self.actualize_source_type (dependencies, prop_set) -        self.actual_sources_ += self.actualize_source_type (sources, prop_set) - -        # This is used to help bjam find dependencies in generated headers -        # in other main targets. -        # Say: -        # -        #   make a.h : ....... ; -        #   exe hello : hello.cpp : <implicit-dependency>a.h ; -        # -        # However, for bjam to find the dependency the generated target must -        # be actualized (i.e. have the jam target). In the above case, -        # if we're building just hello ("bjam hello"), 'a.h' won't be -        # actualized unless we do it here. -        implicit = self.properties_.get("<implicit-dependency>") - -        for i in implicit: -            i.actualize() - -    def adjust_properties (self, prop_set): -        """ Determines real properties when trying building with 'properties'. -            This is last chance to fix properties, for example to adjust includes -            to get generated headers correctly. Default implementation returns -            its argument. -        """ -        return prop_set - - -class NullAction (Action): -    """ Action class which does nothing --- it produces the targets with -        specific properties out of nowhere. It's needed to distinguish virtual -        targets with different properties that are known to exist, and have no  -        actions which create them. -    """ -    def __init__ (self, manager, prop_set): -        Action.__init__ (self, manager, [], None, prop_set) -         -    def actualize (self): -        if not self.actualized_: -            self.actualized_ = True - -            for i in self.targets (): -                i.actualize () - -class NonScanningAction(Action): -    """Class which acts exactly like 'action', except that the sources -    are not scanned for dependencies.""" - -    def __init__(self, sources, action_name, property_set): -        #FIXME: should the manager parameter of Action.__init__ -        #be removed? -- Steven Watanabe -        Action.__init__(self, b2.manager.get_manager(), sources, action_name, property_set) - -    def actualize_source_type(self, sources, property_set): - -        result = [] -        for s in sources: -            result.append(s.actualize()) -        return result - -def traverse (target, include_roots = False, include_sources = False): -    """ Traverses the dependency graph of 'target' and return all targets that will -        be created before this one is created. If root of some dependency graph is -        found during traversal, it's either included or not, dependencing of the -        value of 'include_roots'. In either case, sources of root are not traversed. -    """ -    result = [] -     -    if target.action (): -        action = target.action () -         -        # This includes 'target' as well -        result += action.targets () - -        for t in action.sources (): - -            # FIXME: -            # TODO: see comment in Manager.register_object () -            #if not isinstance (t, VirtualTarget): -            #    t = target.project_.manager_.get_object (t) -                 -            if not t.root (): -                result += traverse (t, include_roots, include_sources) - -            elif include_roots: -                result.append (t) - -    elif include_sources: -        result.append (target) - -    return result - -def clone_action (action, new_project, new_action_name, new_properties): -    """Takes an 'action' instances and creates new instance of it -    and all produced target. The rule-name and properties are set -    to 'new-rule-name' and 'new-properties', if those are specified. -    Returns the cloned action.""" - -    if not new_action_name: -        new_action_name = action.action_name() - -    if not new_properties: -        new_properties = action.properties() - -    cloned_action = action.__class__(action.manager_, action.sources(), new_action_name, -                                     new_properties) -                           -    cloned_targets = [] -    for target in action.targets(): - -        n = target.name() -        # Don't modify the name of the produced targets. Strip the directory f -        cloned_target = FileTarget(n, target.type(), new_project, -                                   cloned_action, exact=True) - -        d = target.dependencies() -        if d: -            cloned_target.depends(d) -        cloned_target.root(target.root()) -        cloned_target.creating_subvariant(target.creating_subvariant()) - -        cloned_targets.append(cloned_target) - -    return cloned_action - -class Subvariant: -     -    def __init__ (self, main_target, prop_set, sources, build_properties, sources_usage_requirements, created_targets): -        """  -        main_target:                 The instance of MainTarget class -        prop_set:                    Properties requested for this target -        sources: -        build_properties:            Actually used properties -        sources_usage_requirements:  Properties propagated from sources -        created_targets:             Top-level created targets -        """ -        self.main_target_ = main_target -        self.properties_ = prop_set -        self.sources_ = sources -        self.build_properties_ = build_properties -        self.sources_usage_requirements_ = sources_usage_requirements -        self.created_targets_ = created_targets - -        self.usage_requirements_ = None -         -        # Pre-compose the list of other dependency graphs, on which this one -        # depends -        deps = build_properties.get('<implicit-dependency>') -         -        self.other_dg_ = [] -        for d in deps: -            self.other_dg_.append(d.creating_subvariant ()) - -        self.other_dg_ = unique (self.other_dg_) - -        self.implicit_includes_cache_ = {} -        self.target_directories_ = None -                -    def main_target (self): -        return self.main_target_ -     -    def created_targets (self): -        return self.created_targets_ -     -    def requested_properties (self): -        return self.properties_ -     -    def build_properties (self): -        return self.build_properties_ -     -    def sources_usage_requirements (self): -        return self.sources_usage_requirements_ -     -    def set_usage_requirements (self, usage_requirements): -        self.usage_requirements_ = usage_requirements -     -    def usage_requirements (self): -        return self.usage_requirements_ - -    def all_referenced_targets(self, result): -        """Returns all targets referenced by this subvariant, -        either directly or indirectly, and either as sources, -        or as dependency properties. Targets referred with -        dependency property are returned a properties, not targets.""" - -        # Find directly referenced targets. -        deps = self.build_properties().dependency() -        all_targets = self.sources_ + deps -         -        # Find other subvariants. -        r = [] -        for e in all_targets: -            if not e in result: -                result.add(e) -                if isinstance(e, property.Property): -                    t = e.value() -                else: -                    t = e -                                     -                # FIXME: how can this be? -                cs = t.creating_subvariant() -                if cs: -                    r.append(cs) -        r = unique(r) -        for s in r: -            if s != self: -                s.all_referenced_targets(result) - - -    def implicit_includes (self, feature, target_type): -        """ Returns the properties which specify implicit include paths to -            generated headers. This traverses all targets in this subvariant, -            and subvariants referred by <implcit-dependecy>properties. -            For all targets which are of type 'target-type' (or for all targets, -            if 'target_type' is not specified), the result will contain -            <$(feature)>path-to-that-target. -        """ - -        if not target_type: -            key = feature -        else: -            key = feature + "-" + target_type - -             -        result = self.implicit_includes_cache_.get(key) -        if not result: -            target_paths = self.all_target_directories(target_type) -            target_paths = unique(target_paths) -            result = ["<%s>%s" % (feature, p) for p in target_paths] -            self.implicit_includes_cache_[key] = result - -        return result - -    def all_target_directories(self, target_type = None): -        # TODO: does not appear to use target_type in deciding -        # if we've computed this already. -        if not self.target_directories_: -            self.target_directories_ = self.compute_target_directories(target_type) -        return self.target_directories_ - -    def compute_target_directories(self, target_type=None): -        result = [] -        for t in self.created_targets(): -            if not target_type or b2.build.type.is_derived(t.type(), target_type): -                result.append(t.path()) - -        for d in self.other_dg_: -            result.extend(d.all_target_directories(target_type)) - -        result = unique(result) -        return result  | 
