diff --git a/new/build-request.jam b/new/build-request.jam index ec9907e4a..89646579f 100644 --- a/new/build-request.jam +++ b/new/build-request.jam @@ -9,54 +9,37 @@ import regex ; import feature ; import numbers ; -# given a build request element of the form -# property1/property2/.../propertyN, return true if any of the -# properties has a composite feature. -local rule has-composite-feature ( feature-space element ) +# Transform property-set by applying f to each component property. +local rule apply-to-property-set ( f property-set ) { - # get the individual properties - local properties = regex.split element / ; - local result = ; - for local p in $(properties) - { - if composite in [ feature.attributes [ property.get-feature $(p) ] ] - { - result = $(p) ; - } - } - return result ; -} - -local rule expand-element ( f element ) -{ - local properties = [ regex.split $(element) / ] ; + local properties = [ feature.split $(property-set) ] ; return [ string.join [ $(f) $(properties) ] : / ] ; } -# expand the given build request by combining all elements which don't +# expand the given build request by combining all property-sets which don't # specify conflicting non-free features. -rule expand ( elements * : feature-space ? ) +rule expand ( property-sets * : feature-space ? ) { feature-space ?= feature ; # First make all features and subfeatures explicit - local expanded-elements = [ - sequence.transform expand-element $(feature-space).expand-subfeatures - : $(elements) ] ; + local expanded-property-sets = [ + sequence.transform apply-to-property-set $(feature-space).expand-subfeatures + : $(property-sets) ] ; - # Now combine all of the expanded elements - local product = [ x-product $(expanded-elements) : $(feature-space) ] ; + # Now combine all of the expanded property-sets + local product = [ x-product $(expanded-property-sets) : $(feature-space) ] ; return [ - sequence.transform expand-element $(feature-space).expand-composites + sequence.transform apply-to-property-set $(feature-space).expand-composites : $(product) ] ; } -local rule x-product-aux ( elements + : feature-space ) +local rule x-product-aux ( property-sets + : feature-space ) { local result ; - local p = [ regex.split $(elements[1]) / ] ; - local f = [ set.difference $(p:G) [ $(feature-space).free-features ] ] ; + local p = [ feature.split $(property-sets[1]) ] ; + local f = [ set.difference $(p:G) : [ $(feature-space).free-features ] ] ; local seen ; # No conflict with things used at a higher level? if ! [ set.intersection $(f) : $(x-product-used) ] @@ -66,28 +49,28 @@ local rule x-product-aux ( elements + : feature-space ) # don't mix in any conflicting features local x-product-used = $(x-product-used) $(f) ; - if $(elements[2]) + if $(property-sets[2]) { - local rest = [ x-product-aux $(elements[2-]) : $(feature-space) ] ; - result = $(elements[1])/$(rest) ; + local rest = [ x-product-aux $(property-sets[2-]) : $(feature-space) ] ; + result = $(property-sets[1])/$(rest) ; } - result ?= $(elements[1]) ; + result ?= $(property-sets[1]) ; } # If we didn't encounter a conflicting feature lower down, # don't recurse again. if ! [ set.intersection $(f) : $(x-product-seen) ] { - elements = ; + property-sets = ; } seen = $(x-product-seen) ; } - if $(elements[2]) + if $(property-sets[2]) { - result += [ x-product-aux $(elements[2-]) : $(feature-space) ] ; + result += [ x-product-aux $(property-sets[2-]) : $(feature-space) ] ; } # Note that we've seen these features so that higher levels will @@ -96,10 +79,10 @@ local rule x-product-aux ( elements + : feature-space ) return $(result) ; } -local rule x-product ( elements * : feature-space ) +local rule x-product ( property-sets * : feature-space ) { local x-product-seen x-product-used ; - return [ x-product-aux $(elements) : $(feature-space) ] ; + return [ x-product-aux $(property-sets) : $(feature-space) ] ; } local rule __test__ ( ) @@ -120,6 +103,7 @@ local rule __test__ ( ) feature variant : debug release : implicit composite ; feature inlining : on off ; + feature "include" : : free ; feature stdlib : native stlport : implicit ; @@ -144,6 +128,14 @@ local rule __test__ ( ) gcc/3.0.1/stlport/release/off : build-request.expand gcc-3.0.1/stlport debug release off + : $(test-space) ; + + assert.result + a/b/c/gcc/3.0.1/stlport/debug/x/y/z + a/b/c/msvc/stlport/debug/x/y/z + a/b/c/msvc/debug/x/y/z + + : build-request.expand a/b/c gcc-3.0.1/stlport msvc/stlport msvc debug x/y/z : $(test-space) ; } } diff --git a/new/feature.jam b/new/feature.jam index 02ee3a150..3510959a9 100644 --- a/new/feature.jam +++ b/new/feature.jam @@ -488,13 +488,13 @@ rule free-features ( ) return $(free.features) ; } -rule expand-composites ( property-set * ) +rule expand-composites ( properties * ) { - local explicit-features = $(property-set:G) ; + local explicit-features = $(properties:G) ; local result ; # now expand composite features - for local p in $(property-set) + for local p in $(properties) { for local x in [ expand-composite $(p) ] { @@ -508,11 +508,11 @@ rule expand-composites ( property-set * ) { error explicitly-specified values of non-free feature $(x:G) conflict : - values: [ get-values $(x:G) : $(property-set) ] ; + values: [ get-values $(x:G) : $(properties) ] ; } else if # if it's not the result of composite expansion - $(x) in $(property-set) + $(x) in $(properties) # or it is, but it doesn't match any explicitly-specified feature || ( ! $(x:G) in $(explicit-features) ) { @@ -529,17 +529,46 @@ rule expand-composites ( property-set * ) # 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 property-set cause any values of +# 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 ( property-set * ) +rule expand ( properties * ) { - local expanded = [ expand-subfeatures $(property-set) ] ; + local expanded = [ expand-subfeatures $(properties) ] ; return [ expand-composites $(expanded) ] ; } +# Given a property-set of the form +# v1/v2/...vN-1/vN/vN+1/...vM +# +# Returns +# v1 v2 ... vN-1 vN vN+1 ... 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. +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) ; +} + } class feature-space ; @@ -592,6 +621,22 @@ local rule __test__ ( ) : expand debug on ; + assert.result y/z b/c e/f + : split y/z/b/c/e/f + ; + + assert.result y/z b/c e/f + : split y\\z\\b\\c\\e\\f + ; + + assert.result a b c e/f/g i/j/k + : split a/b/c/e/f/g/i/j/k + ; + + assert.result a b c e/f/g i/j/k + : split a\\b\\c\\e\\f\\g\\i\\j\\k + ; + # test error checking try ; diff --git a/v2/build/build-request.jam b/v2/build/build-request.jam index ec9907e4a..89646579f 100644 --- a/v2/build/build-request.jam +++ b/v2/build/build-request.jam @@ -9,54 +9,37 @@ import regex ; import feature ; import numbers ; -# given a build request element of the form -# property1/property2/.../propertyN, return true if any of the -# properties has a composite feature. -local rule has-composite-feature ( feature-space element ) +# Transform property-set by applying f to each component property. +local rule apply-to-property-set ( f property-set ) { - # get the individual properties - local properties = regex.split element / ; - local result = ; - for local p in $(properties) - { - if composite in [ feature.attributes [ property.get-feature $(p) ] ] - { - result = $(p) ; - } - } - return result ; -} - -local rule expand-element ( f element ) -{ - local properties = [ regex.split $(element) / ] ; + local properties = [ feature.split $(property-set) ] ; return [ string.join [ $(f) $(properties) ] : / ] ; } -# expand the given build request by combining all elements which don't +# expand the given build request by combining all property-sets which don't # specify conflicting non-free features. -rule expand ( elements * : feature-space ? ) +rule expand ( property-sets * : feature-space ? ) { feature-space ?= feature ; # First make all features and subfeatures explicit - local expanded-elements = [ - sequence.transform expand-element $(feature-space).expand-subfeatures - : $(elements) ] ; + local expanded-property-sets = [ + sequence.transform apply-to-property-set $(feature-space).expand-subfeatures + : $(property-sets) ] ; - # Now combine all of the expanded elements - local product = [ x-product $(expanded-elements) : $(feature-space) ] ; + # Now combine all of the expanded property-sets + local product = [ x-product $(expanded-property-sets) : $(feature-space) ] ; return [ - sequence.transform expand-element $(feature-space).expand-composites + sequence.transform apply-to-property-set $(feature-space).expand-composites : $(product) ] ; } -local rule x-product-aux ( elements + : feature-space ) +local rule x-product-aux ( property-sets + : feature-space ) { local result ; - local p = [ regex.split $(elements[1]) / ] ; - local f = [ set.difference $(p:G) [ $(feature-space).free-features ] ] ; + local p = [ feature.split $(property-sets[1]) ] ; + local f = [ set.difference $(p:G) : [ $(feature-space).free-features ] ] ; local seen ; # No conflict with things used at a higher level? if ! [ set.intersection $(f) : $(x-product-used) ] @@ -66,28 +49,28 @@ local rule x-product-aux ( elements + : feature-space ) # don't mix in any conflicting features local x-product-used = $(x-product-used) $(f) ; - if $(elements[2]) + if $(property-sets[2]) { - local rest = [ x-product-aux $(elements[2-]) : $(feature-space) ] ; - result = $(elements[1])/$(rest) ; + local rest = [ x-product-aux $(property-sets[2-]) : $(feature-space) ] ; + result = $(property-sets[1])/$(rest) ; } - result ?= $(elements[1]) ; + result ?= $(property-sets[1]) ; } # If we didn't encounter a conflicting feature lower down, # don't recurse again. if ! [ set.intersection $(f) : $(x-product-seen) ] { - elements = ; + property-sets = ; } seen = $(x-product-seen) ; } - if $(elements[2]) + if $(property-sets[2]) { - result += [ x-product-aux $(elements[2-]) : $(feature-space) ] ; + result += [ x-product-aux $(property-sets[2-]) : $(feature-space) ] ; } # Note that we've seen these features so that higher levels will @@ -96,10 +79,10 @@ local rule x-product-aux ( elements + : feature-space ) return $(result) ; } -local rule x-product ( elements * : feature-space ) +local rule x-product ( property-sets * : feature-space ) { local x-product-seen x-product-used ; - return [ x-product-aux $(elements) : $(feature-space) ] ; + return [ x-product-aux $(property-sets) : $(feature-space) ] ; } local rule __test__ ( ) @@ -120,6 +103,7 @@ local rule __test__ ( ) feature variant : debug release : implicit composite ; feature inlining : on off ; + feature "include" : : free ; feature stdlib : native stlport : implicit ; @@ -144,6 +128,14 @@ local rule __test__ ( ) gcc/3.0.1/stlport/release/off : build-request.expand gcc-3.0.1/stlport debug release off + : $(test-space) ; + + assert.result + a/b/c/gcc/3.0.1/stlport/debug/x/y/z + a/b/c/msvc/stlport/debug/x/y/z + a/b/c/msvc/debug/x/y/z + + : build-request.expand a/b/c gcc-3.0.1/stlport msvc/stlport msvc debug x/y/z : $(test-space) ; } } diff --git a/v2/build/feature.jam b/v2/build/feature.jam index 02ee3a150..3510959a9 100644 --- a/v2/build/feature.jam +++ b/v2/build/feature.jam @@ -488,13 +488,13 @@ rule free-features ( ) return $(free.features) ; } -rule expand-composites ( property-set * ) +rule expand-composites ( properties * ) { - local explicit-features = $(property-set:G) ; + local explicit-features = $(properties:G) ; local result ; # now expand composite features - for local p in $(property-set) + for local p in $(properties) { for local x in [ expand-composite $(p) ] { @@ -508,11 +508,11 @@ rule expand-composites ( property-set * ) { error explicitly-specified values of non-free feature $(x:G) conflict : - values: [ get-values $(x:G) : $(property-set) ] ; + values: [ get-values $(x:G) : $(properties) ] ; } else if # if it's not the result of composite expansion - $(x) in $(property-set) + $(x) in $(properties) # or it is, but it doesn't match any explicitly-specified feature || ( ! $(x:G) in $(explicit-features) ) { @@ -529,17 +529,46 @@ rule expand-composites ( property-set * ) # 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 property-set cause any values of +# 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 ( property-set * ) +rule expand ( properties * ) { - local expanded = [ expand-subfeatures $(property-set) ] ; + local expanded = [ expand-subfeatures $(properties) ] ; return [ expand-composites $(expanded) ] ; } +# Given a property-set of the form +# v1/v2/...vN-1/vN/vN+1/...vM +# +# Returns +# v1 v2 ... vN-1 vN vN+1 ... 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. +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) ; +} + } class feature-space ; @@ -592,6 +621,22 @@ local rule __test__ ( ) : expand debug on ; + assert.result y/z b/c e/f + : split y/z/b/c/e/f + ; + + assert.result y/z b/c e/f + : split y\\z\\b\\c\\e\\f + ; + + assert.result a b c e/f/g i/j/k + : split a/b/c/e/f/g/i/j/k + ; + + assert.result a b c e/f/g i/j/k + : split a\\b\\c\\e\\f\\g\\i\\j\\k + ; + # test error checking try ;