📄 property.jam
字号:
{ 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 a conditional property, returns the condition and the# property. E.g. <variant>debug,<toolset>gcc:<inlining>full will become# <variant>debug,<toolset>gcc <inlining>full. Otherwise, returns an 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 they# can be called from other modules. Does nothing for such values that are# already in the 'indirect-rule' format.#rule translate-indirect ( specification * : context-module ){ local result ; for local p in $(specification) { local m = [ MATCH ^@(.+) : $(p:G=) ] ; if $(m) { local v ; if [ MATCH "^([^%]*)%([^%]+)$" : $(m) ] { # Rule is already in the 'indirect-rule' format. v = $(m) ; } else { if ! [ MATCH ".*([.]).*" : $(m) ] { # This is an unqualified rule name. The user might want to # set flags on this rule name and toolset.flag # auto-qualifies it. Need to do the same here so flag # setting works. We can arrange for toolset.flag to *not* # auto-qualify the argument but then two rules defined in # two Jamfiles would conflict. m = $(context-module).$(m) ; } v = [ indirect.make $(m) : $(context-module) ] ; } v = @$(v) ; result += $(v:G=$(p:G)) ; } else { result += $(p) ; } } return $(result) ;}# Binds all dependency properties in a list relative to the given project.# Targets with absolute paths will be left unchanged and targets which have a# project specified will have the path to the project interpreted relative to# the specified location.#rule translate-dependencies ( specification * : project-id : location ){ local result ; for local p in $(specification) { local split = [ split-conditional $(p) ] ; local condition = "" ; if $(split) { condition = $(split[1]): ; p = $(split[2]) ; } if dependency in [ feature.attributes $(p:G) ] { local split-target = [ regex.match (.*)//(.*) : $(p:G=) ] ; if $(split-target) { local rooted = [ path.root [ path.make $(split-target[1]) ] [ path.root $(location) [ path.pwd ] ] ] ; result += $(condition)$(p:G)$(rooted)//$(split-target[2]) ; } else if [ path.is-rooted $(p:G=) ] { result += $(condition)$(p) ; } else { result += $(condition)$(p:G)$(project-id)//$(p:G=) ; } } else { result += $(condition)$(p) ; } } return $(result) ;}# Class maintaining a property set -> string mapping.#class property-map{ import errors ; import numbers ; import sequence ; 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) ] ; } # Returns the value associated with 'properties' or any subset of it. If # more than one subset has a value assigned to it, returns the value for the # longest subset, if it is unique. # rule find ( properties + ) { return [ find-replace $(properties) ] ; } # Returns the value associated with 'properties'. If 'value' parameter is # given, replaces the found value. # 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]) { errors.error "Ambiguous key" ; } local original = $(self.value.$(best)) ; if $(value) { self.value.$(best) = $(value) ; } return $(original) ; }}rule __test__ ( ){ import assert ; import "class" : new ; import errors : try catch ; import feature ; # Local rules must be explicitly re-imported. import property : path-order abbreviate-dashed ; feature.prepare-test property-test-temp ; feature.feature toolset : gcc : implicit symmetric ; feature.subfeature toolset gcc : version : 2.95.2 2.95.3 2.95.4 3.0 3.0.1 3.0.2 : optional ; feature.feature define : : free ; feature.feature runtime-link : dynamic static : symmetric link-incompatible ; feature.feature optimization : on off ; feature.feature variant : debug release : implicit composite symmetric ; feature.feature rtti : on off : link-incompatible ; feature.compose <variant>debug : <define>_DEBUG <optimization>off ; feature.compose <variant>release : <define>NDEBUG <optimization>on ; 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-set-equal <toolset>gcc <rtti>off <define>FOO : refine <toolset>gcc <rtti>off : <define>FOO : $(test-space) ; assert.result-set-equal <toolset>gcc <optimization>on : refine <toolset>gcc <optimization>off : <optimization>on : $(test-space) ; assert.result-set-equal <toolset>gcc <rtti>off : refine <toolset>gcc : <rtti>off : $(test-space) ; assert.result-set-equal <toolset>gcc <rtti>off <rtti>off:<define>FOO : refine <toolset>gcc : <rtti>off <rtti>off:<define>FOO : $(test-space) ; assert.result-set-equal <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) ; assert.result optmz-off : abbreviate-dashed optimization-off ; assert.result rntm-lnk-sttc : abbreviate-dashed runtime-link-static ; 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-set-equal <rtti>on : remove free implicit : <toolset>gcc <define>foo <rtti>on : $(test-space) ; assert.result-set-equal <include>a : select include : <include>a <toolset>gcc ; assert.result-set-equal <include>a : select include bar : <include>a <toolset>gcc ; assert.result-set-equal <include>a <toolset>gcc : select include <bar> <toolset> : <include>a <toolset>gcc ; assert.result-set-equal <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-set-equal <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 + -