📄 feature.jam
字号:
#
# Requires: for every subproperty, there is a parent property. All
# features are explicitly expressed.
#
# This rule probably shouldn't be needed, but
# build-request.expand-no-defaults is being abused for unintended
# purposes and it needs help
rule compress-subproperties ( properties * )
{
local all-subs matched-subs result ;
for local p in $(properties)
{
if ! $(p:G)
{
assert.nonempty-variable p:G ; # expecting fully-gristed properties
}
if ! subfeature in $($(p:G).attributes)
{
local subs = [
sequence.insertion-sort
[ sequence.filter is-subproperty-of $(p) : $(properties) ]
] ;
matched-subs += $(subs) ;
local subvalues = -$(subs:G=:J=-) ;
subvalues ?= "" ;
result += $(p)$(subvalues) ;
}
else
{
all-subs += $(p) ;
}
}
assert.result true : set.equal $(all-subs) : $(matched-subs) ;
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
# F2, which includes some value for F1, and both feature have default values,
# then the default value of F1 will be added, not the value in F2. This might
# not be right idea: consider
#
# feature variant : debug ... ;
# <variant>debug : .... <runtime-debugging>on
# feature <runtime-debugging> : off on ;
#
# Here, when adding default for an empty property set, we'll get
#
# <variant>debug <runtime_debugging>off
#
# and that's kind of strange.
rule add-defaults ( properties * )
{
for local v in $(properties:G=)
{
if $(v) in $(properties)
{
error add-defaults requires explicitly specified features,
but \"$(v)\" appears to be the value of an un-expanded implicit feature ;
}
}
# We don't add default for elements with ":" inside. This catches:
# 1. Conditional properties --- we don't want <variant>debug:<define>DEBUG
# to be takes as specified value for <variant>
# 2. Free properties with ":" in values. We don't care, since free properties
# don't have defaults.
local xproperties = [ MATCH "^([^:]+)$" : $(properties) ] ;
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
# 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) ;
}
# Appends a rule to the list of rules assigned to the given feature or property.
# That rules will be used in extending property sets by the 'run-actions' rule.
# The rule should accept two arguments:
# - the property which is registered
# - the list of all properties
# and return a set of additional
# properties to be added. Property should be specified in the usual way:
# <feature>value, and feature should be specified as <feature>.
rule action ( property-or-feature : rule-name )
{
.rules.$(property-or-feature) += [ indirect.make-qualified $(rule-name) ] ;
}
# Returns 'properties' augmented with results of calling rule associated with properties.
# If both a property and its feature have rules, only rules for the property are executed.
rule run-actions ( properties * )
{
local added = ;
for local e in $(properties)
{
local rules ;
if $(.rules.$(e))
{
rules = $(.rules.$(e)) ;
}
else if $(.rules.$(e:G))
{
rules = $(.rules.$(e:G)) ;
}
for local r in $(rules)
{
added += [ indirect.call $(r) $(e) : $(properties) ] ;
}
}
return $(properties) $(added) ;
}
# tests of module feature
local rule __test__ ( )
{
# use a fresh copy of the feature module
prepare-test feature-test-temp ;
# These are local rules and so must be explicitly reimported into
# the testing module
import feature : extend-feature validate-feature select-subfeatures ;
import errors : try catch ;
import assert ;
feature toolset : gcc : implicit ;
feature define : : free ;
feature runtime-link : dynamic static : symmetric ;
feature optimization : on off ;
feature variant : debug release : implicit composite symmetric ;
feature stdlib : native stlport ;
feature magic : : free ;
compose <variant>debug : <define>_DEBUG <optimization>off ;
compose <variant>release : <define>NDEBUG <optimization>on ;
extend-feature toolset : msvc metrowerks ;
subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4
3.0 3.0.1 3.0.2 : optional ;
local rule handle-stlport ( property : properties * )
{
return <include>/path/to/stlport ;
}
local rule handle-magic ( property : properties * )
{
return <define>MAGIC=$(property:G=) ;
}
local rule handle-magic2 ( property : properties * )
{
return <define>MAGIC=BIG_MAGIC ;
}
local rule handle-magic3 ( property : properties * )
{
return <define>MAGIC=VERY_BIG_MAGIC ;
}
action <stdlib>stlport : handle-stlport ;
action <magic> : handle-magic ;
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 ;
assert.result <define>foo=x-y
: expand-subfeatures <define>foo=x-y ;
assert.result <toolset>gcc <toolset-gcc:version>3.0.1
: expand-subfeatures gcc-3.0.1 ;
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 ;
assert.result <toolset>gcc <toolset-gcc:version>3.0.1
<variant>debug <define>_DEBUG <optimization>on
: 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
;
assert.result <optimization>on <variant>debug <define>_DEBUG
: expand <optimization>on debug
;
assert.result <runtime-link>dynamic <optimization>on
: defaults <runtime-link> <define> <optimization>
;
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
;
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 ;
assert.result <runtime-link>static
: defaults <runtime-link>
;
assert.result <toolset>gcc <define>foo <stdlib>stlport <magic>3 <include>/path/to/stlport <define>MAGIC=3
: run-actions <toolset>gcc <define>foo <stdlib>stlport <magic>3
;
assert.result <magic>17 <define>MAGIC=BIG_MAGIC <define>MAGIC=VERY_BIG_MAGIC
: run-actions <magic>17
;
assert.result gcc-3.0.1 debug <optimization>on
: minimize [ expand gcc-3.0.1 debug <optimization>on <stdlib>native ]
;
assert.result gcc-3.0.1 debug <runtime-link>dynamic
: minimize [ expand gcc-3.0.1 debug <optimization>off <runtime-link>dynamic ]
;
assert.result gcc-3.0.1 debug
: minimize [ expand gcc-3.0.1 debug <optimization>off ]
;
assert.result debug <optimization>on
: minimize [ expand debug <optimization>on ]
;
assert.result gcc-3.0
: minimize <toolset>gcc <toolset-gcc:version>3.0
;
assert.result gcc-3.0
: minimize <toolset-gcc:version>3.0 <toolset>gcc
;
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 ;
{
expand release <optimization>off <optimization>on ;
}
catch explicitly-specified values of non-free feature <optimization> conflict ;
try ;
{
validate-feature <foobar> ;
}
catch unknown feature ;
validate-value-string <toolset> gcc ;
validate-value-string <toolset> gcc-3.0.1 ;
try ;
{
validate-value-string <toolset> digital_mars ;
}
catch \"digital_mars\" is not a known value of <toolset> ;
try ;
{
feature foobar : : baz ;
}
catch unknown attributes: baz ;
feature feature1 ;
try ;
{
feature feature1 ;
}
catch feature already defined: ;
try ;
{
feature feature2 : : free implicit ;
}
catch free features cannot also be implicit ;
try ;
{
feature feature3 : : free propagated ;
}
catch free features cannot be propagated ;
try ;
{
implied-feature lackluster ;
}
catch \"lackluster\" is not a value of an implicit feature ;
try ;
{
implied-subfeature <toolset> 3.0.1 ;
}
catch \"3.0.1\" is not a known subfeature value of
<toolset> ;
try ;
{
implied-subfeature <toolset> not-a-version : gcc ;
}
catch \"not-a-version\" is not a known subfeature value of
<toolset>gcc ;
# leave a clean copy of the features module behind
finish-test feature-test-temp ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -