📄 targets.jam
字号:
ECHO [ targets.indent ] "Build request: " $(property-set) [ $(property-set).raw ] ; local cf = [ build-system.command-line-free-features ] ; ECHO [ targets.indent ] "Command line free features: " [ $(cf).raw ] ; ECHO [ targets.indent ] "Target requirements: " [ $(self.requirements).raw ] ; } if ! $(self.generated.$(property-set)) { # Apply free features from the command line. If user said # define=FOO # he most likely wants this define to be set for all compiles. property-set = [ $(property-set).refine [ build-system.command-line-free-features ] ] ; local rproperties = [ targets.common-properties $(property-set) $(self.requirements) ] ; if [ modules.peek : .debug-building ] { ECHO ; ECHO [ targets.indent ] "Common properties: " [ $(rproperties).raw ] ; } if ( $(rproperties[1]) != "@error" ) && ( [ $(rproperties).get <build> ] != no ) { 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 ; ECHO [ targets.indent ] "Usage requirements for" $(self.name)": " $(usage-requirements) ; } rproperties = [ property-set.create $(properties) $(usage-requirements) ] ; usage-requirements = [ property-set.create $(usage-requirements) ] ; if [ modules.peek : .debug-building ] { ECHO [ targets.indent ] "Build properties: " [ $(rproperties).raw ] ; } local extra = [ $(rproperties).get <source> ] ; source-targets += $(extra:G=) ; # We might get duplicate sources, for example if we link to two # libraries having the same <library> usage requirement. source-targets = [ sequence.unique $(source-targets) ] ; local result = [ construct $(self.name) : $(source-targets) : $(rproperties) ] ; if $(result) { local gur = $(result[1]) ; result = $(result[2-]) ; local s = [ create-subvariant $(result) : [ virtual-target.recent-targets ] : $(property-set) : $(source-targets) : $(rproperties) : $(usage-requirements) ] ; virtual-target.clear-recent-targets ; local ur = [ compute-usage-requirements $(s) ] ; ur = [ $(ur).add $(gur) ] ; $(s).set-usage-requirements $(ur) ; if [ modules.peek : .debug-building ] { ECHO [ targets.indent ] "Usage requirements from" $(self.name)": " [ $(ur).raw ] ; } self.generated.$(property-set) = $(ur) $(result) ; } } else { if $(rproperties[1]) = "@error" { ECHO [ targets.indent ] "Skipping build of:" [ full-name ] "cannot compute common properties" ; } else if [ $(rproperties).get <build> ] = no { ECHO [ targets.indent ] "Skipping build of: " [ full-name ] " <build>no in common properties" ; } else { ECHO [ targets.indent ] "Skipping build of: " [ full-name ] " unknown reason" ; } # We are here either because there has been an error computing # properties or there is <build>no in properties. In the latter # case we do not want any diagnostic. In the former case, we # need diagnostics. FIXME # If this target fails to build, add <build>no to properties to # cause any parent target to fail to build. Except that it # - does not work now, since we check for <build>no only in # common properties, but not in properties that came from # dependencies # - it is not clear if that is a good idea anyway. The alias # target, for example, should not fail to build if a # dependency fails. self.generated.$(property-set) = [ property-set.create <build>no ] ; } } else { if [ modules.peek : .debug-building ] { ECHO [ targets.indent ] "Already built" ; local ur = $(self.generated.$(property-set)) ; ur = $(ur[0]) ; targets.increase-indent ; ECHO [ targets.indent ] "Usage requirements from" $(self.name)": " [ $(ur).raw ] ; targets.decrease-indent ; } } targets.decrease-indent ; return $(self.generated.$(property-set)) ; } # Given the set of generated targets, and refined build properties, # determines and sets appropriate usage requirements on those targets. # rule compute-usage-requirements ( subvariant ) { local rproperties = [ $(subvariant).build-properties ] ; xusage-requirements = [ targets.evaluate-requirements $(self.usage-requirements) : $(rproperties) : added ] ; # We generate all dependency properties and add them, as well as their # usage requirements, to the result. local extra ; generate-dependencies [ $(xusage-requirements).dependency ] : $(rproperties) : extra extra ; local result = [ property-set.create [ $(xusage-requirements).non-dependency ] $(extra) ] ; # Propagate usage requirements we got from sources, except for the # <pch-header> and <pch-file> features. # # That feature specifies which pch file to use, and should apply only to # direct dependents. Consider: # # pch pch1 : ... # lib lib1 : ..... pch1 ; # pch pch2 : # lib lib2 : pch2 lib1 ; # # Here, lib2 should not get <pch-header> property from pch1. # # Essentially, when those two features are in usage requirements, they # are propagated only to direct dependents. We might need a more general # mechanism, but for now, only those two features are special. # # TODO - Actually there are more possible candidates like for instance # when listing static library X as a source for another static library. # Then static library X will be added as a <source> property to the # second library's usage requirements but those requirements should last # only up to the first executable or shared library that actually links # to it. local raw = [ $(subvariant).sources-usage-requirements ] ; raw = [ $(raw).raw ] ; raw = [ property.change $(raw) : <pch-header> ] ; raw = [ property.change $(raw) : <pch-file> ] ; return [ $(result).add [ property-set.create $(raw) ] ] ; } # Creates new subvariant instances for 'targets'. # 'root-targets' - virtual targets to be returned to dependants # 'all-targets' - virtual targets created while building this main target # 'build-request' - property-set instance with requested build properties # local rule create-subvariant ( root-targets * : all-targets * : build-request : sources * : rproperties : usage-requirements ) { for local e in $(root-targets) { $(e).root true ; } # Process all virtual targets that will be created if this main target # is created. 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 virtual targets for this abstract target and the dependency # graph. Returns a usage-requirements property-set and a list of virtual # targets. Should be overriden 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:S=) : $(self.type) : [ property-set.create [ $(property-set).raw ] <main-target-type>$(self.type) ] : $(source-targets) ] ; if ! $(r) { ECHO "warn: Unable to construct" [ full-name ] ; # Are there any top-level generators for this type/property set. if ! [ generators.find-viable-generators $(self.type) : $(property-set) ] { ECHO "error: no generators were found for type '$(self.type)'" ; ECHO "error: and the requested properties" ; ECHO "error: make sure you've configured the needed tools" ; ECHO "See http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html" ; ECHO "To debug this problem, try the --debug-generators option." ; EXIT ; } } 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 the name of such targets are adjusted to be# '<name_of_this_target>__<name_of_source_target>'. Such renaming is disabled if# a non-empty value is passed as the 'no-renaming' parameter.#rule main-target-sources ( sources * : main-target-name : no-renaming ? ){ local result ; for local t in $(sources) { if [ class.is-instance $(t) ] { local name = [ $(t).name ] ; if ! $(no-renaming) { name = $(main-target-name)__$(name) ; $(t).rename $(name) ; } # Inline targets are not built by default. local p = [ $(t).project ] ; $(p).mark-target-as-explicit $(name) ; result += $(name) ; } else { result += $(t) ; } } return $(result) ;}# Returns the requirements to use when declaring a main target, obtained by# translating all specified property paths and refining project requirements# with the ones specified for the target.#rule main-target-requirements ( specification * # Properties explicitly specified for the main target. : project # Project where the main target is to be declared.){ specification += [ toolset.requirements ] ; local requirements = [ property-set.refine-from-user-input [ $(project).get requirements ] : $(specification) : [ $(project).project-module ] : [ $(project).get location ] ] ; if $(requirements[1]) = "@error" { errors.error "Conflicting requirements for target:" $(requirements) ; } return $(requirements) ;}# Returns the usage requirements to use when declaring 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 project-usage-requirements = [ $(project).get usage-requirements ] ; # We do not use 'refine-from-user-input' because: # - I am not sure if removing parent's usage requirements makes sense # - refining usage requirements is not needed, since usage requirements are # always free. local usage-requirements = [ property-set.create-from-user-input $(specification) : [ $(project).project-module ] [ $(project).get location ] ] ; return [ $(project-usage-requirements).add $(usage-requirements) ] ;}# Return the default build value to use when declaring a main target, which is# obtained by using the 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 alternative and returns it.#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 + -