📄 property.jam
字号:
result += $(e) ;
}
}
return $(result) ;
}
# Selects properties which correspond to any of the given features.
rule select ( features * : properties * )
{
local result ;
# add any missing angle brackets
local empty = "" ;
features = $(empty:G=$(features)) ;
for local p in $(properties)
{
if $(p:G) in $(features)
{
result += $(p) ;
}
}
return $(result) ;
}
# Returns a modified version of properties with all values of the
# given feature replaced by the given value.
# If 'value' is empty the feature will be removed
rule change ( properties * : feature value ? )
{
local result ;
for local p in $(properties)
{
if $(p:G) = $(feature)
{
result += $(value:G=$(feature)) ;
}
else
{
result += $(p) ;
}
}
return $(result) ;
}
# If 'property' is conditional property, returns
# condition and the property, e.g
# <variant>debug,<toolset>gcc:<inlining>full will become
# <variant>debug,<toolset>gcc <inlining>full.
# Otherwise, returns empty string.
rule split-conditional ( property )
{
local m = [ MATCH "(.+):<(.+)" : $(property) ] ;
if $(m)
{
return $(m[1]) <$(m[2]) ;
}
}
# Interpret all path properties in 'properties' as relative to 'path'
# The property values are assumed to be in system-specific form, and
# will be translated into normalized form.
rule translate-paths ( properties * : path )
{
local result ;
for local p in $(properties)
{
local split = [ split-conditional $(p) ] ;
local condition = "" ;
if $(split)
{
condition = $(split[1]): ;
p = $(split[2]) ;
}
if path in [ feature.attributes $(p:G) ]
{
local values = [ regex.split $(p:TG=) "&&" ] ;
local t ;
for local v in $(values)
{
t += [ path.root [ path.make $(v) ] $(path) ] ;
}
t = $(t:J="&&") ;
result += $(condition)$(t:TG=$(p:G)) ;
}
else
{
result += $(condition)$(p) ;
}
}
return $(result) ;
}
# Assumes that all feature values that start with '@' are
# names of rules, used in 'context-module'. Such rules
# can be either local to the module or global. Converts such
# values into 'indirect-rule' format (see indirect.jam), so
# that they can be called from other modules.
rule translate-indirect ( specification * : context-module )
{
local result ;
for local p in $(specification)
{
local m = [ MATCH ^@(.+) : $(p:G=) ] ;
if $(m)
{
local v = [ indirect.make $(m) : $(context-module) ] ;
v = @$(v) ;
result += $(v:G=$(p:G)) ;
}
else
{
result += $(p) ;
}
}
return $(result) ;
}
# Class which maintains a property set -> string
# mapping
class property-map
{
import numbers ;
import sequence ;
import errors : error ;
rule __init__ ( )
{
self.next-flag = 1 ;
}
# Associate 'value' with 'properties'
rule insert ( properties + : value )
{
self.all-flags += $(self.next-flag) ;
self.properties.$(self.next-flag) = $(properties) ;
self.value.$(self.next-flag) = $(value) ;
self.next-flag = [ numbers.increment $(self.next-flag) ] ;
}
# Return the value associated with 'properties'
# or any subset of it. If more than one
# subset has value assigned to it, return the
# value for the longest subset, if it's unique.
rule find ( properties + )
{
return [ find-replace $(properties) ] ;
}
# Find the value associated with 'properties'.
# If 'value' parameter is given, replaces the found value
# Returns the value that were stored originally.
rule find-replace ( properties + : value ? )
{
# First find all matches
local matches ;
local match-ranks ;
for local i in $(self.all-flags)
{
if $(self.properties.$(i)) in $(properties)
{
matches += $(i) ;
match-ranks += [ sequence.length
$(self.properties.$(i)) ] ;
}
}
local best = [ sequence.select-highest-ranked
$(matches) : $(match-ranks) ] ;
if $(best[2])
{
error "Ambiguous key" ;
}
local original = $(self.value.$(best)) ;
if $(value)
{
self.value.$(best) = $(value) ;
}
return $(original) ;
}
}
local rule __test__ ( )
{
import errors : try catch ;
import feature ;
import feature : feature subfeature compose ;
# local rules must be explicitly re-imported
import property : path-order ;
feature.prepare-test property-test-temp ;
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 symmetric ;
feature rtti : on off : link-incompatible ;
compose <variant>debug : <define>_DEBUG <optimization>off ;
compose <variant>release : <define>NDEBUG <optimization>on ;
import assert ;
import "class" : new ;
validate <toolset>gcc <toolset>gcc-3.0.1 : $(test-space) ;
assert.true path-order $(test-space) debug <define>foo ;
assert.false path-order $(test-space) <define>foo debug ;
assert.true path-order $(test-space) gcc debug ;
assert.false path-order $(test-space) debug gcc ;
assert.true path-order $(test-space) <optimization>on <rtti>on ;
assert.false path-order $(test-space) <rtti>on <optimization>on ;
assert.result <toolset>gcc <rtti>off <define>FOO
: refine <toolset>gcc <rtti>off
: <define>FOO
: $(test-space)
;
assert.result <toolset>gcc <optimization>on
: refine <toolset>gcc <optimization>off
: <optimization>on
: $(test-space)
;
assert.result <toolset>gcc <rtti>off
: refine <toolset>gcc : <rtti>off : $(test-space)
;
assert.result <toolset>gcc <rtti>off <rtti>off:<define>FOO
: refine <toolset>gcc : <rtti>off <rtti>off:<define>FOO
: $(test-space)
;
assert.result <toolset>gcc:<define>foo <toolset>gcc:<define>bar
: refine <toolset>gcc:<define>foo : <toolset>gcc:<define>bar
: $(test-space)
;
assert.result <define>MY_RELEASE
: evaluate-conditionals-in-context
<variant>release,<rtti>off:<define>MY_RELEASE
: <toolset>gcc <variant>release <rtti>off
;
assert.result debug
: as-path <optimization>off <variant>debug
: $(test-space)
;
assert.result gcc/debug/rtti-off
: as-path <toolset>gcc <optimization>off <rtti>off <variant>debug
: $(test-space)
;
try ;
validate <feature>value : $(test-space) ;
catch "Invalid property '<feature>value': unknown feature 'feature'." ;
try ;
validate <rtti>default : $(test-space) ;
catch \"default\" is not a known value of feature <rtti> ;
validate <define>WHATEVER : $(test-space) ;
try ;
validate <rtti> : $(test-space) ;
catch "Invalid property '<rtti>': No value specified for feature 'rtti'." ;
try ;
validate value : $(test-space) ;
catch "value" is not a value of an implicit feature ;
assert.result <rtti>on
: remove free implicit : <toolset>gcc <define>foo <rtti>on : $(test-space) ;
assert.result <include>a
: select include : <include>a <toolset>gcc ;
assert.result <include>a
: select include bar : <include>a <toolset>gcc ;
assert.result <include>a <toolset>gcc
: select include <bar> <toolset> : <include>a <toolset>gcc ;
assert.result <toolset>kylix <include>a
: change <toolset>gcc <include>a : <toolset> kylix ;
pm = [ new property-map ] ;
$(pm).insert <toolset>gcc : o ;
$(pm).insert <toolset>gcc <os>NT : obj ;
$(pm).insert <toolset>gcc <os>CYGWIN : obj ;
assert.equal o
: [ $(pm).find <toolset>gcc ] ;
assert.equal obj
: [ $(pm).find <toolset>gcc <os>NT ] ;
try ;
$(pm).find <toolset>gcc <os>NT <os>CYGWIN ;
catch "Ambiguous key" ;
# Test ordinary properties
assert.result
: split-conditional <toolset>gcc
;
# Test properties with ":"
assert.result
: split-conditional <define>FOO=A::B
;
# Test conditional feature
assert.result <toolset>gcc,<toolset-gcc:version>3.0 <define>FOO
: split-conditional <toolset>gcc,<toolset-gcc:version>3.0:<define>FOO
;
feature.finish-test property-test-temp ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -