📄 virtual-target.jam
字号:
# Copyright 2003 Dave Abrahams# Copyright 2005, 2006 Rene Rivera# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus# Distributed under the Boost Software License, Version 1.0.# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)# Implements virtual targets, which correspond to actual files created during a# build, but are not yet targets in Jam sense. They are needed, for example,# when searching for possible transformation sequences, when it is not yet known# whether a particular target should be created at all.import "class" : new ;import errors ;import path ;import sequence ;import set ;import type ;import utility ;# +--------------------------+# | virtual-target |# +==========================+# | actualize |# +--------------------------+# | actualize-action() = 0 |# | actualize-location() = 0 |# +----------------+---------+# |# ^# / \# +-+-+# |# +---------------------+ +-------+--------------+# | action | | abstract-file-target |# +=====================| * +======================+# | action-name | +--+ action |# | properties | | +----------------------+# +---------------------+--+ | actualize-action() |# | actualize() |0..1 +-----------+----------+# | path() | |# | adjust-properties() | sources |# | actualize-sources() | targets |# +------+--------------+ ^# | / \# ^ +-+-+# / \ |# +-+-+ +-------------+-------------+# | | |# | +------+---------------+ +--------+-------------+# | | file-target | | searched-lib-target |# | +======================+ +======================+# | | actualize-location() | | actualize-location() |# | +----------------------+ +----------------------+# |# +-+------------------------------+# | |# +----+----------------+ +---------+-----------+# | compile-action | | link-action |# +=====================+ +=====================+# | adjust-properties() | | adjust-properties() |# +---------------------+ | actualize-sources() |# +---------------------+## The 'compile-action' and 'link-action' classes are not defined here but in# builtin.jam modules. They are shown in the diagram to give the big picture.# Models a potential target. It can be converted into a Jam target and used in# building, if needed. However, it can be also dropped, which allows us to# search for different transformations and select only one.#class virtual-target{ import scanner ; import sequence ; import utility ; import virtual-target ; rule __init__ ( name # Target/project name. : project # Project to which this target belongs. ) { self.name = $(name) ; self.project = $(project) ; self.dependencies = ; } # Name of this target. # rule name ( ) { return $(self.name) ; } # Project of this target. # rule project ( ) { return $(self.project) ; } # Adds additional 'virtual-target' instances this one depends on. # rule depends ( d + ) { self.dependencies = [ sequence.merge $(self.dependencies) : [ sequence.insertion-sort $(d) ] ] ; } rule dependencies ( ) { return $(self.dependencies) ; } # Generates all the actual targets and sets up build actions for this # target. # # If 'scanner' is specified, creates an additional target with the same # location as the actual target, which will depend on the actual target and # be associated with a 'scanner'. That additional target is returned. See # the docs (#dependency_scanning) for rationale. Target must correspond to a # file if 'scanner' is specified. # # If scanner is not specified then the actual target is returned. # rule actualize ( scanner ? ) { local actual-name = [ actualize-no-scanner ] ; if ! $(scanner) { return $(actual-name) ; } else { # Add the scanner instance to the grist for name. local g = [ sequence.join [ utility.ungrist $(actual-name:G) ] $(scanner) : - ] ; local name = $(actual-name:G=$(g)) ; if ! $(self.made.$(name)) { self.made.$(name) = true ; DEPENDS $(name) : $(actual-name) ; actualize-location $(name) ; scanner.install $(scanner) : $(name) $(__name__) ; } return $(name) ; } }# private: (overridables) # Sets up build actions for 'target'. Should call appropriate rules and set # target variables. # rule actualize-action ( target ) { errors.error "method should be defined in derived classes" ; } # Sets up variables on 'target' which specify its location. # rule actualize-location ( target ) { errors.error "method should be defined in derived classes" ; } # If the target is a generated one, returns the path where it will be # generated. Otherwise, returns an empty list. # rule path ( ) { errors.error "method should be defined in derived classes" ; } # Returns the actual target name to be used in case when no scanner is # involved. # rule actual-name ( ) { errors.error "method should be defined in derived classes" ; }# implementation rule actualize-no-scanner ( ) { # In fact, we just need to merge virtual-target with # abstract-file-target as the latter is the only class derived from the # former. But that has been left for later. errors.error "method should be defined in derived classes" ; }}# Target corresponding to a file. The exact mapping for file is not yet# specified in this class. (TODO: Actually, the class name could be better...)## May be a source file (when no action is specified) or a derived file# (otherwise).## The target's grist is a concatenation of its project's location, action# properties (for derived targets) and, optionally, value identifying the main# target.#class abstract-file-target : virtual-target{ import project ; import regex ; import sequence ; import path ; import type ; import property-set ; import indirect ; rule __init__ ( name # Target's name. exact ? # If non-empty, the name is exactly the name created file # should have. Otherwise, the '__init__' method will add a # suffix obtained from 'type' by calling # 'type.generated-target-suffix'. : type ? # Target's type. : project : action ? ) { virtual-target.__init__ $(name) : $(project) ; self.type = $(type) ; self.action = $(action) ; if $(action) { $(action).add-targets $(__name__) ; if $(self.type) && ! $(exact) { _adjust-name $(name) ; } } } rule type ( ) { return $(self.type) ; } # Sets the path. When generating target name, it will override any path # computation from properties. # rule set-path ( path ) { self.path = [ path.native $(path) ] ; } # Returns the currently set action. # rule action ( ) { return $(self.action) ; } # Sets/gets the 'root' flag. Target is root if it directly corresponds to # some variant of a main target. # rule root ( set ? ) { if $(set) { self.root = true ; } return $(self.root) ; } # Gets or sets the subvariant which created this target. Subvariant is set # when target is brought into existance and is never changed after that. In # particular, if a target is shared by a subvariant, only the first is # stored. # rule creating-subvariant ( s ? # If specified, specifies the value to set, # which should be a 'subvariant' class # instance. ) { if $(s) && ! $(self.creating-subvariant) { self.creating-subvariant = $(s) ; } return $(self.creating-subvariant) ; } rule actualize-action ( target ) { if $(self.action) { $(self.action).actualize ; } } # Return a human-readable representation of this target. If this target has # an action, that is: # # { <action-name>-<self.name>.<self.type> <action-sources>... } # # otherwise, it is: # # { <self.name>.<self.type> } # rule str ( ) { local action = [ action ] ; local name-dot-type = [ sequence.join $(self.name) "." $(self.type) ] ; if $(action) { local sources = [ $(action).sources ] ; local action-name = [ $(action).action-name ] ; local ss ; for local s in $(sources) { ss += [ $(s).str ] ; } return "{" $(action-name)-$(name-dot-type) $(ss) "}" ; } else { return "{" $(name-dot-type) "}" ; } } rule less ( a ) { if [ str ] < [ $(a).str ] { return true ; } } rule equal ( a ) { if [ str ] = [ $(a).str ] { return true ; } }# private: rule actual-name ( ) { if ! $(self.actual-name) { local grist = [ grist ] ; local basename = [ path.native $(self.name) ] ; self.actual-name = <$(grist)>$(basename) ; } return $(self.actual-name) ; } # Helper to 'actual-name', above. Computes a unique prefix used to # distinguish this target from other targets with the same name creating # different files. # rule grist ( ) { # Depending on target, there may be different approaches to generating # unique prefixes. We generate prefixes in the form: # <one letter approach code> <the actual prefix> local path = [ path ] ; if $(path) { # The target will be generated to a known path. Just use the path # for identification, since path is as unique as it can get. return p$(path) ; } else { # File is either source, which will be searched for, or is not a # file at all. Use the location of project for distinguishing. local project-location = [ $(self.project).get location ] ; local location-grist = [ sequence.join [ regex.split $(project-location) "/" ] : "!" ] ; if $(self.action) { local ps = [ $(self.action).properties ] ; local property-grist = [ $(ps).as-path ] ; # 'property-grist' can be empty when 'ps' is an empty property # set. if $(property-grist) { location-grist = $(location-grist)/$(property-grist) ; } } return l$(location-grist) ; } } # Given the target name specified in constructor, returns the name which # should be really used, by looking at the <tag> properties. Tag properties # need to be specified as <tag>@rule-name. This makes Boost Build call the # specified rule with the target name, type and properties to get the new # name. If no <tag> property is specified or the rule specified by <tag> # returns nothing, returns the result of calling # virtual-target.add-prefix-and-suffix. # rule _adjust-name ( specified-name ) { local ps ; if $(self.action) { ps = [ $(self.action).properties ] ; } else { ps = [ property-set.empty ] ; } # We add ourselves to the properties so that any tag rule can get more # direct information about the target than just that available through # the properties. This is useful in implementing name changes based on
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -