📄 virtual-target.jam
字号:
# Class which acts exactly like 'action', except that its sources are not# scanned for dependencies.#class non-scanning-action : action{ rule __init__ ( sources * : action-name + : property-set ? ) { action.__init__ $(sources) : $(action-name) : $(property-set) ; } rule actualize-source-type ( sources * : property-set ) { local result ; for local i in $(sources) { result += [ $(i).actualize ] ; } return $(result) ; }}# Creates a virtual target with an appropriate name and type from 'file'. If a# target with that name in that project already exists, returns that already# created target.## FIXME: a more correct way would be to compute the path to the file, based on# name and source location for the project, and use that path to determine if# the target has already been created. This logic should be shared with how we# usually find targets identified by a specific target id. It should also be# updated to work correctly when the file is specified using both relative and# absolute paths.## TODO: passing a project with all virtual targets is starting to be annoying.#rule from-file ( file : file-loc : project ){ import type ; # Had to do this here to break a circular dependency. # Check whether we already created a target corresponding to this file. local path = [ path.root [ path.root $(file) $(file-loc) ] [ path.pwd ] ] ; if $(.files.$(path)) { return $(.files.$(path)) ; } else { local name = [ path.make $(file) ] ; local type = [ type.type $(file) ] ; local result ; result = [ new file-target $(file) : $(type) : $(project) : : $(file-loc) ] ; .files.$(path) = $(result) ; return $(result) ; }}# Registers a new virtual target. Checks if there is already a registered target# with the same name, type, project and subvariant properties as well as the# same sources and equal action. If such target is found it is returned and a# new 'target' is not registered. Otherwise, 'target' is registered and# returned.#rule register ( target ){ local signature = [ sequence.join [ $(target).path ] [ $(target).name ] : - ] ; local result ; for local t in $(.cache.$(signature)) { local a1 = [ $(t).action ] ; local a2 = [ $(target).action ] ; if ! $(result) { if ! $(a1) && ! $(a2) { result = $(t) ; } else { if $(a1) && $(a2) && ( [ $(a1).action-name ] = [ $(a2).action-name ] ) && ( [ $(a1).sources ] = [ $(a2).sources ] ) { local ps1 = [ $(a1).properties ] ; local ps2 = [ $(a2).properties ] ; local p1 = [ $(ps1).base ] [ $(ps1).free ] [ set.difference [ $(ps1).dependency ] : [ $(ps1).incidental ] ] ; local p2 = [ $(ps2).base ] [ $(ps2).free ] [ set.difference [ $(ps2).dependency ] : [ $(ps2).incidental ] ] ; if $(p1) = $(p2) { result = $(t) ; } } } } } if ! $(result) { .cache.$(signature) += $(target) ; result = $(target) ; } .recent-targets += $(result) ; .all-targets += $(result) ; return $(result) ;}# Each target returned by 'register' is added to the .recent-targets list,# returned by this function. This allows us to find all virtual targets created# when building a specific main target, even those constructed only as# intermediate targets.#rule recent-targets ( ){ return $(.recent-targets) ;}rule clear-recent-targets ( ){ .recent-targets = ;}# Returns all virtual targets ever created.#rule all-targets ( ){ return $(.all-targets) ;}# Returns all targets from 'targets' with types equal to 'type' or derived from# it.#rule select-by-type ( type : targets * ){ local result ; for local t in $(targets) { if [ type.is-subtype [ $(t).type ] $(type) ] { result += $(t) ; } } return $(result) ;}rule register-actual-name ( actual-name : virtual-target ){ if $(.actual.$(actual-name)) { local cs1 = [ $(.actual.$(actual-name)).creating-subvariant ] ; local cs2 = [ $(virtual-target).creating-subvariant ] ; local cmt1 = [ $(cs1).main-target ] ; local cmt2 = [ $(cs2).main-target ] ; local action1 = [ $(.actual.$(actual-name)).action ] ; local action2 = [ $(virtual-target).action ] ; local properties-added ; local properties-removed ; if $(action1) && $(action2) { local p1 = [ $(action1).properties ] ; p1 = [ $(p1).raw ] ; local p2 = [ $(action2).properties ] ; p2 = [ $(p2).raw ] ; properties-removed = [ set.difference $(p1) : $(p2) ] ; properties-removed ?= "none" ; properties-added = [ set.difference $(p2) : $(p1) ] ; properties-added ?= "none" ; } errors.error "Duplicate name of actual target:" $(actual-name) : "previous virtual target" [ $(.actual.$(actual-name)).str ] : "created from" [ $(cmt1).full-name ] : "another virtual target" [ $(virtual-target).str ] : "created from" [ $(cmt2).full-name ] : "added properties:" $(properties-added) : "removed properties:" $(properties-removed) ; } else { .actual.$(actual-name) = $(virtual-target) ; }}# Traverses the dependency graph of 'target' and return all targets that will be# created before this one is created. If the root of some dependency graph is# found during traversal, it is either included or not, depending on the# 'include-roots' value. In either case traversal stops at root targets, i.e.# root target sources are not traversed.#rule traverse ( target : include-roots ? : include-sources ? ){ local result ; if [ $(target).action ] { local action = [ $(target).action ] ; # This includes the 'target' as well. result += [ $(action).targets ] ; for local t in [ $(action).sources ] { if ! [ $(t).root ] { result += [ traverse $(t) : $(include-roots) : $(include-sources) ] ; } else if $(include-roots) { result += $(t) ; } } } else if $(include-sources) { result = $(target) ; } return $(result) ;}# Takes an 'action' instance and creates a new instance of it and all targets# produced by the action. The rule-name and properties are set to# 'new-rule-name' and 'new-properties', if those are specified. Returns the# cloned action.#rule clone-action ( action : new-project : new-action-name ? : new-properties ? ){ if ! $(new-action-name) { new-action-name = [ $(action).action-name ] ; } if ! $(new-properties) { new-properties = [ $(action).properties ] ; } local action-class = [ modules.peek $(action) : __class__ ] ; local cloned-action = [ class.new $(action-class) [ $(action).sources ] : $(new-action-name) : $(new-properties) ] ; local cloned-targets ; for local target in [ $(action).targets ] { local n = [ $(target).name ] ; # Do not modify produced target names. local cloned-target = [ class.new file-target $(n) exact : [ $(target).type ] : $(new-project) : $(cloned-action) ] ; local d = [ $(target).dependencies ] ; if $(d) { $(cloned-target).depends $(d) ; } $(cloned-target).root [ $(target).root ] ; $(cloned-target).creating-subvariant [ $(target).creating-subvariant ] ; cloned-targets += $(cloned-target) ; } return $(cloned-action) ;}class subvariant{ import sequence ; import type ; rule __init__ ( main-target # The instance of main-target class. : property-set # Properties requested for this target. : sources * : build-properties # Actually used properties. : sources-usage-requirements # Properties propagated from sources. : created-targets * ) # Top-level created targets. { self.main-target = $(main-target) ; self.properties = $(property-set) ; self.sources = $(sources) ; self.build-properties = $(build-properties) ; self.sources-usage-requirements = $(sources-usage-requirements) ; self.created-targets = $(created-targets) ; # Pre-compose a list of other dependency graphs this one depends on. local deps = [ $(build-properties).get <implicit-dependency> ] ; for local d in $(deps) { self.other-dg += [ $(d:G=).creating-subvariant ] ; } self.other-dg = [ sequence.unique $(self.other-dg) ] ; } rule main-target ( ) { return $(self.main-target) ; } rule created-targets ( ) { return $(self.created-targets) ; } rule requested-properties ( ) { return $(self.properties) ; } rule build-properties ( ) { return $(self.build-properties) ; } rule sources-usage-requirements ( ) { return $(self.sources-usage-requirements) ; } rule set-usage-requirements ( usage-requirements ) { self.usage-requirements = $(usage-requirements) ; } rule usage-requirements ( ) { return $(self.usage-requirements) ; } # Returns all targets referenced by this subvariant, either directly or # indirectly, and either as sources, or as dependency properties. Targets # referred to using the dependency property are returned as properties, not # targets. # rule all-referenced-targets ( ) { # Find directly referenced targets. local deps = [ $(self.build-properties).dependency ] ; local all-targets = $(self.sources) $(deps) ; # Find other subvariants. local r ; for local t in $(all-targets) { r += [ $(t:G=).creating-subvariant ] ; } r = [ sequence.unique $(r) ] ; for local s in $(r) { if $(s) != $(__name__) { all-targets += [ $(s).all-referenced-targets ] ; } } return $(all-targets) ; } # Returns the properties specifying implicit include paths to generated # headers. This traverses all targets in this subvariant and subvariants # referred by <implcit-dependecy> properties. For all targets of type # 'target-type' (or for all targets, if 'target-type' is not specified), the # result will contain <$(feature)>path-to-that-target. # rule implicit-includes ( feature : target-type ? ) { local key = ii$(feature)-$(target-type:E="") ; if ! $($(key))-is-not-empty { local target-paths = [ all-target-directories $(target-type) ] ; target-paths = [ sequence.unique $(target-paths) ] ; local result = $(target-paths:G=$(feature)) ; if ! $(result) { result = "" ; } $(key) = $(result) ; } if $($(key)) = "" { return ; } else { return $($(key)) ; } } rule all-target-directories ( target-type ? ) { if ! $(self.target-directories) { compute-target-directories $(target-type) ; } return $(self.target-directories) ; } rule compute-target-directories ( target-type ? ) { local result ; for local t in $(self.created-targets) { # Skip targets of the wrong type. if ! $(target-type) || [ type.is-derived [ $(t).type ] $(target-type) ] { result = [ sequence.merge $(result) : [ $(t).path ] ] ; } } for local d in $(self.other-dg) { result += [ $(d).all-target-directories $(target-type) ] ; } self.target-directories = $(result) ; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -