diff options
author | Patrick Simianer <simianer@cl.uni-heidelberg.de> | 2012-05-13 03:35:30 +0200 |
---|---|---|
committer | Patrick Simianer <simianer@cl.uni-heidelberg.de> | 2012-05-13 03:35:30 +0200 |
commit | 670a8f984fc6d8342180c59ae9e96b0b76f34d3d (patch) | |
tree | 9f2ce7eec1a77e56b3bb1ad0ad40f212d7a996b0 /jam-files/boost-build/build/build_request.py | |
parent | eb3ee28dc0eb1d3e5ed01ba0df843be329ae450d (diff) | |
parent | 2f64af3e06a518b93f7ca2c30a9d0aeb2c947031 (diff) |
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'jam-files/boost-build/build/build_request.py')
-rw-r--r-- | jam-files/boost-build/build/build_request.py | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/jam-files/boost-build/build/build_request.py b/jam-files/boost-build/build/build_request.py new file mode 100644 index 00000000..cc9f2400 --- /dev/null +++ b/jam-files/boost-build/build/build_request.py @@ -0,0 +1,216 @@ +# 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 ; +### } +### +### |