mirror of
https://github.com/boostorg/build.git
synced 2026-02-21 02:52:12 +00:00
bug fixes and more test cases
[SVN r12780]
This commit is contained in:
@@ -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__ ( )
|
||||
<toolset>gcc/<toolset-version>3.0.1/<stdlib>stlport/<variant>release/<inlining>off
|
||||
|
||||
: build-request.expand gcc-3.0.1/stlport debug release <inlining>off
|
||||
: $(test-space) ;
|
||||
|
||||
assert.result
|
||||
<include>a/b/c/<toolset>gcc/<toolset-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 <include>a/b/c gcc-3.0.1/stlport msvc/stlport msvc debug <include>x/y/z
|
||||
: $(test-space) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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/<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.
|
||||
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 <optimization>on
|
||||
;
|
||||
|
||||
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 ;
|
||||
|
||||
@@ -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__ ( )
|
||||
<toolset>gcc/<toolset-version>3.0.1/<stdlib>stlport/<variant>release/<inlining>off
|
||||
|
||||
: build-request.expand gcc-3.0.1/stlport debug release <inlining>off
|
||||
: $(test-space) ;
|
||||
|
||||
assert.result
|
||||
<include>a/b/c/<toolset>gcc/<toolset-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 <include>a/b/c gcc-3.0.1/stlport msvc/stlport msvc debug <include>x/y/z
|
||||
: $(test-space) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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/<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.
|
||||
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 <optimization>on
|
||||
;
|
||||
|
||||
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 ;
|
||||
|
||||
Reference in New Issue
Block a user