📄 targets.jam
字号:
# It's not clear if we should expand 'self.requirements' or not.
# For one thing, it would be nice to be able to put
# <toolset>msvc-6.0
# in requirements.
# On the other hand, if we have <variant>release in condition it
# does not make sense to require <optimization>full to be in
# build request just to select this variant.
local bcondition = [ $(self.requirements).base ] ;
local ccondition = [ $(self.requirements).conditional ] ;
local condition = [ set.difference $(bcondition) : $(ccondition) ] ;
if $(condition) in [ $(property-set).raw ]
{
return $(condition) ;
}
else
{
return no-match ;
}
}
# Takes a target reference, which might be either target id
# or a dependency property, and generates that target using
# 'property-set' as build request.
#
# The results are added to to variable called 'result-var'.
# Usage requirements are added variable called 'usage-requirements-var'.
rule generate-dependencies ( dependencies * : property-set
: result-var usage-requirements-var )
{
for local dependency in $(dependencies)
{
local grist = $(dependency:G) ;
local id = $(dependency:G=) ;
local result =
[ targets.generate-from-reference $(id) : $(self.project)
: $(property-set) ] ;
$(result-var) += $(result[2-]:G=$(grist)) ;
$(usage-requirements-var) += [ $(result[1]).raw ] ;
}
}
# Determines final build properties, generates sources,
# and calls 'construct'. This method should not be
# overridden.
rule generate ( property-set )
{
if [ modules.peek : .debug-building ]
{
ECHO [ targets.indent ] "Building target '$(self.name)'" ;
ECHO [ targets.indent ] "Build request: " [ $(property-set).raw ] ;
targets.increase-indent ;
}
if ! $(self.generated.$(property-set))
{
local rproperties = [ targets.common-properties $(property-set)
$(self.requirements) ] ;
if [ modules.peek : .debug-building ]
{
ECHO [ targets.indent ] "Common properties are" [ $(rproperties).raw ] ;
}
if $(rproperties[1]) != "@error"
{
local source-targets ;
local properties = [ $(rproperties).non-dependency ] ;
local usage-requirements ;
generate-dependencies [ $(rproperties).dependency ]
: $(rproperties)
: properties usage-requirements ;
generate-dependencies $(self.sources) : $(rproperties)
: source-targets usage-requirements ;
if [ modules.peek : .debug-building ]
{
ECHO [ targets.indent ]
"Usage requirements for $(self.name) are $(usage-requirements)" ;
}
rproperties = [ property-set.create $(properties)
$(usage-requirements) ] ;
usage-requirements = [ property-set.create $(usage-requirements) ] ;
local extra = [ $(rproperties).get <source> ] ;
source-targets += $(extra:G=) ;
# We might get duplicate sources, for example if
# we link to two library which have the same <library> in
# usage requirements.
source-targets = [ sequence.unique $(source-targets) ] ;
local result =
[ construct $(self.name) :
$(source-targets) : $(rproperties) ] ;
local gur = $(result[1]) ;
result = $(result[2-]) ;
local s = [ create-subvariant $(result) : $(property-set) : $(source-targets)
: $(rproperties) : $(usage-requirements) ] ;
local ur = [ compute-usage-requirements $(s) ] ;
ur = [ $(ur).add $(gur) ] ;
$(s).set-usage-requirements $(ur) ;
self.generated.$(property-set) = $(ur) $(result) ;
}
else
{
self.generated.$(property-set) = $(rproperties) ;
}
}
else
{
if [ modules.peek : .debug-building ]
{
ECHO [ targets.indent ] "Already built" ;
}
}
targets.decrease-indent ;
return $(self.generated.$(property-set)) ;
}
# Given the set of generated targets, and refined build
# properties, determines and sets appripriate usage requirements
# on those targets.
rule compute-usage-requirements ( subvariant )
{
local rproperties = [ $(subvariant).build-properties ] ;
xusage-requirements = [ $(self.usage-requirements).evaluate-conditionals
$(rproperties) ] ;
# We generate all dependency properties and add them,
# as well as their usage requirements, to result.
local extra ;
generate-dependencies [ $(xusage-requirements).dependency ] :
$(rproperties) : extra extra ;
local result = [ property-set.create
[ $(xusage-requirements).non-dependency ] $(extra) ] ;
result = [ $(result).add
[ $(subvariant).sources-usage-requirements ] ] ;
return $(result) ;
}
# Creates a new subvariant-dg instances for 'targets'
local rule create-subvariant ( targets * : build-request : sources * :
rproperties
: usage-requirements )
{
for local e in $(targets)
{
$(e).root true ;
}
# Process all vtargets that will be created if this main target
# is created.
local all-targets =
[ sequence.transform virtual-target.traverse : $(targets) ] ;
local s = [ new subvariant $(__name__) : $(build-request) : $(sources)
: $(rproperties) : $(usage-requirements) : $(all-targets) ] ;
for local v in $(all-targets)
{
if ! [ $(v).creating-subvariant ]
{
$(v).creating-subvariant $(s) ;
}
}
return $(s) ;
}
# Constructs the virtual targets for this abstract targets and
# the dependecy graph. Returns the list of virtual targets.
# Should be overrided in derived classes.
rule construct ( name : source-targets * : properties * )
{
errors.error "method should be defined in derived classes" ;
}
}
class typed-target : basic-target
{
import generators ;
rule __init__ ( name : project : type
: sources * : requirements * : default-build * : usage-requirements * )
{
basic-target.__init__ $(name) : $(project)
: $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ;
self.type = $(type) ;
}
rule type ( )
{
return $(self.type) ;
}
rule construct ( name : source-targets * : property-set )
{
local r = [ generators.construct $(self.project) $(name) : $(self.type)
: [ property-set.create [ $(property-set).raw ] # [ feature.expand
<main-target-type>$(self.type) ]
# ]
: $(source-targets) ] ;
if ! $(r)
{
errors.error "unable to construct" [ full-name ] ;
}
return $(r) ;
}
}
# Return the list of sources to use, if main target rule is invoked
# with 'sources'. If there are any objects in 'sources', they are treated
# as main target instances, and WRITEME.
rule main-target-sources ( sources * : main-target-name )
{
local result ;
for local t in $(sources)
{
if [ class.is-instance $(t) ]
{
local name = [ $(t).name ] ;
# NOTE: on windows, this won't work if 'main-target-name'
# if single letter. But other alternatives are even worse.
local new-name = $(main-target-name)..$(name) ;
$(t).rename $(new-name) ;
#local p = [ $(t).project ] ;
#local pt = [ project.target $(p) ] ;
#$(pt).rename-main-target $(name) : $(new-name) ;
result += $(new-name) ;
}
else
{
result += $(t) ;
}
}
return $(result) ;
}
# Returns the requirement to use when declaring a main target,
# which are obtained by
# - translating all specified property paths, and
# - refining project requirements with the one specified for the target
rule main-target-requirements (
specification * # Properties explicitly specified for a main target
: project # Project where the main target is to be declared
)
{
local loc = [ $(project).get location ] ;
local jamfile-module = [ $(project).project-module ] ;
local requirements = [ property-set.create-from-user-input $(specification)
: $(jamfile-module) $(loc) ] ;
local project-requirements = [ $(project).get requirements ] ;
requirements = [ $(project-requirements).refine $(requirements) ] ;
if $(requirements[1]) = "@error"
{
errors.error "Conflicting requirements for target:" $(requirements) ;
}
return $(requirements) ;
}
# Returns the use requirement to use when declaraing a main target,
# which are obtained by
# - translating all specified property paths, and
# - adding project's usage requirements
rule main-target-usage-requirements (
specification * # Use-properties explicitly specified for a main target
: project # Project where the main target is to be declared
)
{
local loc = [ $(project).get location ] ;
local project-usage-requirements = [ $(project).get usage-requirements ] ;
local usage-requirements = [ property-set.create
[ property.translate-paths $(specification) : $(loc) ] ] ;
return [ $(project-usage-requirements).add $(usage-requirements) ] ;
}
# Return the default build value to use when declaring a main target,
# which is obtained by using specified value if not empty and parent's
# default build attribute otherwise.
rule main-target-default-build (
specification * # Default build explicitly specified for a main target
: project # Project where the main target is to be declared
)
{
local result ;
if $(specification)
{
result = $(specification) ;
}
else
{
result = [ $(project).get default-build ] ;
}
return [ property-set.create-with-validation $(result) ] ;
}
# Registers the specified target as a main target alternatives.
# Returns 'target'.
rule main-target-alternative ( target )
{
local ptarget = [ $(target).project ] ;
$(ptarget).add-alternative $(target) ;
return $(target) ;
}
# Creates a typed-target with the specified properties.
# The 'name', 'sources', 'requirements', 'default-build' and
# 'usage-requirements' are assumed to be in the form specified
# by the user in Jamfile corresponding to 'project'.
rule create-typed-target ( type : project :
name : sources * : requirements * : default-build *
: usage-requirements * )
{
return [
targets.main-target-alternative
[ new typed-target $(name) : $(project) : $(type)
: [ targets.main-target-sources $(sources) : $(name) ]
: [ targets.main-target-requirements $(requirements) : $(project) ]
: [ targets.main-target-default-build $(default-build) : $(project) ]
: [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
] ] ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -