summaryrefslogtreecommitdiff
path: root/jam-files/boost-build/build
diff options
context:
space:
mode:
authorPatrick Simianer <simianer@cl.uni-heidelberg.de>2012-11-05 15:29:46 +0100
committerPatrick Simianer <simianer@cl.uni-heidelberg.de>2012-11-05 15:29:46 +0100
commit6f29f345dc06c1a1033475eac1d1340781d1d603 (patch)
tree6fa4cdd7aefd7d54c9585c2c6274db61bb8b159a /jam-files/boost-build/build
parentb510da2e562c695c90d565eb295c749569c59be8 (diff)
parentc615c37501fa8576584a510a9d2bfe2fdd5bace7 (diff)
merge upstream/master
Diffstat (limited to 'jam-files/boost-build/build')
-rw-r--r--jam-files/boost-build/build/__init__.py0
-rw-r--r--jam-files/boost-build/build/ac.jam198
-rw-r--r--jam-files/boost-build/build/alias.jam73
-rw-r--r--jam-files/boost-build/build/alias.py63
-rw-r--r--jam-files/boost-build/build/build-request.jam322
-rw-r--r--jam-files/boost-build/build/build_request.py216
-rw-r--r--jam-files/boost-build/build/configure.jam237
-rw-r--r--jam-files/boost-build/build/configure.py164
-rw-r--r--jam-files/boost-build/build/engine.py172
-rw-r--r--jam-files/boost-build/build/errors.py127
-rw-r--r--jam-files/boost-build/build/feature.jam1335
-rw-r--r--jam-files/boost-build/build/feature.py905
-rw-r--r--jam-files/boost-build/build/generators.jam1408
-rw-r--r--jam-files/boost-build/build/generators.py1089
-rw-r--r--jam-files/boost-build/build/modifiers.jam232
-rw-r--r--jam-files/boost-build/build/project.ann.py996
-rw-r--r--jam-files/boost-build/build/project.jam1110
-rw-r--r--jam-files/boost-build/build/project.py1120
-rw-r--r--jam-files/boost-build/build/property-set.jam481
-rw-r--r--jam-files/boost-build/build/property.jam788
-rw-r--r--jam-files/boost-build/build/property.py593
-rw-r--r--jam-files/boost-build/build/property_set.py449
-rw-r--r--jam-files/boost-build/build/readme.txt13
-rw-r--r--jam-files/boost-build/build/scanner.jam153
-rw-r--r--jam-files/boost-build/build/scanner.py158
-rw-r--r--jam-files/boost-build/build/targets.jam1659
-rw-r--r--jam-files/boost-build/build/targets.py1401
-rw-r--r--jam-files/boost-build/build/toolset.jam502
-rw-r--r--jam-files/boost-build/build/toolset.py398
-rw-r--r--jam-files/boost-build/build/type.jam425
-rw-r--r--jam-files/boost-build/build/type.py313
-rw-r--r--jam-files/boost-build/build/version.jam161
-rw-r--r--jam-files/boost-build/build/virtual-target.jam1317
-rw-r--r--jam-files/boost-build/build/virtual_target.py1118
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