summaryrefslogtreecommitdiff
path: root/jam-files/boost-build/build/build_request.py
diff options
context:
space:
mode:
authorPatrick Simianer <simianer@cl.uni-heidelberg.de>2012-05-13 03:35:30 +0200
committerPatrick Simianer <simianer@cl.uni-heidelberg.de>2012-05-13 03:35:30 +0200
commitd94373453c69c6cfec952a0f7b427cacc78654d8 (patch)
tree43febdf719c103d19bd5d22d0be734e1574bc1e9 /jam-files/boost-build/build/build_request.py
parentcc9650b8b664d1f6836a0fa86a012401b51aafa0 (diff)
parenta65a80c5d5b6fc4cbd32280f07cae9be71551b70 (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.py216
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 ;
+### }
+###
+###