2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-16 01:12:13 +00:00

Implemented subfeature defaults

feature.jam -

   * subfeatures acquired a subfeature attribute
   * improved error reporting
   * eliminated some unused code
   * simplified, improved commenting in, and fixed bugs in minimize

property.jam -

   * added missing "symmetric" label on toolset and variant in tests

msvc.jam -

   * version number is now defaulted, so I can have msvc-7.1 and
     msvc-6 configured, and simply type "bjam msvc".


[SVN r19675]
This commit is contained in:
Dave Abrahams
2003-08-18 04:39:43 +00:00
parent c712b4b272
commit 2a72b0dd7d
6 changed files with 442 additions and 132 deletions

View File

@@ -27,9 +27,12 @@ local rule setup ( )
dependency
propagated
link-incompatible
subfeature
;
.all-features = ;
.all-subfeatures = ; # non-subfeatures
.all-top-features = ; # non-subfeatures
.all-implicit-values = ;
}
setup ;
@@ -127,6 +130,14 @@ rule feature (
$(attributes).features += $(name) ;
.all-features += $(name) ;
if subfeature in $(attributes)
{
.all-subfeatures += $(name) ;
}
else
{
.all-top-features += $(name) ;
}
extend $(name) : $(values) ;
}
@@ -138,7 +149,7 @@ rule set-default ( feature : value )
if ! $(value) in $($(f).values)
{
errors.error "The specified default value, '$(value)' is invalid"
: "values values are " $($(f).values) ;
: "allowed values are: " $($(f).values) ;
}
$(f).default = $(value) ;
}
@@ -257,8 +268,9 @@ rule implied-subfeature (
if ! $(subfeature)
{
value-string ?= "" ;
error \"$(subvalue)\" is not a known subfeature value of
feature $(feature) ;
$(feature)$(value-string) ;
}
return $(subfeature) ;
@@ -331,6 +343,20 @@ local rule expand-subfeatures-aux (
}
}
# Add all the default feature values for non-optional subfeatures.
local ungristed-feature = [ utility.ungrist $(feature) ] ;
for local s in $($(feature).subfeatures)
{
local full-name = <$(ungristed-feature)-$(s)> ;
if ! optional in $($(full-name).attributes)
{
if ! $(full-name) in $(result:G)
{
result += $(full-name)$($(full-name).default) ;
}
}
}
return $(result) ;
}
@@ -451,12 +477,12 @@ rule extend-subfeature (
local subfeature-name = [ get-subfeature-name $(subfeature) $(value-string) ] ;
local f = [ utility.ungrist $(feature) ] ;
extend $(f)-$(subfeature-name) : $(subvalues) ;
# provide a way to get from the given feature or property and
# subfeature value to the subfeature name.
for local subvalue in $(subvalues)
{
$(feature)$(value-string:E="")<>$(subvalue).subfeature = $(subfeature-name) ;
}
$(feature)$(value-string:E="")<>$(subvalues).subfeature = $(subfeature-name) ;
}
# Can be called three ways:
@@ -535,7 +561,6 @@ rule subfeature (
validate-feature $(feature) ;
# Add grist to the subfeature name if a value-string was supplied
local value-prefix = $(value-string): ;
local subfeature-name = [ get-subfeature-name $(subfeature) $(value-string) ] ;
if $(subfeature-name) in $($(feature).subfeatures)
@@ -544,9 +569,13 @@ rule subfeature (
"specific to "$(value-string) ;
}
$(feature).subfeatures += $(subfeature-name) ;
extend-subfeature $(feature) $(value-string) : $(subfeature) : $(subvalues) ;
# First declare the subfeature as a feature in its own right
local f = [ utility.ungrist $(feature) ] ;
feature $(f)-$(subfeature-name) : $(subvalues) : $(attributes) ;
feature $(f)-$(subfeature-name) : $(subvalues) : $(attributes) subfeature ;
# Now make sure the subfeature values are known.
extend-subfeature $(feature) $(value-string) : $(subfeature) : $(subvalues) ;
}
# Set the components of the given composite property
@@ -662,6 +691,60 @@ rule expand-composites ( properties * )
return $(result) ;
}
# Return true iff f is an ordinary subfeature of the parent-property's
# feature, or if f is a subfeature fo the parent-property's feature
# specific to the parent-property's value
local rule is-subfeature ( 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 above, for subproperties
local rule is-subproperty ( parent-property p )
{
return [ is-subfeature $(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 $(parent-property) : $(features) ] ;
}
# as above, for subproperties
local rule select-subproperties ( parent-property : properties * )
{
return [ sequence.filter is-subproperty $(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
@@ -724,75 +807,89 @@ local rule move-subfeatures-to-the-end ( properties * )
# to the corresponding main property.
rule minimize ( properties * )
{
# remove properties implied by composite features
local x = $(properties) ;
local components ;
for local p in $(properties)
# Precondition checking
local implicits = [ set.intersection $(p:G=) : $(p:G) ] ;
if $(implicits)
{
if ! $(p:G)
{
error minimize requires an expanded property set, but \"$(p)\"
appears to be the value of an un-expanded implicit feature ;
}
components += $($(p).components:G) ;
x = [ set.difference $(x) : $($(p).components) ] ;
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 = $(x[1]) ;
local p fullp = $(x[1]) ;
local f = $(p:G) ;
local v = $(p:G=) ;
# eliminate features in implicit properties.
if implicit in [ attributes $(f) ]
{
p = $(p:G="") ;
p = $(v) ;
}
# eliminate properties which value is equal to feature's default
# and which are not symmetric
if $(p) = [ defaults $(f) ] && ! symmetric in [ attributes $(f) ]
# If the feature is not specified in any of composite ones,
# then removing it is OK, because adding defaults would bring that
# feature back --- there's 1-1 correspondence between minimized
# and full property set.
&& ! $(f:G) in $(components)
# locate all subproperties of $(x[1]) in the property set
local subproperties = [ select-subproperties $(fullp) : $(x) ] ;
if $(subproperties)
{
x = $(x[2-]) ;
# reconstitute the joined property name
local sorted = [ sequence.insertion-sort $(subproperties) ] ;
result += $(p)-$(sorted:G="":J=-) ;
x = [ set.difference $(x[2-]) : $(subproperties) ] ;
}
else
{
# locate all subproperties of f in the property set
local subproperties ;
local subfeatures = $($(f).subfeatures:G=) ;
if $(subfeatures)
{
local f_ = [ utility.ungrist $(f) ] ;
subfeatures = [ grist $(f_)-$(subfeatures) ] ;
subproperties = [ sequence.filter in-features subfeatures : $(x) ] ;
}
{
# 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.
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
# 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-]) ;
}
}
x = $(x[2-]) ;
}
}
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 can 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 there's ordinary feature F1 and composite feature
@@ -825,8 +922,21 @@ rule add-defaults ( properties * )
# 2. Free properties with ":" in values. We don't care, since free properties
# don't have defaults.
local xproperties = [ MATCH "^([^:]+)$" : $(properties) ] ;
local missing = [ set.difference $(.all-features) : $(xproperties:G) ] ;
return $(properties) [ defaults $(missing) ] ;
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
@@ -901,9 +1011,9 @@ local rule __test__ ( )
# use a fresh copy of the feature module
prepare-test feature-test-temp ;
# This is a local rule and so must be explicitly reimported into
# These are local rules and so must be explicitly reimported into
# the testing module
import feature : extend-feature validate-feature ;
import feature : extend-feature validate-feature select-subfeatures ;
import errors : try catch ;
import assert ;
@@ -912,7 +1022,7 @@ local rule __test__ ( )
feature define : : free ;
feature runtime-link : dynamic static : symmetric ;
feature optimization : on off ;
feature variant : debug release : implicit composite ;
feature variant : debug release : implicit composite symmetric ;
feature stdlib : native stlport ;
feature magic : : free ;
@@ -948,6 +1058,24 @@ local rule __test__ ( )
action <magic>17 : handle-magic2 ;
action <magic>17 : handle-magic3 ;
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 ;
@@ -960,6 +1088,10 @@ local rule __test__ ( )
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 a c e
: get-values x : <x>a <y>b <x>c <y>d <x>e ;
@@ -968,6 +1100,10 @@ local rule __test__ ( )
: expand gcc-3.0.1 debug <optimization>on
;
assert.result <fu>fu1 <fu-subfu2>q
: expand-subfeatures <fu>fu1
;
assert.result <variant>debug <define>_DEBUG <optimization>on
: expand debug <optimization>on
;
@@ -982,7 +1118,16 @@ local rule __test__ ( )
assert.result <runtime-link>static <define>foobar <optimization>on <toolset>gcc:<define>FOO
<toolset>gcc <variant>debug <stdlib>native <dummy>dummy1
: add-defaults <runtime-link>static <define>foobar <optimization>on <toolset>gcc:<define>FOO
: 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
: add-defaults <runtime-link>static <define>foobar
<optimization>on <toolset>gcc:<define>FOO <fu>fu1
;
set-default <runtime-link> : static ;
@@ -1099,14 +1244,14 @@ local rule __test__ ( )
implied-subfeature toolset 3.0.1 ;
}
catch \"3.0.1\" is not a known subfeature value of
feature <toolset> ;
<toolset> ;
try ;
{
implied-subfeature toolset not-a-version : gcc ;
}
catch \"not-a-version\" is not a known subfeature value of
feature <toolset> ;
<toolset>gcc ;
# leave a clean copy of the features module behind
finish-test feature-test-temp ;

View File

@@ -458,13 +458,13 @@ local rule __test__ ( )
feature.prepare-test property-test-temp ;
feature toolset : gcc : implicit ;
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 ;
feature variant : debug release : implicit composite symmetric ;
feature rtti : on off : link-incompatible ;
compose <variant>debug : <define>_DEBUG <optimization>off ;

View File

@@ -34,7 +34,11 @@ feature.subfeature toolset msvc : vendor
# versions of msvc are link-compatible
# link-incompatible
;
# Remember whether any versions have been initialized, allowing us to
# set the first initialized version as the default.
.initialized = ;
# Initialize the toolset for a specific version. As the result, path to
# compiler and, possible, program names are set up, and will be used when
# that version of compiler is requested. For example, you might have::
@@ -71,12 +75,17 @@ rule init (
if $(version)
{
feature.extend-subfeature toolset msvc : version : $(version) ;
feature.extend <toolset>msvc version : $(version) ;
if ! $(.initialized) # The first version initialized becomes the default.
{
feature.set-default toolset-msvc:version : $(version) ;
}
}
if $(vendor) && ( $(vendor) != intel )
{
feature.extend-subfeature toolset msvc : vendor : $(vendor) ;
feature.extend <toolset>msvc vendor : $(vendor) ;
}
# setup will be used iff a path has been specified. If setup is
@@ -135,6 +144,7 @@ rule init (
.CC = $(prefix)$(compiler) ;
.LD = $(prefix)$(linker) ;
}
.initialized = true ; # remember that we've initialized at least one version of msvc
}
.CC = cl ;

View File

@@ -27,9 +27,12 @@ local rule setup ( )
dependency
propagated
link-incompatible
subfeature
;
.all-features = ;
.all-subfeatures = ; # non-subfeatures
.all-top-features = ; # non-subfeatures
.all-implicit-values = ;
}
setup ;
@@ -127,6 +130,14 @@ rule feature (
$(attributes).features += $(name) ;
.all-features += $(name) ;
if subfeature in $(attributes)
{
.all-subfeatures += $(name) ;
}
else
{
.all-top-features += $(name) ;
}
extend $(name) : $(values) ;
}
@@ -138,7 +149,7 @@ rule set-default ( feature : value )
if ! $(value) in $($(f).values)
{
errors.error "The specified default value, '$(value)' is invalid"
: "values values are " $($(f).values) ;
: "allowed values are: " $($(f).values) ;
}
$(f).default = $(value) ;
}
@@ -257,8 +268,9 @@ rule implied-subfeature (
if ! $(subfeature)
{
value-string ?= "" ;
error \"$(subvalue)\" is not a known subfeature value of
feature $(feature) ;
$(feature)$(value-string) ;
}
return $(subfeature) ;
@@ -331,6 +343,20 @@ local rule expand-subfeatures-aux (
}
}
# Add all the default feature values for non-optional subfeatures.
local ungristed-feature = [ utility.ungrist $(feature) ] ;
for local s in $($(feature).subfeatures)
{
local full-name = <$(ungristed-feature)-$(s)> ;
if ! optional in $($(full-name).attributes)
{
if ! $(full-name) in $(result:G)
{
result += $(full-name)$($(full-name).default) ;
}
}
}
return $(result) ;
}
@@ -451,12 +477,12 @@ rule extend-subfeature (
local subfeature-name = [ get-subfeature-name $(subfeature) $(value-string) ] ;
local f = [ utility.ungrist $(feature) ] ;
extend $(f)-$(subfeature-name) : $(subvalues) ;
# provide a way to get from the given feature or property and
# subfeature value to the subfeature name.
for local subvalue in $(subvalues)
{
$(feature)$(value-string:E="")<>$(subvalue).subfeature = $(subfeature-name) ;
}
$(feature)$(value-string:E="")<>$(subvalues).subfeature = $(subfeature-name) ;
}
# Can be called three ways:
@@ -535,7 +561,6 @@ rule subfeature (
validate-feature $(feature) ;
# Add grist to the subfeature name if a value-string was supplied
local value-prefix = $(value-string): ;
local subfeature-name = [ get-subfeature-name $(subfeature) $(value-string) ] ;
if $(subfeature-name) in $($(feature).subfeatures)
@@ -544,9 +569,13 @@ rule subfeature (
"specific to "$(value-string) ;
}
$(feature).subfeatures += $(subfeature-name) ;
extend-subfeature $(feature) $(value-string) : $(subfeature) : $(subvalues) ;
# First declare the subfeature as a feature in its own right
local f = [ utility.ungrist $(feature) ] ;
feature $(f)-$(subfeature-name) : $(subvalues) : $(attributes) ;
feature $(f)-$(subfeature-name) : $(subvalues) : $(attributes) subfeature ;
# Now make sure the subfeature values are known.
extend-subfeature $(feature) $(value-string) : $(subfeature) : $(subvalues) ;
}
# Set the components of the given composite property
@@ -662,6 +691,60 @@ rule expand-composites ( properties * )
return $(result) ;
}
# Return true iff f is an ordinary subfeature of the parent-property's
# feature, or if f is a subfeature fo the parent-property's feature
# specific to the parent-property's value
local rule is-subfeature ( 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 above, for subproperties
local rule is-subproperty ( parent-property p )
{
return [ is-subfeature $(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 $(parent-property) : $(features) ] ;
}
# as above, for subproperties
local rule select-subproperties ( parent-property : properties * )
{
return [ sequence.filter is-subproperty $(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
@@ -724,75 +807,89 @@ local rule move-subfeatures-to-the-end ( properties * )
# to the corresponding main property.
rule minimize ( properties * )
{
# remove properties implied by composite features
local x = $(properties) ;
local components ;
for local p in $(properties)
# Precondition checking
local implicits = [ set.intersection $(p:G=) : $(p:G) ] ;
if $(implicits)
{
if ! $(p:G)
{
error minimize requires an expanded property set, but \"$(p)\"
appears to be the value of an un-expanded implicit feature ;
}
components += $($(p).components:G) ;
x = [ set.difference $(x) : $($(p).components) ] ;
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 = $(x[1]) ;
local p fullp = $(x[1]) ;
local f = $(p:G) ;
local v = $(p:G=) ;
# eliminate features in implicit properties.
if implicit in [ attributes $(f) ]
{
p = $(p:G="") ;
p = $(v) ;
}
# eliminate properties which value is equal to feature's default
# and which are not symmetric
if $(p) = [ defaults $(f) ] && ! symmetric in [ attributes $(f) ]
# If the feature is not specified in any of composite ones,
# then removing it is OK, because adding defaults would bring that
# feature back --- there's 1-1 correspondence between minimized
# and full property set.
&& ! $(f:G) in $(components)
# locate all subproperties of $(x[1]) in the property set
local subproperties = [ select-subproperties $(fullp) : $(x) ] ;
if $(subproperties)
{
x = $(x[2-]) ;
# reconstitute the joined property name
local sorted = [ sequence.insertion-sort $(subproperties) ] ;
result += $(p)-$(sorted:G="":J=-) ;
x = [ set.difference $(x[2-]) : $(subproperties) ] ;
}
else
{
# locate all subproperties of f in the property set
local subproperties ;
local subfeatures = $($(f).subfeatures:G=) ;
if $(subfeatures)
{
local f_ = [ utility.ungrist $(f) ] ;
subfeatures = [ grist $(f_)-$(subfeatures) ] ;
subproperties = [ sequence.filter in-features subfeatures : $(x) ] ;
}
{
# 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.
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
# 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-]) ;
}
}
x = $(x[2-]) ;
}
}
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 can 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 there's ordinary feature F1 and composite feature
@@ -825,8 +922,21 @@ rule add-defaults ( properties * )
# 2. Free properties with ":" in values. We don't care, since free properties
# don't have defaults.
local xproperties = [ MATCH "^([^:]+)$" : $(properties) ] ;
local missing = [ set.difference $(.all-features) : $(xproperties:G) ] ;
return $(properties) [ defaults $(missing) ] ;
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
@@ -901,9 +1011,9 @@ local rule __test__ ( )
# use a fresh copy of the feature module
prepare-test feature-test-temp ;
# This is a local rule and so must be explicitly reimported into
# These are local rules and so must be explicitly reimported into
# the testing module
import feature : extend-feature validate-feature ;
import feature : extend-feature validate-feature select-subfeatures ;
import errors : try catch ;
import assert ;
@@ -912,7 +1022,7 @@ local rule __test__ ( )
feature define : : free ;
feature runtime-link : dynamic static : symmetric ;
feature optimization : on off ;
feature variant : debug release : implicit composite ;
feature variant : debug release : implicit composite symmetric ;
feature stdlib : native stlport ;
feature magic : : free ;
@@ -948,6 +1058,24 @@ local rule __test__ ( )
action <magic>17 : handle-magic2 ;
action <magic>17 : handle-magic3 ;
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 ;
@@ -960,6 +1088,10 @@ local rule __test__ ( )
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 a c e
: get-values x : <x>a <y>b <x>c <y>d <x>e ;
@@ -968,6 +1100,10 @@ local rule __test__ ( )
: expand gcc-3.0.1 debug <optimization>on
;
assert.result <fu>fu1 <fu-subfu2>q
: expand-subfeatures <fu>fu1
;
assert.result <variant>debug <define>_DEBUG <optimization>on
: expand debug <optimization>on
;
@@ -982,7 +1118,16 @@ local rule __test__ ( )
assert.result <runtime-link>static <define>foobar <optimization>on <toolset>gcc:<define>FOO
<toolset>gcc <variant>debug <stdlib>native <dummy>dummy1
: add-defaults <runtime-link>static <define>foobar <optimization>on <toolset>gcc:<define>FOO
: 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
: add-defaults <runtime-link>static <define>foobar
<optimization>on <toolset>gcc:<define>FOO <fu>fu1
;
set-default <runtime-link> : static ;
@@ -1099,14 +1244,14 @@ local rule __test__ ( )
implied-subfeature toolset 3.0.1 ;
}
catch \"3.0.1\" is not a known subfeature value of
feature <toolset> ;
<toolset> ;
try ;
{
implied-subfeature toolset not-a-version : gcc ;
}
catch \"not-a-version\" is not a known subfeature value of
feature <toolset> ;
<toolset>gcc ;
# leave a clean copy of the features module behind
finish-test feature-test-temp ;

View File

@@ -458,13 +458,13 @@ local rule __test__ ( )
feature.prepare-test property-test-temp ;
feature toolset : gcc : implicit ;
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 ;
feature variant : debug release : implicit composite symmetric ;
feature rtti : on off : link-incompatible ;
compose <variant>debug : <define>_DEBUG <optimization>off ;

View File

@@ -34,7 +34,11 @@ feature.subfeature toolset msvc : vendor
# versions of msvc are link-compatible
# link-incompatible
;
# Remember whether any versions have been initialized, allowing us to
# set the first initialized version as the default.
.initialized = ;
# Initialize the toolset for a specific version. As the result, path to
# compiler and, possible, program names are set up, and will be used when
# that version of compiler is requested. For example, you might have::
@@ -71,12 +75,17 @@ rule init (
if $(version)
{
feature.extend-subfeature toolset msvc : version : $(version) ;
feature.extend <toolset>msvc version : $(version) ;
if ! $(.initialized) # The first version initialized becomes the default.
{
feature.set-default toolset-msvc:version : $(version) ;
}
}
if $(vendor) && ( $(vendor) != intel )
{
feature.extend-subfeature toolset msvc : vendor : $(vendor) ;
feature.extend <toolset>msvc vendor : $(vendor) ;
}
# setup will be used iff a path has been specified. If setup is
@@ -135,6 +144,7 @@ rule init (
.CC = $(prefix)$(compiler) ;
.LD = $(prefix)$(linker) ;
}
.initialized = true ; # remember that we've initialized at least one version of msvc
}
.CC = cl ;