📄 targets.jam
字号:
if ! [ $(result).exists ] { result = ; } } # Interpret id as project-id. if ! $(result) { local project-module = [ project.find $(id) : $(current-location) ] ; if $(project-module) { result = [ project.target $(project-module) ] ; } } } return $(result) ; } # Find and return the target with the specified id, treated relative to # self. Id may specify either a target or a file name with the target taking # priority. May report an error or return nothing if the target is not found # depending on the 'no-error' parameter. # rule find ( id : no-error ? ) { local v = $(.id.$(id)) ; if ! $(v) { v = [ find-really $(id) ] ; if ! $(v) { v = none ; } .id.$(id) = $(v) ; } if $(v) != none { return $(v) ; } else { if ! $(no-error) { local current-location = [ get location ] ; ECHO "error: Unable to find file or target named" ; ECHO "error: '$(id)'" ; ECHO "error: referred from project at" ; ECHO "error: '$(current-location)'" ; ECHO $(extra-error-message) ; EXIT ; } } } rule build-main-targets ( ) { self.built-main-targets = true ; for local a in $(self.alternatives) { local name = [ $(a).name ] ; local target = $(self.main-target.$(name)) ; if ! $(target) { local t = [ new main-target $(name) : $(self.project) ] ; self.main-target.$(name) = $(t) ; self.main-targets += $(t) ; target = $(self.main-target.$(name)) ; } $(target).add-alternative $(a) ; } } # Accessor, add a constant. # rule add-constant ( name # Variable name of the constant. : value + # Value of the constant. : type ? # Optional type of value. ) { switch $(type) { case path : local r ; for local v in $(value) { v = [ path.root [ path.make $(v) ] $(self.location) ] ; # Now make the value absolute path. v = [ path.root $(v) [ path.pwd ] ] ; # Constants should be in platform-native form. v = [ path.native $(v) ] ; r += $(v) ; } value = $(r) ; } if ! $(name) in $(self.constants) { self.constants += $(name) ; } self.constant.$(name) = $(value) ; # Inject the constant in the scope of the Jamroot module. modules.poke $(self.project-module) : $(name) : $(value) ; } rule inherit ( parent ) { for local c in [ modules.peek $(parent) : self.constants ] { # No need to pass the type. Path constants were converted to # absolute paths already by parent. add-constant $(c) : [ modules.peek $(parent) : self.constant.$(c) ] ; } # Import rules from parent. local this-module = [ project-module ] ; local parent-module = [ $(parent).project-module ] ; # Do not import rules coming from 'project-rules' as they must be # imported localized. local user-rules = [ set.difference [ RULENAMES $(parent-module) ] : [ RULENAMES project-rules ] ] ; IMPORT $(parent-module) : $(user-rules) : $(this-module) : $(user-rules) ; EXPORT $(this-module) : $(user-rules) ; }}# Helper rules to detect cycles in main target references.#local rule start-building ( main-target-instance ){ if $(main-target-instance) in $(.targets-being-built) { local names ; for local t in $(.targets-being-built) $(main-target-instance) { names += [ $(t).full-name ] ; } errors.error "Recursion in main target references" : "the following target are being built currently:" : $(names) ; } .targets-being-built += $(main-target-instance) ;}local rule end-building ( main-target-instance ){ .targets-being-built = $(.targets-being-built[1--2]) ;}# A named top-level target in Jamfile.#class main-target : abstract-target{ import assert ; import build-request ; import errors ; import feature ; import print ; import property-set ; import sequence ; import targets : start-building end-building ; rule __init__ ( name : project ) { abstract-target.__init__ $(name) : $(project) ; } # Add a new alternative for this target rule add-alternative ( target ) { local d = [ $(target).default-build ] ; if $(self.alternatives) && ( $(self.default-build) != $(d) ) { errors.error "default build must be identical in all alternatives" : "main target is" [ full-name ] : "with" [ $(d).raw ] : "differing from previous default build" [ $(self.default-build).raw ] ; } else { self.default-build = $(d) ; } self.alternatives += $(target) ; } # Returns the best viable alternative for this property-set. See the # documentation for selection rules. # local rule select-alternatives ( property-set debug ? ) { # When selecting alternatives we have to consider defaults, for example: # lib l : l.cpp : <variant>debug ; # lib l : l_opt.cpp : <variant>release ; # won't work unless we add default value <variant>debug. property-set = [ $(p).add-defaults ] ; # The algorithm: we keep the current best viable alternative. When we've # got a new best viable alternative, we compare it with the current one. local best ; local best-properties ; if $(self.alternatives[2-]) { local bad ; local worklist = $(self.alternatives) ; while $(worklist) && ! $(bad) { local v = $(worklist[1]) ; local properties = [ $(v).match $(property-set) $(debug) ] ; if $(properties) != no-match { if ! $(best) { best = $(v) ; best-properties = $(properties) ; } else { if $(properties) = $(best-properties) { bad = true ; } else if $(properties) in $(best-properties) { # Do nothing, this alternative is worse } else if $(best-properties) in $(properties) { best = $(v) ; best-properties = $(properties) ; } else { bad = true ; } } } worklist = $(worklist[2-]) ; } if ! $(bad) { return $(best) ; } } else { return $(self.alternatives) ; } } rule apply-default-build ( property-set ) { # 1. First, see what properties from default-build are already present # in property-set. local raw = [ $(property-set).raw ] ; local specified-features = $(raw:G) ; local defaults-to-apply ; for local d in [ $(self.default-build).raw ] { if ! $(d:G) in $(specified-features) { defaults-to-apply += $(d) ; } } # 2. If there are any defaults to be applied, form a new build request. # Pass it through to 'expand-no-defaults' since default-build might # contain "release debug" resulting in two property-sets. local result ; if $(defaults-to-apply) { properties = [ build-request.expand-no-defaults # We have to compress subproperties here to prevent property # lists like: # # <toolset>msvc <toolset-msvc:version>7.1 <threading>multi # # from being expanded into: # # <toolset-msvc:version>7.1/<threading>multi # <toolset>msvc/<toolset-msvc:version>7.1/<threading>multi # # due to a cross-product property combination. That may be an # indication that build-request.expand-no-defaults is the wrong # rule to use here. [ feature.compress-subproperties $(raw) ] $(defaults-to-apply) ] ; if $(properties) { for local p in $(properties) { result += [ property-set.create [ feature.expand [ feature.split $(p) ] ] ] ; } } else { result = [ property-set.empty ] ; } } else { result = $(property-set) ; } return $(result) ; } # Select an alternative for this main target, by finding all alternatives # which requirements are satisfied by 'properties' and picking the one with # the longest requirements set. Returns the result of calling 'generate' on # that alternative. # rule generate ( property-set ) { start-building $(__name__) ; # We want composite properties in build request act as if all the # properties it expands too are explicitly specified. property-set = [ $(property-set).expand ] ; local all-property-sets = [ apply-default-build $(property-set) ] ; local usage-requirements = [ property-set.empty ] ; local result ; for local p in $(all-property-sets) { local r = [ generate-really $(p) ] ; if $(r) { usage-requirements = [ $(usage-requirements).add $(r[1]) ] ; result += $(r[2-]) ; } } end-building $(__name__) ; return $(usage-requirements) [ sequence.unique $(result) ] ; } # Generates the main target with the given property set and returns a list # which first element is property-set object containing usage-requirements # of generated target and with generated virtual target in other elements. # It is possible that no targets are generated. # local rule generate-really ( property-set ) { local best-alternatives = [ select-alternatives $(property-set) ] ; if ! $(best-alternatives) { ECHO "error: No best alternative for" [ full-name ] ; select-alternatives $(property-set) debug ; return [ property-set.empty ] ; } else { # Now return virtual targets for the only alternative. return [ $(best-alternatives).generate $(property-set) ] ; } } rule rename ( new-name ) { abstract-target.rename $(new-name) ; for local a in $(self.alternatives) { $(a).rename $(new-name) ; } }}# Abstract target refering to a source file. This is an artificial entity# allowing sources to a target to be represented using a list of abstract target# instances.#class file-reference : abstract-target{ import virtual-target ; import property-set ; import path ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -