📄 targets.jam
字号:
# 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
# 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) ] ;
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's possible
# that no targets are generated.
local rule generate-really ( property-set )
{
local best-alternatives = [ select-alternatives $(property-set) ] ;
if ! $(best-alternatives)
{
errors.error
"failed to build" [ full-name ]
"with properties" [ $(property-set).raw ]
"because no best-matching alternative could be found"
;
return [ property-set.empty ] ;
}
else
{
local result = [ $(best-alternatives).generate $(property-set) ] ;
# Now return virtual targets for the only alternative
return $(result) ;
}
}
rule rename ( new-name )
{
abstract-target.rename $(new-name) ;
for local a in $(self.alternatives)
{
$(a).rename $(new-name) ;
}
}
}
# Abstract target which refers to a source file.
# This is artificial creature; it's usefull so that sources to
# a target can be represented as list of abstract target instances.
class file-reference : abstract-target
{
import virtual-target ;
import property-set ;
import path ;
rule __init__ ( file : project )
{
abstract-target.__init__ $(file) : $(project) ;
}
rule generate ( properties )
{
return [ property-set.empty ]
[ virtual-target.from-file $(self.name)
: [ location ]
: $(self.project) ] ;
}
# Returns true if the referred file really exists;
rule exists ( )
{
location ;
return $(self.file-path) ;
}
# Returns the location of target. Needed by 'testing.jam'
rule location ( )
{
if ! $(self.file-location)
{
local source-location = [ $(self.project).get source-location ] ;
for local src-dir in $(source-location)
{
if ! $(self.file-location)
{
local location = [ path.root $(self.name) $(src-dir) ] ;
if [ CHECK_IF_FILE [ path.native $(location) ] ]
{
self.file-location = $(src-dir) ;
self.file-path = $(location) ;
}
}
}
}
return $(self.file-location) ;
}
}
if "--quiet" in [ modules.peek : ARGV ]
{
.quiet = true ;
}
# Given a target-reference, made in context of 'project',
# returns the abstract-target instance that is referred to, as well
# as properties explicitly specified for this reference.
rule resolve-reference ( target-reference : project )
{
# Separate target name from properties override
local split = [ MATCH "^([^<]*)(/(<.*))?$" : $(target-reference) ] ;
local id = $(split[1]) ;
local sproperties = ;
if $(split[3])
{
sproperties = [ property.make [ feature.split $(split[3]) ] ] ;
sproperties = [ feature.expand-composites $(sproperties) ] ;
}
# Find the target
local target = [ $(project).find $(id) ] ;
return $(target) [ property-set.create $(sproperties) ] ;
}
# Attempts to generate the target given by target reference, which
# can refer both to a main target or to a file.
# Returns a list consisting of
# - usage requirements
# - generated virtual targets, if any
rule generate-from-reference
( target-reference # Target reference
: project # Project where the reference is made
: property-set # Properties of the main target that
# makes the reference
)
{
local r = [ resolve-reference $(target-reference) : $(project) ] ;
local target = $(r[1]) ;
local sproperties = $(r[2]) ;
# Take properties which should be propagated and refine them
# with source-specific requirements.
local propagated = [ $(property-set).propagated ] ;
local rproperties = [ $(propagated).refine $(sproperties) ] ;
if $(rproperties[1]) = "@error"
{
errors.error
"When building" [ full-name ] " with properties " $(properties) :
"Invalid properties specified for " $(source) ":"
$(rproperties[2-]) ;
}
return [ $(target).generate $(rproperties) ] ;
}
# Given build request and requirements, return properties
# common to dependency build request and target build
# properties
rule common-properties ( build-request requirements )
{
# For optimization, we add free requirements directly,
# without using complex algorithsm.
# This gives the complex algorithm better chance of caching results.
local free = [ $(requirements).free ] ;
local non-free = [ property-set.create
[ $(requirements).base ] [ $(requirements).incidental ] ] ;
local key = .rp.$(build-request)-$(non-free) ;
if ! $($(key))
{
$(key) = [ common-properties2 $(build-request) $(non-free) ] ;
}
result = [ $($(key)).add-raw $(free) ] ;
}
rule common-properties2 ( build-request requirements )
{
# This guarantees that default properties are present
# in result, unless they are overrided by some requirement.
# FIXME: There is possibility that we've added <foo>bar, which is composite
# and expands to <foo2>bar2, but default value of <foo2> is not bar2,
# in which case it's not clear what to do.
#
build-request = [ $(build-request).add-defaults ] ;
# Featured added by 'add-default' can be composite and expand
# to features without default values -- so they are not added yet.
# It could be clearer/faster to expand only newly added properties
# but that's not critical.
build-request = [ $(build-request).expand ] ;
# Apply non-conditional requirements.
# There's a slight bug here: it's possible that conditional
# requirement change a value set by non-conditional requirements. This
# should be error, but we don't detect it yet.
local raw = [ $(build-request).raw ] ;
raw = [ property.refine $(raw) :
[ feature.expand [ $(requirements).non-conditional ] ] ] ;
# We've collected properties that surely must be present in common
# properties. We now try to figure out what other properties
# should be added in order to satisfy rules (4)-(6) from the docs.
local conditionals = [ $(requirements).conditional ] ;
local count = $(conditionals) and-once-more ;
local prev ;
local current = $(raw) ;
local ok ;
while $(count)
{
# Evaluate conditionals in context of current properties
local e = [ property.evaluate-conditionals-in-context $(conditionals)
: $(current) ] ;
if $(e) = $(prev)
{
# If we got the same result, we've found final properties.
count = ;
ok = true ;
}
else
{
# Oops, results of evaluation of conditionals has changes
# Also 'current' contains leftover from previous evaluation.
# Recompute 'current' using initial properties and conditional
# requirements.
prev = $(e) ;
current = [ property.refine $(raw) : [ feature.expand $(e) ] ] ;
}
count = $(count[2-]) ;
}
if ! $(ok)
{
errors.error "Can't evaluate conditional properties " $(conditionals) ;
}
return [ property-set.create $(current) ] ;
}
# Implements the most standard way of constructing main target
# alternative from sources. Allows sources to be either file or
# other main target and handles generation of those dependency
# targets.
class basic-target : abstract-target
{
import build-request ;
import virtual-target targets ;
import property-set ;
import set sequence errors ;
import "class" : new ;
import property feature ;
rule __init__ ( name : project
: sources * : requirements * :
default-build * : usage-requirements * )
{
abstract-target.__init__ $(name) : $(project) ;
self.sources = $(sources) ;
if ! $(requirements) {
requirements = [ property-set.empty ] ;
}
self.requirements = $(requirements) ;
if ! $(default-build)
{
default-build = [ property-set.empty ] ;
}
self.default-build = $(default-build) ;
if ! $(usage-requirements)
{
usage-requirements = [ property-set.empty ] ;
}
self.usage-requirements = $(usage-requirements) ;
if $(sources:G)
{
errors.error "gristed element in sources for" [ full-name ] ;
}
}
rule requirements ( )
{
return $(self.requirements) ;
}
rule default-build ( )
{
return $(self.default-build) ;
}
# Returns the alternative condition for this alternative, if
# the condition is satisfied by 'property-set'.
rule match ( property-set )
{
# The condition is composed of all base non-conditional properties.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -