diff --git a/doc/src/reference.xml b/doc/src/reference.xml index 8c45dfb05..59a03483b 100644 --- a/doc/src/reference.xml +++ b/doc/src/reference.xml @@ -856,6 +856,60 @@ path-constant DATA : data/a.txt ; + relevant + + + featuresrelevance + relevant + + + Allowed values: the name of any feature. + + + + This feature is used to indicate which other features are relevant for + a given target. It is usually not necessary to manage it explicitly, + as Boost.Build can deduce it in most cases. Features which are not + relevant will not affect target paths, and will not cause conflicts. + + + + A feature will be considered relevant if any of the following are true + + It is referenced by toolset.flags or toolset.uses-features + It is used by the requirements of a generator + It is a subfeature of a relevant feature + It has a subfeature which is relevant + It is a composite feature, and any composed feature is relevant + It affects target alternative selection for a main target + It is a propagated feature and is relevant for any dependency + It is relevant for any dependency created by the same main target + It is used in the condition of a conditional property and the corresponding value is relevant + It is explicitly named as relevent + + + + Relevant features cannot be automatically deduced in the following cases: + + Indirect conditionals. Solution: return properties of the form + <relevant>result-feature:<relevant>condition-feature + This isn't really a conditional, + although for most purposes it functions like one. In particular, it does not support + multiple comma-separated elements in the condition, and it does work correctly even + in contexts where conditional properties are not allowed + + Action rules that read properties. Solution: add toolset.uses-features + to tell Boost.Build that the feature is actually used. + + + Generators and targets that manipulate property-sets directly. + Solution: set <relevant> manually. + + + + + + @@ -2539,7 +2593,8 @@ exe a : a.cpp the directory bin unless this is overridden by the build-dir project attribute. Under bin is a path that depends on the properties used to build each target. This path is uniquely determined by - all non-free, non-incidental properties. For example, + all relevant + non-free, non-incidental properties. For example, given a property set containing: <toolset>gcc <toolset-gcc:version>4.6.1 <variant>debug <warnings>all <define>_DEBUG <include>/usr/local/include diff --git a/src/build/ac.jam b/src/build/ac.jam index 846965a03..718765649 100644 --- a/src/build/ac.jam +++ b/src/build/ac.jam @@ -316,5 +316,8 @@ rule check-library ( target : true-properties * : false-properties * ) { local instance = [ class.new check-library-worker $(target) : $(true-properties) : $(false-properties) ] ; - return @$(instance).check ; + return @$(instance).check + [ property.evaluate-conditional-relevance + $(true-properties) $(false-properties) + : [ configure.get-relevant-features ] ] ; } diff --git a/src/build/configure.jam b/src/build/configure.jam index 3f3f97034..b5d85c456 100644 --- a/src/build/configure.jam +++ b/src/build/configure.jam @@ -507,6 +507,11 @@ class configure-choose-worker } } } + rule all-properties ( ) + { + local i = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; + return $(self.props.$(i)) ; + } rule check ( properties * ) { local i = [ configure.find-builds $(self.message) : $(properties) @@ -542,7 +547,10 @@ rule check-target-builds ( target message ? : true-properties * : { local instance = [ new check-target-builds-worker $(target) $(message) : $(true-properties) : $(false-properties) ] ; - return @$(instance).check ; + return @$(instance).check + [ property.evaluate-conditional-relevance + $(true-properties) $(false-properties) + : [ configure.get-relevant-features ] ] ; } # Usage: @@ -556,7 +564,10 @@ rule choose ( message : * ) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) : $(10) : $(11) : $(12) : $(13) : $(14) : $(15) : $(16) : $(17) : $(18) : $(19) ] ; - return @$(instance).check ; + return @$(instance).check + [ property.evaluate-conditional-relevance + [ $(instance).all-properties ] + : [ configure.get-relevant-features ] ] ; } diff --git a/src/build/feature.jam b/src/build/feature.jam index c4f681867..d833d70e4 100644 --- a/src/build/feature.jam +++ b/src/build/feature.jam @@ -662,6 +662,10 @@ rule subfeature ( local f = [ utility.ungrist $(feature) ] ; feature $(f)-$(subfeature-name) : $(subvalues) : $(attributes) subfeature ; + # Features and subfeatures are always relevent as a group + .feature-dependencies.$(f) += $(f)-$(subfeature-name) ; + .feature-dependencies.$(f)-$(subfeature-name) += $(f) ; + # Now make sure the subfeature values are known. extend-subfeature $(feature) $(value-string) : $(subfeature) : $(subvalues) ; } @@ -692,6 +696,10 @@ rule compose ( composite-property : component-properties * ) errors.error composite property "$(composite-property)" cannot have itself as a component ; } $(composite-property).components = $(component-properties) ; + + # A composite feature is relevant if any composed feature is relevant + local component-features = [ sequence.transform utility.ungrist : $(component-properties:G) ] ; + .feature-dependencies.$(component-features) += [ utility.ungrist $(feature) ] ; } @@ -1161,6 +1169,41 @@ rule split ( property-set ) return $(result) ; } +# Returns all the features that also must be relevant when these features are relevant +rule expand-relevant ( features * ) +{ + local conditional ; + local result ; + for f in $(features) + { + # This looks like a conditional, even though it isn't really. + # (Free features can never be used in conditionals) + local split = [ MATCH "^(.*):(.*)$" : $(f) ] ; + if $(split) + { + local-dependencies.$(split[1]) += $(split[2]) ; + conditional += local-dependencies.$(split[1]) ; + } + else + { + result += $(f) ; + } + } + local queue = $(result) ; + while $(queue) + { + local added = [ set.difference + $(.feature-dependencies.$(queue)) + $(local-dependencies.$(queue)) + : $(result) ] ; + result += $(added) ; + queue = $(added) ; + } + # Clean up local map + $(conditional) = ; + return $(result) ; +} + # Tests of module feature. # diff --git a/src/build/generators.jam b/src/build/generators.jam index c26db7257..d00f5242c 100644 --- a/src/build/generators.jam +++ b/src/build/generators.jam @@ -167,8 +167,10 @@ class generator import utility ; import path ; import property ; + import property-set ; import sequence ; import set ; + import toolset ; import type ; import virtual-target ; @@ -236,6 +238,10 @@ class generator # Note that 'transform' here, is the same as 'for_each'. sequence.transform type.validate : $(self.source-types) ; sequence.transform type.validate : $(self.target-types) ; + + local relevant-for-generator = + [ sequence.transform utility.ungrist : $(requirements:G) ] ; + self.relevant-features = [ property-set.create $(relevant-for-generator) ] ; } ################# End of constructor ################# @@ -406,10 +412,10 @@ class generator } local result ; - if $(consumed) + if $(consumed[2]) { - result = [ construct-result $(consumed) : $(project) $(name) : - $(property-set) ] ; + result = [ construct-result $(consumed[2-]) : $(project) $(name) : + [ $(property-set).add $(consumed[1]) ] ] ; } if $(result) @@ -421,7 +427,11 @@ class generator generators.dout [ indent ] " FAILURE" ; } generators.dout ; - return $(result) ; + if $(result) + { + # Make sure that we propagate usage-requirements up the stack. + return [ $(result[1]).add $(consumed[1]) ] $(result[2-]) ; + } } # Constructs the dependency graph to be returned by this generator. @@ -443,6 +453,11 @@ class generator ) { local result ; + + local relevant = [ toolset.relevant $(self.rule-name) ] ; + relevant = [ $(relevant).add $(self.relevant-features) ] ; + property-set = [ $(property-set).add $(relevant) ] ; + # If this is a 1->1 transformation, apply it to all consumed targets in # order. if ! $(self.source-types[2]) && ! $(self.composing) @@ -458,7 +473,10 @@ class generator result += [ generated-targets $(consumed) : $(property-set) : $(project) $(name) ] ; } - return $(result) ; + if $(result) + { + return $(relevant) $(result) ; + } } # Determine target name from fullname (maybe including path components) @@ -576,6 +594,7 @@ class generator { local _consumed ; local missing-types ; + local usage-requirements ; if $(sources[2]) { @@ -588,6 +607,7 @@ class generator local temp = [ consume-directly $(sources) ] ; if $(temp[1]) { + usage-requirements = [ property-set.empty ] ; _consumed = $(temp[1]) ; } missing-types = $(temp[2-]) ; @@ -613,7 +633,7 @@ class generator # everything to the required type. There is no need to rerun it on # targets of different types. - # NOTE: ignoring usage requirements. + usage-requirements = $(transformed[1]) ; for local t in $(transformed[2-]) { if [ $(t).type ] in $(missing-types) @@ -623,7 +643,7 @@ class generator } } - return [ sequence.unique $(_consumed) ] ; + return $(usage-requirements) [ sequence.unique $(_consumed) ] ; } # Converts several files to consumable types. Called for composing @@ -638,10 +658,11 @@ class generator if ! $(self.source-types) { # Anything is acceptible - return $(sources) ; + return [ property-set.empty ] $(sources) ; } else { + local usage-requirements = [ property-set.empty ] ; local acceptible-types = [ sequence.unique [ sequence.transform type.all-derived : $(self.source-types) ] ] ; for local source in $(sources) @@ -661,13 +682,17 @@ class generator { generators.dout [ indent ] " failed to convert " $(source) ; } + else + { + usage-requirements = [ $(usage-requirements).add $(transformed[1]) ] ; + } } else { result += $(source) ; } } - return [ sequence.unique $(result) : stable ] ; + return $(usage-requirements) [ sequence.unique $(result) : stable ] ; } } diff --git a/src/build/property-set.jam b/src/build/property-set.jam index feb4fb42e..194b3e0bc 100644 --- a/src/build/property-set.jam +++ b/src/build/property-set.jam @@ -34,6 +34,7 @@ class property-set { import errors ; import feature ; + import modules ; import path ; import property ; import property-set ; @@ -86,6 +87,26 @@ class property-set return $(self.free) ; } + # Returns relevant base properties + rule base-relevant ( ) + { + if ! $(self.relevant-initialized) + { + init-relevant ; + } + return $(self.base-relevant) ; + } + + # Returns all relevant properties + rule relevant + { + if ! $(self.relevant-initialized) + { + init-relevant ; + } + return $(self.relevant) ; + } + # Returns dependency properties. # rule dependency ( ) @@ -215,7 +236,7 @@ class property-set { if ! $(self.as-path) { - self.as-path = [ property.as-path [ base ] ] ; + self.as-path = [ property.as-path [ base-relevant ] ] ; } return $(self.as-path) ; } @@ -345,6 +366,30 @@ class property-set self.base-initialized = true ; } + rule init-relevant ( ) + { + local relevant-features = [ get ] ; + relevant-features = [ feature.expand-relevant $(relevant-features) ] ; + relevant-features = <$(relevant-features)> ; + ignore-relevance = [ modules.peek property-set : .ignore-relevance ] ; + for local p in $(self.raw) + { + if $(ignore-relevance) || $(p:G) in $(relevant-features) + { + local att = [ feature.attributes $(p:G) ] ; + if ! ( incidental in $(att) ) + { + self.relevant += $(p) ; + if ! ( free in $(att) ) + { + self.base-relevant += $(p) ; + } + } + } + } + self.relevant-initialized = true ; + } + rule init-dependency ( ) { for local p in $(self.raw) @@ -369,7 +414,7 @@ class property-set # characters as well, e.g. free or indirect properties. Indirect # properties for example contain a full Jamfile path in their value # which on Windows file systems contains ':' as the drive separator. - if [ MATCH (:) : $(p:G=) ] || $(p:G) = + if ( [ MATCH (:) : $(p:G=) ] && ! ( free in [ feature.attributes $(p:G) ] ) ) || $(p:G) = { self.conditional += $(p) ; } @@ -382,6 +427,13 @@ class property-set } } +# This is a temporary measure to help users work around +# any problems. Remove it once we've verified that +# everything works. +if --ignore-relevance in [ modules.peek : ARGV ] +{ + .ignore-relevance = true ; +} # Creates a new 'property-set' instance for the given raw properties or returns # an already existing ones. diff --git a/src/build/property.jam b/src/build/property.jam index 4be08eeb7..c172bd253 100644 --- a/src/build/property.jam +++ b/src/build/property.jam @@ -70,7 +70,7 @@ rule evaluate-conditionals-in-context ( properties * : context * ) local indirect ; for local p in $(properties) { - if [ MATCH (:<) : $(p) ] + if [ MATCH (:<) : $(p) ] && ! free in [ feature.attributes $(p:G) ] { conditionals += $(p) ; } @@ -155,6 +155,36 @@ rule evaluate-conditionals-in-context ( properties * : context * ) } +# Returns properties indicating how the conditionals in +# properties affect feature relevance. If the optional argument cond +# is passed, it is treated as extra conditions for all properties. +# +rule evaluate-conditional-relevance ( properties * : cond * ) +{ + cond = [ sequence.transform utility.ungrist : $(cond:G) ] ; + local result ; + for local p in $(properties) + { + # Separate condition and property. + local s = [ MATCH ^(.*):(<.*) : $(p) ] ; + if ! $(s) || free in [ feature.attributes $(p:G) ] + { + local value = [ utility.ungrist $(p:G) ] ; + result += $(value):$(cond) ; + } + else + { + local condition = [ regex.split $(s[1]) "," ] ; + condition = [ MATCH ^!?(.*) : $(condition) ] ; + condition = [ sequence.transform utility.ungrist : $(condition:G) ] $(cond) ; + local value = [ utility.ungrist $(s[2]:G) ] ; + result += $(value):$(condition) ; + } + } + return [ sequence.unique $(result) ] ; +} + + rule expand-subfeatures-in-conditions ( properties * ) { local result ; diff --git a/src/build/targets.jam b/src/build/targets.jam index 0964b0d86..6ffc082a4 100644 --- a/src/build/targets.jam +++ b/src/build/targets.jam @@ -191,6 +191,7 @@ class project-target : abstract-target import property-set ; import set ; import sequence ; + import toolset ; import "class" : new ; rule __init__ ( name : project-module parent-project ? @@ -584,6 +585,8 @@ class project-target : abstract-target IMPORT $(parent-module) : $(user-rules) : $(this-module) : $(user-rules) ; EXPORT $(this-module) : $(user-rules) ; + + toolset.inherit-flags $(this-module) : $(parent-module) ; } } @@ -621,10 +624,11 @@ class main-target : abstract-target { import assert ; import feature ; - import print ; import property-set ; import sequence ; + import set ; import targets : start-building end-building ; + import utility ; rule __init__ ( name : project ) { @@ -719,6 +723,43 @@ class main-target : abstract-target } } + # Features are relevant here if they could affect alternative + # selection. That is, base, non-conditional properties that + # are not identical in all target alternatives. + rule relevant-features ( ) + { + if $(self.alternatives[2-]) + { + if $(self.relevant-features) + { + return $(self.relevant-features) ; + } + local all-properties ; + for t in $(self.alternatives) + { + local ps = [ $(t).requirements ] ; + ps = [ property-set.create [ $(ps).non-conditional ] ] ; + all-properties += [ $(ps).base ] ; + } + all-properties = [ sequence.unique $(all-properties) ] ; + local result ; + for t in $(self.alternatives) + { + local ps = [ $(t).requirements ] ; + ps = [ property-set.create [ $(ps).non-conditional ] ] ; + local properties = [ set.difference $(all-properties) : [ $(ps).base ] ] ; + result += $(properties:G) ; + } + result = [ sequence.transform utility.ungrist : [ sequence.unique $(result) ] ] ; + self.relevant-features = [ property-set.create $(result) ] ; + return $(self.relevant-features) ; + } + else + { + return [ property-set.empty ] ; + } + } + rule apply-default-build ( property-set ) { return [ targets.apply-default-build $(property-set) : @@ -735,11 +776,12 @@ class main-target : abstract-target start-building $(__name__) ; local all-property-sets = [ apply-default-build $(property-set) ] ; + local relevant = [ relevant-features ] ; local usage-requirements = [ property-set.empty ] ; local result ; for local p in $(all-property-sets) { - local r = [ generate-really $(p) ] ; + local r = [ generate-really [ $(p).add $(relevant) ] ] ; if $(r) { usage-requirements = [ $(usage-requirements).add $(r[1]) ] ; @@ -1317,6 +1359,15 @@ class basic-target : abstract-target local gur = $(result[1]) ; result = $(result[2-]) ; + # Relevant is automatically applied to usage requirements + # and only applies for propagated features + local relevant = [ propagated-relevant + [ $(gur).get ] + [ $(rproperties).get ] ] ; + gur = [ property-set.create + [ property.change [ $(gur).raw ] : ] + $(relevant) ] ; + if $(self.always) { for local t in $(result) @@ -1409,6 +1460,22 @@ class basic-target : abstract-target [ $(self.usage-requirements).evaluate-conditionals $(rproperties) ] ; + # Filter out non-propagated properties + local relevant ; + for local r in [ $(xusage-requirements).get ] + { + local check = [ MATCH "(.*):(.*)" : $(r) ] ; + if $(check) { check = $(check[2]) ; } + else { check = $(r) ; } + if propagated in [ feature.attributes <$(check)> ] + { + relevant += $(r) ; + } + } + xusage-requirements = [ property-set.create + [ property.change [ $(xusage-requirements).raw ] : ] + $(relevant) ] ; + # We generate all dependency properties and add them, as well as their # usage requirements, to the result. local extra ; @@ -1448,6 +1515,19 @@ class basic-target : abstract-target return [ $(result).add [ property-set.create $(raw) ] ] ; } + local rule propagated-relevant ( values * ) + { + local result ; + for local v in [ feature.expand-relevant $(values) ] + { + if propagated in [ feature.attributes <$(v)> ] + { + result += $(v) ; + } + } + return $(result) ; + } + # 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 @@ -1594,7 +1674,8 @@ rule main-target-requirements ( import errors ; errors.error "Conflicting requirements for target:" $(requirements) ; } - return [ $(requirements).add [ toolset.requirements ] ] ; + local result = [ $(requirements).add [ toolset.requirements ] ] ; + return [ $(result).add-raw [ property.evaluate-conditional-relevance [ $(result).raw ] ] ] ; } @@ -1617,7 +1698,10 @@ rule main-target-usage-requirements ( $(specification) : [ $(project).project-module ] [ $(project).get location ] ] ; - return [ $(project-usage-requirements).add $(usage-requirements) ] ; + local result = [ $(project-usage-requirements).add $(usage-requirements) ] ; + local relevant = + [ property.evaluate-conditional-relevance [ $(result).raw ] ] ; + return [ $(result).add-raw $(relevant) ] ; } diff --git a/src/build/toolset.jam b/src/build/toolset.jam index a942cd906..d5b326488 100644 --- a/src/build/toolset.jam +++ b/src/build/toolset.jam @@ -19,6 +19,7 @@ import set ; import property-set ; import order ; import "class" : new ; +import utility ; .flag-no = 1 ; @@ -76,6 +77,36 @@ rule pop-checking-for-flags-module ( ) } +# Specifies features that are referenced by the action rule. +# This is necessary in order to detect that these features +# are relevant. +# +rule uses-features ( rule-or-module : features * : unchecked ? ) +{ + local caller = [ CALLER_MODULE ] ; + if ! [ MATCH ".*([.]).*" : $(rule-or-module) ] + && [ MATCH "(Jamfile<.*)" : $(caller) ] + { + # Unqualified rule name, used inside Jamfile. Most likely used with + # 'make' or 'notfile' rules. This prevents setting flags on the entire + # Jamfile module (this will be considered as rule), but who cares? + # Probably, 'flags' rule should be split into 'flags' and + # 'flags-on-module'. + rule-or-module = $(caller).$(rule-or-module) ; + } + else + { + local module_ = [ MATCH "([^.]*).*" : $(rule-or-module) ] ; + if $(unchecked) != unchecked + && $(.flags-module-checking[1]) != unchecked + && $(module_) != $(caller) + { + errors.error "Module $(caller) attempted to set flags for module $(module_)" ; + } + } + .uses-features.$(rule-or-module) += $(features) ; +} + # Specifies the flags (variables) that must be set on targets under certain # conditions, described by arguments. # @@ -399,6 +430,34 @@ rule relevant-features ( rule-or-module ) } } +# Returns a list of all the features which were +# passed to uses-features. +local rule used-features ( rule-or-module ) +{ + if ! $(.used-features.$(rule-or-module)) + { + local result = $(.uses-features.$(rule-or-module)) ; + + # Strip away last dot separated part and recurse. + local next = [ MATCH ^(.+)\\.([^\\.])* : $(rule-or-module) ] ; + if $(next) + { + result += [ used-features $(next[1]) ] ; + } + result = [ sequence.unique $(result) ] ; + if $(result[1]) = "" + { + result = $(result) ; + } + .used-features.$(rule-or-module) = $(result) ; + return $(result) ; + } + else + { + return $(.used-features.$(rule-or-module)) ; + } +} + rule filter-property-set ( rule-or-module : property-set ) { local key = .filtered.property-set.$(rule-or-module).$(property-set) ; @@ -454,6 +513,23 @@ rule set-target-variables ( rule-or-module targets + : property-set ) } +# Returns a property-set indicating which features are relevant +# for the given rule. +# +rule relevant ( rule-name ) +{ + if ! $(.relevant-features-ps.$(rule-name)) + { + local features = [ sequence.transform utility.ungrist : + [ relevant-features $(rule-name) ] + [ used-features $(rule-name) ] ] ; + .relevant-features-ps.$(rule-name) = + [ property-set.create $(features) ] ; + } + return $(.relevant-features-ps.$(rule-name)) ; +} + + # Make toolset 'toolset', defined in a module of the same name, inherit from # 'base'. # 1. The 'init' rule from 'base' is imported into 'toolset' with full name. diff --git a/src/build/virtual-target.jam b/src/build/virtual-target.jam index 2d139bd7f..cb8128362 100644 --- a/src/build/virtual-target.jam +++ b/src/build/virtual-target.jam @@ -999,10 +999,8 @@ rule register ( target ) { 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 ] ] ; + local p1 = [ $(ps1).relevant ] ; + local p2 = [ $(ps2).relevant ] ; if $(p1) = $(p2) { result = $(t) ; diff --git a/src/tools/bison.jam b/src/tools/bison.jam index 0689d4bd8..96b86a327 100644 --- a/src/tools/bison.jam +++ b/src/tools/bison.jam @@ -4,8 +4,8 @@ import generators ; import feature ; +import toolset : flags ; import type ; -import property ; feature.feature bison.prefix : : free ; type.register Y : y ; @@ -17,16 +17,10 @@ rule init ( ) { } -rule bison ( dst dst_header : src : properties * ) -{ - local r = [ property.select bison.prefix : $(properties) ] ; - if $(r) - { - PREFIX_OPT on $(<) = -p $(r:G=) ; - } -} +flags bison.bison PREFIX ; +_ = " " ; actions bison { - bison $(PREFIX_OPT) -d -o $(<[1]) $(>) + bison -p$(_)$(PREFIX) -d -o $(<[1]) $(>) } diff --git a/src/tools/doxygen.jam b/src/tools/doxygen.jam index 0594e5363..19de6d0ec 100644 --- a/src/tools/doxygen.jam +++ b/src/tools/doxygen.jam @@ -274,6 +274,7 @@ rule translate-path ( path ) } } +toolset.uses-features doxygen.headers-to-doxyfile : "" ; # Generates a doxygen configuration file (doxyfile) given a set of C++ sources # and a property list that may contain features. @@ -321,6 +322,7 @@ rule headers-to-doxyfile ( target : sources * : properties * ) print.text $(text) : true ; } +toolset.uses-features doxygen.run : "" ; # Run Doxygen. See doxygen-action for a description of the strange properties of # this rule. @@ -406,6 +408,7 @@ rule collect ( target : source : properties * ) : doxygen.xml.path=$(native-path) ; } +toolset.uses-features doxygen.xml-to-boostbook : ; # Translate Doxygen XML into BoostBook. # diff --git a/src/tools/features/relevant-feature.jam b/src/tools/features/relevant-feature.jam new file mode 100644 index 000000000..f55bd7f4c --- /dev/null +++ b/src/tools/features/relevant-feature.jam @@ -0,0 +1,10 @@ +# Copyright 2017 Steven Watanabe +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Identifies relevant features. + +import feature ; + +feature.feature relevant : : incidental free ; diff --git a/src/tools/features/threadapi-feature.jam b/src/tools/features/threadapi-feature.jam index 1a2b0923d..0f9d42fa5 100644 --- a/src/tools/features/threadapi-feature.jam +++ b/src/tools/features/threadapi-feature.jam @@ -25,5 +25,5 @@ rule detect ( properties * ) local ps = [ property-set.create $(properties) ] ; local api = [ $(ps).get ] ; if ! $(api) { api = [ get-default $(ps) ] ; } - return $(api) ; + return $(api) threadapi:target-os ; } diff --git a/src/tools/gcc.jam b/src/tools/gcc.jam index 6ba56967e..e9e40aa5a 100644 --- a/src/tools/gcc.jam +++ b/src/tools/gcc.jam @@ -550,8 +550,8 @@ class gcc-pch-generator : pch-generator # Return result of base class and pch-file property as # usage-requirements. return - [ property-set.create $(pch-file) -Winvalid-pch ] - $(pch-file) + [ $(pch-file[1]).add-raw $(pch-file[2-]) -Winvalid-pch ] + $(pch-file[2-]) ; } diff --git a/src/tools/generators/archive-generator.jam b/src/tools/generators/archive-generator.jam index 88ef16559..57a46bf92 100644 --- a/src/tools/generators/archive-generator.jam +++ b/src/tools/generators/archive-generator.jam @@ -11,6 +11,7 @@ import generators ; # class archive-generator : generator { + import generators ; import property-set ; rule __init__ ( id composing ? : source-types + : target-types + @@ -56,9 +57,7 @@ class archive-generator : generator } } - usage-requirements = [ property-set.create $(usage-requirements) ] ; - - return $(usage-requirements) $(result) ; + return [ generators.add-usage-requirements $(result) : $(usage-requirements) ] ; } } diff --git a/src/tools/generators/lib-generator.jam b/src/tools/generators/lib-generator.jam index f520b6102..e4ba23e2c 100644 --- a/src/tools/generators/lib-generator.jam +++ b/src/tools/generators/lib-generator.jam @@ -54,8 +54,9 @@ class lib-generator : generator } property-set = [ $(property-set).add-raw LIB ] ; # Construct the target. - return [ generators.construct $(project) $(name) : $(actual-type) + local result = [ generators.construct $(project) $(name) : $(actual-type) : $(property-set) : $(sources) ] ; + return [ $(result[1]).add-raw link ] $(result[2-]) ; } } diff --git a/src/tools/generators/linking-generator.jam b/src/tools/generators/linking-generator.jam index 0c9d38f3e..2d905faf6 100644 --- a/src/tools/generators/linking-generator.jam +++ b/src/tools/generators/linking-generator.jam @@ -83,11 +83,12 @@ class linking-generator : generator local ur ; if $(result) { - ur = [ extra-usage-requirements $(result) : $(property-set) ] ; + ur = [ extra-usage-requirements $(result[2-]) : $(property-set) ] ; ur = [ $(ur).add [ property-set.create $(extra-xdll-paths) ] ] ; + ur = [ $(ur).add $(result[1]) ] ; } - return $(ur) $(result) ; + return $(ur) $(result[2-]) ; } rule extra-usage-requirements ( created-targets * : property-set ) diff --git a/src/tools/generators/searched-lib-generator.jam b/src/tools/generators/searched-lib-generator.jam index 174d137e3..dc451970d 100644 --- a/src/tools/generators/searched-lib-generator.jam +++ b/src/tools/generators/searched-lib-generator.jam @@ -38,7 +38,7 @@ class searched-lib-generator : generator local search = [ feature.get-values : $(properties) ] ; - local a = [ new null-action $(property-set) ] ; + local a = [ new null-action [ $(property-set).add-raw link ] ] ; local lib-name = [ feature.get-values : $(properties) ] ; lib-name ?= $(name) ; local t = [ new searched-lib-target $(lib-name) : $(project) @@ -47,7 +47,7 @@ class searched-lib-generator : generator # lib png : z : png ; # the 'z' target should be returned, so that apps linking to 'png' # will link to 'z', too. - return [ property-set.create $(search) ] + return [ property-set.create $(search) link ] [ virtual-target.register $(t) ] $(sources) ; } } diff --git a/src/tools/lex.jam b/src/tools/lex.jam index 75d641318..e85d1d1ad 100644 --- a/src/tools/lex.jam +++ b/src/tools/lex.jam @@ -5,8 +5,7 @@ import type ; import generators ; import feature ; -import property ; - +import toolset : flags ; feature.feature flex.prefix : : free ; type.register LEX : l ; @@ -18,14 +17,7 @@ rule init ( ) { } -rule lex ( target : source : properties * ) -{ - local r = [ property.select flex.prefix : $(properties) ] ; - if $(r) - { - PREFIX on $(<) = $(r:G=) ; - } -} +flags lex.lex PREFIX ; actions lex { diff --git a/src/tools/make.jam b/src/tools/make.jam index 40b59faf3..7c9a7ca68 100644 --- a/src/tools/make.jam +++ b/src/tools/make.jam @@ -17,6 +17,8 @@ import targets ; class make-target-class : basic-target { import "class" : new ; + import indirect ; + import toolset ; import type ; import virtual-target ; @@ -34,10 +36,11 @@ class make-target-class : basic-target # below. local m = [ MATCH ^@(.*) : $(action-name) ] ; - local a = [ new action $(source-targets) : $(m[1]) : $(property-set) ] ; + local relevant = [ toolset.relevant [ indirect.get-rule $(m[1]) ] ] ; + local a = [ new action $(source-targets) : $(m[1]) : [ $(property-set).add $(relevant) ] ] ; local t = [ new file-target $(self.name) exact : [ type.type $(self.name) ] : $(self.project) : $(a) ] ; - return [ property-set.empty ] [ virtual-target.register $(t) ] ; + return $(relevant) [ virtual-target.register $(t) ] ; } } diff --git a/src/tools/mpi.jam b/src/tools/mpi.jam index 1ccc54133..a4d29340e 100644 --- a/src/tools/mpi.jam +++ b/src/tools/mpi.jam @@ -595,6 +595,10 @@ feature mpi:processes : : free incidental ; # apply to mpi.capture output at the moment. # Redo this explicitly. toolset.flags mpi.capture-output ARGS ; +toolset.uses-features mpi.capture-output : + + ; + rule capture-output ( target : sources * : properties * ) { # Use the standard capture-output rule to run the tests diff --git a/src/tools/msvc.jam b/src/tools/msvc.jam index f096e64f4..9365a7e12 100644 --- a/src/tools/msvc.jam +++ b/src/tools/msvc.jam @@ -527,6 +527,7 @@ actions compile.rc $(.SETUP) $(.RC) -l 0x409 -U$(UNDEFS) -D$(DEFINES) -I"$(INCLUDES:W)" -fo "$(<:W)" "$(>:W)" } +toolset.uses-features msvc.link : ; rule link ( targets + : sources * : properties * ) { @@ -706,7 +707,7 @@ class msvc-pch-generator : pch-generator : $(pch-header) ] ; local pch-file ; - for local g in $(generated) + for local g in $(generated[2-]) { if [ type.is-derived [ $(g).type ] PCH ] { @@ -714,8 +715,8 @@ class msvc-pch-generator : pch-generator } } - return [ property-set.create $(pch-header) - $(pch-file) ] $(generated) ; + return [ $(generated[1]).add-raw $(pch-header) + $(pch-file) ] $(generated[2-]) ; } } @@ -878,7 +879,7 @@ local rule set-setup-command ( targets * : properties * ) if ! $($(key)) { properties = [ feature.expand $(properties) ] ; - properties = [ property.select : $(properties) ] ; + properties = [ property.select : $(properties) ] ; local ps = [ property-set.create $(properties) $(setup-options) ] ; local original = [ virtual-target.from-file $(setup-script) : [ path.pwd ] : $(.project) ] ; local action = [ new non-scanning-action $(original) : msvc.adjust-setup-command : $(ps) ] ; @@ -1422,8 +1423,8 @@ class msvc-linking-generator : linking-generator if $(result) { - local name-main = [ $(result[0]).name ] ; - local action = [ $(result[0]).action ] ; + local name-main = [ $(result[1]).name ] ; + local action = [ $(result[1]).action ] ; if [ $(property-set).get ] = "on" { diff --git a/src/tools/python.jam b/src/tools/python.jam index c9f6f4c25..0459f8575 100644 --- a/src/tools/python.jam +++ b/src/tools/python.jam @@ -1243,6 +1243,10 @@ local rule pyd-pythonpath ( source ) toolset.flags python.capture-output ARGS ; toolset.flags python.capture-output INPUT_FILES ; +toolset.uses-features python.capture-output : + + ; + rule capture-output ( target : sources * : properties * ) { # Setup up a proper DLL search path. Here, $(sources[1]) is a python module diff --git a/src/tools/stlport.jam b/src/tools/stlport.jam index ed0947ca5..4a08c8c9b 100644 --- a/src/tools/stlport.jam +++ b/src/tools/stlport.jam @@ -89,6 +89,9 @@ class stlport-target-class : basic-target local requirements ; requirements += $(self.version) ; + requirements += runtime-debugging ; + requirements += toolset ; + requirements += runtime-link ; self.requirements = [ property-set.create $(requirements) ] ; } diff --git a/src/tools/testing.jam b/src/tools/testing.jam index c7383cd03..a36258ed3 100644 --- a/src/tools/testing.jam +++ b/src/tools/testing.jam @@ -331,6 +331,8 @@ generators.register-standard testing.capture-output : EXE : RUN_OUTPUT ; # http://article.gmane.org/gmane.comp.lib.boost.build/6353). generators.register-standard testing.unit-test : EXE : UNIT_TEST ; +toolset.uses-features testing.expect-success : ; +toolset.uses-features testing.expect-failure : ; # The action rules called by generators. @@ -456,6 +458,9 @@ toolset.flags testing.capture-output ARGS ; toolset.flags testing.capture-output INPUT_FILES ; toolset.flags testing.capture-output LAUNCHER ; +toolset.uses-features testing.capture-output : + ; + if --remove-test-targets in [ modules.peek : ARGV ] { feature.set-default preserve-test-targets : off ; diff --git a/src/tools/xsltproc.jam b/src/tools/xsltproc.jam index b08089b92..f6bf1af98 100644 --- a/src/tools/xsltproc.jam +++ b/src/tools/xsltproc.jam @@ -151,6 +151,7 @@ IMPORT xsltproc : register-generator : : generators.register-xslt ; rule flags ( rulename ) { + toolset.uses-features $(rulename) : : unchecked ; toolset.flags $(rulename) XSL-PATH : : unchecked ; toolset.flags $(rulename) FLAGS : : unchecked ; } diff --git a/test/MockToolset.py b/test/MockToolset.py index aa280b83a..bc02bf8f5 100755 --- a/test/MockToolset.py +++ b/test/MockToolset.py @@ -214,8 +214,9 @@ generators.register-linker mock.link : LIB OBJ : EXE : mock ; generators.register-linker mock.link.dll : LIB OBJ : SHARED_LIB : mock ; generators.register-archiver mock.archive : OBJ : STATIC_LIB : mock ; -toolset.flags mock.compile INCLUDES ; -toolset.flags mock.compile DEFINES ; +toolset.flags mock.compile OPTIONS shared : -fPIC ; +toolset.flags mock.compile INCLUDES : ; +toolset.flags mock.compile DEFINES : ; actions compile.c { diff --git a/test/TestToolset.py b/test/TestToolset.py index 98bc7c82b..8915e78cc 100644 --- a/test/TestToolset.py +++ b/test/TestToolset.py @@ -60,7 +60,7 @@ def expand_properties(properties): result += ["target-os=" + default_target_os] return result -def compute_path(properties): +def compute_path(properties, target_type): path = "" if "variant=release" in properties: path += "/release" @@ -74,9 +74,9 @@ def compute_path(properties): path += "/cxxstd-latest-iso" if "link=static" in properties: path += "/link-static" - if "runtime-link=static" in properties: + if "runtime-link=static" in properties and target_type in ["exe"]: path += "/runtime-link-static" - if "strip=on" in properties: + if "strip=on" in properties and target_type in ["dll", "exe", "obj2"]: path += "/strip-on" if get_target_os(properties) != default_target_os: path += "/target-os-" + get_target_os(properties) @@ -96,16 +96,17 @@ def test_toolset(toolset, version, property_sets): for properties in property_sets: t.set_toolset(toolset + "-" + version, get_target_os(properties)) properties = adjust_properties(properties) - path = toolset.split("-")[0] + "-*" + version + compute_path(properties) + def path(t): + return toolset.split("-")[0] + "-*" + version + compute_path(properties, t) os.environ["B2_PROPERTIES"] = " ".join(expand_properties(properties)) t.run_build_system(["--user-config="] + properties) - t.expect_addition("bin/%s/lib.obj" % (path)) + t.expect_addition("bin/%s/lib.obj" % (path("obj"))) if "link=static" not in properties: - t.expect_addition("bin/%s/l1.dll" % (path)) + t.expect_addition("bin/%s/l1.dll" % (path("dll"))) else: - t.expect_addition("bin/%s/l1.lib" % (path)) - t.expect_addition("bin/%s/main.obj" % (path)) - t.expect_addition("bin/%s/test.exe" % (path)) + t.expect_addition("bin/%s/l1.lib" % (path("lib"))) + t.expect_addition("bin/%s/main.obj" % (path("obj2"))) + t.expect_addition("bin/%s/test.exe" % (path("exe"))) t.expect_nothing_more() t.rm("bin") diff --git a/test/command_line_properties.py b/test/command_line_properties.py index a69bf1282..ebb186ea4 100644 --- a/test/command_line_properties.py +++ b/test/command_line_properties.py @@ -63,8 +63,8 @@ def test_free(): actions run { echo $(OPTIONS) > $(<) } ''') t.run_build_system(['f1=x,/:-']) - t.expect_content("bin/*/output1.txt", "x,/:-") - t.expect_content("bin/*/output2.txt", "x,/:-") + t.expect_content("bin*/output1.txt", "x,/:-") + t.expect_content("bin*/output2.txt", "x,/:-") t.cleanup() def test_subfeature(): diff --git a/test/custom_generator.py b/test/custom_generator.py index f98a46878..00860f643 100644 --- a/test/custom_generator.py +++ b/test/custom_generator.py @@ -61,6 +61,6 @@ t.write("r.rcc", """ """) t.run_build_system() -t.expect_content("bin/$toolset/debug*/r.obj", "rc-object") +t.expect_content("bin/r.obj", "rc-object") t.cleanup() diff --git a/test/example_make.py b/test/example_make.py index e65158ec2..d72423cb2 100644 --- a/test/example_make.py +++ b/test/example_make.py @@ -13,5 +13,5 @@ import sys t = BoostBuild.Tester(['example.python.interpreter=%s' % sys.executable]) t.set_tree("../example/make") t.run_build_system() -t.expect_addition(["bin/$toolset/debug*/main.cpp"]) +t.expect_addition(["bin/main.cpp"]) t.cleanup() diff --git a/test/feature_relevant.py b/test/feature_relevant.py new file mode 100644 index 000000000..4e7a0c451 --- /dev/null +++ b/test/feature_relevant.py @@ -0,0 +1,142 @@ +#!/usr/bin/python + +# Copyright 2018 Steven Watanabe +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Tests the feature + +import BoostBuild + +t = BoostBuild.Tester(use_test_config=False) + +t.write("xxx.jam", """ +import type ; +import feature : feature ; +import toolset : flags ; +import generators ; +type.register XXX : xxx ; +type.register YYY : yyy ; +feature xxxflags : : free ; +generators.register-standard xxx.run : YYY : XXX ; +# xxxflags is relevant because it is used by flags +flags xxx.run OPTIONS : ; +actions run +{ + echo okay > $(<) +} +""") + +t.write("zzz.jam", """ +import xxx ; +import type ; +import feature : feature ; +import generators ; +type.register ZZZ : zzz ; +feature zzz.enabled : off on : propagated ; +# zzz.enabled is relevant because it is used in the generator's +# requirements +generators.register-standard zzz.run : XXX : ZZZ : on ; +actions run +{ + echo okay > $(<) +} +""") + +t.write("aaa.jam", """ +import zzz ; +import type ; +import feature : feature ; +import generators ; +import toolset : flags ; +type.register AAA : aaa ; +feature aaaflags : : free ; +generators.register-standard aaa.run : ZZZ : AAA ; +flags aaa.run OPTIONS : ; +actions run +{ + echo okay > $(<) +} +""") + +t.write("Jamroot.jam", """ +import xxx ; +import zzz ; +import aaa ; +import feature : feature ; + +# f1 is relevant, because it is composite and is relevant +feature f1 : n y : composite propagated ; +feature.compose y : -no1 ; +# f2 is relevant, because it is used in a conditional +feature f2 : n y : propagated ; +# f3 is relevant, because it is used to choose the target alternative +feature f3 : n y : propagated ; +# f4 is relevant, because it is marked as such explicitly +feature f4 : n y : propagated ; +# f5 is relevant because of the conditional usage-requirements +feature f5 : n y : propagated ; +# f6 is relevant because the indirect conditional indicates so +feature f6 : n y : propagated ; +# f7 is relevant because the icond7 says so +feature f7 : n y : propagated ; + +# The same as f[n], except not propagated +feature g1 : n y : composite ; +feature.compose y : -no1 ; +feature g2 : n y ; +feature g3 : n y ; +feature g4 : n y ; +feature g5 : n y ; +feature g6 : n y ; +feature g7 : n y ; + +project : default-build + y y y y y y y + y y y y y y y on ; + +rule icond6 ( properties * ) +{ + local result ; + if y in $(properties) || y in $(properties) + { + result += -yes6 ; + } + return $(result) + xxxflags:f6 + xxxflags:g6 ; +} + +rule icond7 ( properties * ) +{ + local result ; + if y in $(properties) || y in $(properties) + { + result += -yes7 ; + } + return $(result) + aaaflags:f7 + aaaflags:g7 ; +} + +zzz out : in.yyy + : y:-no2 y:-no2 f4 g4 + @icond6 + : + : y:-yes5 y:-yes5 @icond7 + ; +alias out : : n ; +alias out : : n ; +# Features that are relevant for out are also relevant for check-propagate +aaa check-propagate : out ; +""") + +t.write("in.yyy", "") + +t.run_build_system() +t.expect_addition("bin/f1-y/f2-y/f3-y/f4-y/f6-y/g1-y/g2-y/g3-y/g4-y/g6-y/out.xxx") +t.expect_addition("bin/f1-y/f2-y/f3-y/f4-y/f6-y/g1-y/g2-y/g3-y/g4-y/g6-y/zzz.enabled-on/out.zzz") +t.expect_addition("bin/f1-y/f2-y/f3-y/f4-y/f5-y/f6-y/f7-y/zzz.enabled-on/check-propagate.aaa") + +t.cleanup() diff --git a/test/gcc_runtime.py b/test/gcc_runtime.py index 28b6410a5..76c95e1af 100644 --- a/test/gcc_runtime.py +++ b/test/gcc_runtime.py @@ -20,9 +20,8 @@ t.expect_output_lines("warning: On gcc, DLLs can not be built with " t.expect_nothing_more() t.run_build_system(["link=static", "runtime-link=static"]) -binFolder = "bin/$toolset/debug*/link-static/runtime-link-static" -t.expect_addition("%s/hello.obj" % binFolder) -t.expect_addition("%s/hello.lib" % binFolder) +t.expect_addition("bin/$toolset/debug*/link-static/hello.obj") +t.expect_addition("bin/$toolset/debug*/link-static/hello.lib") t.expect_nothing_more() t.cleanup() diff --git a/test/generator_selection.py b/test/generator_selection.py index 64f9cc7b3..1ecca7100 100755 --- a/test/generator_selection.py +++ b/test/generator_selection.py @@ -87,9 +87,9 @@ my-obj other-obj : source.extension ; t.run_build_system() t.expect_output_lines("Generating a CPP file...") - t.expect_addition("bin/$toolset/debug*/dummy.my_obj") - t.expect_addition("Other/bin/$toolset/debug*/other-obj.cpp") - t.expect_addition("Other/bin/$toolset/debug*/other-obj.my_obj") + t.expect_addition("bin/dummy.my_obj") + t.expect_addition("Other/bin/other-obj.cpp") + t.expect_addition("Other/bin/other-obj.my_obj") t.expect_nothing_more() t.cleanup() @@ -139,8 +139,8 @@ yyy other : source.xxx2 ; """) t.run_build_system() - t.expect_addition("bin/$toolset/debug*/dummy.yyy") - t.expect_addition("Other/bin/$toolset/debug*/other.yyy") + t.expect_addition("bin/dummy.yyy") + t.expect_addition("Other/bin/other.yyy") t.expect_nothing_more() t.cleanup() diff --git a/test/generators_test.py b/test/generators_test.py index 7d0997404..a29a3a538 100644 --- a/test/generators_test.py +++ b/test/generators_test.py @@ -215,17 +215,17 @@ nm-exe e : e.cpp ; """) t.run_build_system() - t.expect_addition("bin/$toolset/debug*/" * BoostBuild.List("a.my_exe " + t.expect_addition("bin/" * BoostBuild.List("a.my_exe " "a.my_obj b.my_obj c.tui_h c.cpp c.my_obj d_parser.whl d_lexer.dlp " "d_parser.cpp d_lexer.cpp d_lexer.my_obj d_parser.lr0 d_parser.h " "d_parser.my_obj d_parser_symbols.h x.c x.my_obj y.x1 y.x2 y.cpp " "y.my_obj e.marked_cpp e.positions e.target_cpp e.my_obj e.my_exe " "f.my_exe obj_1.my_obj obj_2.my_obj")) - t.expect_addition("lib/bin/$toolset/debug*/" * BoostBuild.List("c.my_obj " + t.expect_addition("lib/bin/" * BoostBuild.List("c.my_obj " "auxilliary.my_lib")) t.expect_nothing_more() - folder = "bin/$toolset/debug*" + folder = "bin" t.expect_content_lines("%s/obj_1.my_obj" % folder, " Sources: 'z.cpp'") t.expect_content_lines("%s/obj_2.my_obj" % folder, " Sources: 'z.cpp'") t.expect_content_lines("%s/a.my_obj" % folder, " Sources: 'a.cpp'") @@ -311,7 +311,7 @@ ddd _xxx : _xxx._a ; def suffix(rename): if rename: return "_x" return "" - name = "bin/$toolset/debug*/_xxx" + name = "bin/_xxx" e = t.expect_addition e("%s%s._b1" % (name, suffix(rename1))) e("%s%s._b2" % (name, suffix(rename2))) diff --git a/test/inline.py b/test/inline.py index d0ce91ae8..03d91a5d0 100644 --- a/test/inline.py +++ b/test/inline.py @@ -21,12 +21,11 @@ int main() {} t.write("helper.cpp", "void helper() {}\n") t.run_build_system() -t.expect_addition("bin/$toolset/debug/link-static*/a__helper.lib") -t.rm("bin/$toolset/debug/link-static/a__helper.lib") -t.rm("bin/$toolset/debug/link-static/*/a__helper.lib") +t.expect_addition("bin/$toolset/debug*/a__helper.lib") +t.rm("bin/$toolset/debug*/a__helper.lib") t.run_build_system(["a__helper"]) -t.expect_addition("bin/$toolset/debug/link-static*/a__helper.lib") +t.expect_addition("bin/$toolset/debug*/a__helper.lib") t.rm("bin") @@ -41,8 +40,8 @@ exe a2 : a.cpp [ lib helper : helper.cpp ] ; t.run_build_system() t.expect_addition("bin/$toolset/debug/link-static*/a.exe") -t.expect_addition("bin/$toolset/debug/link-static*/a__helper.lib") -t.expect_addition("bin/$toolset/debug/link-static*/a2__helper.lib") +t.expect_addition("bin/$toolset/debug*/a__helper.lib") +t.expect_addition("bin/$toolset/debug*/a2__helper.lib") # Check that the 'alias' target does not change the name of inline targets, and @@ -58,6 +57,6 @@ t.run_build_system() t.expect_nothing_more() t.run_build_system(["a"]) -t.expect_addition("bin/$toolset/debug/link-static*/helper.lib") +t.expect_addition("bin/$toolset/debug*/helper.lib") t.cleanup() diff --git a/test/make_rule.py b/test/make_rule.py index 4a2e09ad9..ab994376e 100644 --- a/test/make_rule.py +++ b/test/make_rule.py @@ -28,8 +28,8 @@ make foo.bar : : creator : 12345678 ; """) t.run_build_system() -t.expect_addition("bin/$toolset/debug*/foo.bar") -t.fail_test(string.find(t.read("bin/$toolset/debug*/foo.bar"), "12345678") == -1) +t.expect_addition("bin/foo.bar") +t.fail_test(string.find(t.read("bin/foo.bar"), "12345678") == -1) # Regression test. Make sure that if a main target is requested two times, and diff --git a/test/project-test3/jamroot.jam b/test/project-test3/jamroot.jam index 3d4dfa19a..d7cd490eb 100644 --- a/test/project-test3/jamroot.jam +++ b/test/project-test3/jamroot.jam @@ -6,6 +6,7 @@ import os ; import gcc ; import property ; +import toolset ; rule properties-as-path ( properties * ) { @@ -21,6 +22,9 @@ rule properties-as-path ( properties * ) [ property.remove incidental : $(r) ] ] ; } +toolset.flags yfc-compile KNOWN-PROPERTIES : ; +toolset.flags yfc-link KNOWN-PROPERTIES : ; + rule yfc-compile ( target : sources * : property-set * ) { PROPERTIES on $(target) = [ properties-as-path $(property-set) ] ; diff --git a/test/project-test4/jamroot.jam b/test/project-test4/jamroot.jam index fbbe0abf1..d8cf571ae 100644 --- a/test/project-test4/jamroot.jam +++ b/test/project-test4/jamroot.jam @@ -5,6 +5,7 @@ import os ; import gcc ; import property ; +import toolset ; rule properties-as-path ( properties * ) { @@ -21,6 +22,10 @@ rule properties-as-path ( properties * ) } +toolset.flags yfc-compile KNOWN-PROPERTIES : ; +toolset.flags yfc-link KNOWN-PROPERTIES : ; + + rule yfc-compile ( target : sources * : property-set * ) { PROPERTIES on $(target) = [ properties-as-path $(property-set) ] ; @@ -60,4 +65,4 @@ if [ os.name ] = VMS } } -IMPORT $(__name__) : yfc-compile yfc-link : : yfc-compile yfc-link ; +#IMPORT $(__name__) : yfc-compile yfc-link : : yfc-compile yfc-link ; diff --git a/test/project_id.py b/test/project_id.py index 7f4070e07..6477f5957 100755 --- a/test/project_id.py +++ b/test/project_id.py @@ -98,7 +98,7 @@ project /project-a3 ; """) t.run_build_system() - t.expect_addition("bin/$toolset/b%d._b" % x for x in range(1, 8)) + t.expect_addition("bin/b%d._b" % x for x in range(1, 8)) t.expect_nothing_more() t.cleanup() @@ -280,7 +280,7 @@ bbb b-invalid-target : /foo//invalid ; """) t.run_build_system(["b1", "b2"]) - t.expect_addition("bin/$toolset/debug*/b%d._b" % x for x in range(1, 3)) + t.expect_addition("bin/b%d._b" % x for x in range(1, 3)) t.expect_nothing_more() t.run_build_system(["b-invalid"], status=1) diff --git a/test/project_root_rule.py b/test/project_root_rule.py index 956c8953b..503b3cad2 100644 --- a/test/project_root_rule.py +++ b/test/project_root_rule.py @@ -29,6 +29,6 @@ my-lib foo ; t.run_build_system(subdir="sub") -t.expect_addition("sub/bin/$toolset/debug/link-static*/foo.lib") +t.expect_addition("sub/bin/$toolset/debug*/foo.lib") t.cleanup() diff --git a/test/remove_requirement.py b/test/remove_requirement.py index 8009e0f64..6efd44116 100644 --- a/test/remove_requirement.py +++ b/test/remove_requirement.py @@ -12,6 +12,8 @@ t = BoostBuild.Tester(use_test_config=False) t.write("jamroot.jam", """ project : requirements multi debug:static ; +# Force link to be relevant +project : requirements shared:TEST_DLL ; build-project sub ; build-project sub2 ; diff --git a/test/rescan_header.py b/test/rescan_header.py index 37b37c7d4..1257a223c 100755 --- a/test/rescan_header.py +++ b/test/rescan_header.py @@ -35,7 +35,7 @@ obj test : test.cpp : header3.h ; """) t.run_build_system(["-j2"]) -t.expect_addition("bin/$toolset/debug*/header3.h") +t.expect_addition("bin/header3.h") t.expect_addition("bin/$toolset/debug*/test.obj") t.expect_nothing_more() @@ -72,9 +72,9 @@ obj test : test.cpp : """) t.run_build_system(["-j2", "test"]) -t.expect_addition("bin/$toolset/debug*/header1.h") -t.expect_addition("bin/$toolset/debug*/header2.h") -t.expect_addition("bin/$toolset/debug*/header3.h") +t.expect_addition("bin/header1.h") +t.expect_addition("bin/header2.h") +t.expect_addition("bin/header3.h") t.expect_addition("bin/$toolset/debug*/test.obj") t.expect_nothing_more() @@ -122,9 +122,9 @@ obj test : test.cpp : """) t.run_build_system(["-j2", "test"]) -t.expect_addition("bin/$toolset/debug*/header1.h") -t.expect_addition("bin/$toolset/debug*/header2.h") -t.expect_addition("bin/$toolset/debug*/header3.h") +t.expect_addition("bin/header1.h") +t.expect_addition("bin/header2.h") +t.expect_addition("bin/header3.h") t.expect_addition("bin/$toolset/debug*/test.obj") t.expect_nothing_more() @@ -184,7 +184,7 @@ exe test : test2.cpp test1.cpp : header3.h ; """) t.run_build_system(["-j2", "test"]) -t.expect_addition("bin/$toolset/debug*/header3.h") +t.expect_addition("bin/header3.h") t.expect_addition("bin/$toolset/debug*/test1.obj") t.expect_addition("bin/$toolset/debug*/test2.obj") t.expect_addition("bin/$toolset/debug*/test.exe") @@ -192,7 +192,7 @@ t.expect_nothing_more() t.touch("header3.in") t.run_build_system(["-j2", "test"]) -t.expect_touch("bin/$toolset/debug*/header3.h") +t.expect_touch("bin/header3.h") t.expect_touch("bin/$toolset/debug*/test1.obj") t.expect_touch("bin/$toolset/debug*/test2.obj") t.expect_touch("bin/$toolset/debug*/test.exe") @@ -256,7 +256,7 @@ exe test : test2.cpp test1.cpp : header2.h . ; """) t.run_build_system(["-j2", "test"]) -t.expect_addition("bin/$toolset/debug*/header2.h") +t.expect_addition("bin/header2.h") t.expect_addition("bin/$toolset/debug*/test1.obj") t.expect_addition("bin/$toolset/debug*/test2.obj") t.expect_addition("bin/$toolset/debug*/test.exe") diff --git a/test/source_order.py b/test/source_order.py index d3cc2ab20..f21710a8c 100755 --- a/test/source_order.py +++ b/test/source_order.py @@ -74,8 +74,8 @@ t.write("file2.c", "") t.write("file3.c", "") t.run_build_system() -t.expect_addition("bin/$toolset/debug*/check.order-test") -t.expect_content("bin/$toolset/debug*/check.order-test", """\ +t.expect_addition("bin/check.order-test") +t.expect_content("bin/check.order-test", """\ file2.c file1.c file3.c diff --git a/test/space_in_path.py b/test/space_in_path.py index f4c6c579a..7f0c041a3 100755 --- a/test/space_in_path.py +++ b/test/space_in_path.py @@ -36,7 +36,7 @@ os.environ["TMPDIR"] = tmpdir; # *nix try: t.run_build_system(["has space"]) - t.expect_addition("has space/bin/$toolset/debug*/test.txt") + t.expect_addition("has space/bin/test.txt") t.expect_addition("has space/bin/$toolset/debug*/test.passed") finally: if oldtmp is not None: diff --git a/test/static_and_shared_library.py b/test/static_and_shared_library.py index da010a241..5b3a6b73a 100755 --- a/test/static_and_shared_library.py +++ b/test/static_and_shared_library.py @@ -31,7 +31,7 @@ t.expect_nothing_more() reset() t.run_build_system(["link=static"], subdir="lib") -t.expect_addition("lib/bin/$toolset/debug/link-static*/" * BoostBuild.List( +t.expect_addition("lib/bin/$toolset/debug*/" * BoostBuild.List( "c.obj auxilliary1.lib auxilliary2.lib")) t.expect_nothing_more() diff --git a/test/suffix.py b/test/suffix.py index b6946a48a..b31dd1730 100644 --- a/test/suffix.py +++ b/test/suffix.py @@ -73,6 +73,6 @@ second a : a.cpp ; """) t.run_build_system() -t.expect_addition("bin/$toolset/debug*/a") +t.expect_addition("bin/a") t.cleanup() diff --git a/test/tag.py b/test/tag.py index 87f537c8c..adf2fce6f 100644 --- a/test/tag.py +++ b/test/tag.py @@ -91,11 +91,11 @@ __declspec (dllexport) void x () {} BoostBuild.List("bin/$toolset/release*/a_rs.exe") + BoostBuild.List("bin/$toolset/release*/b_rs.dll") + BoostBuild.List("c/a_rs.exe") + - BoostBuild.List("bin/$toolset/debug/link-static*/a_dt.exe") + - BoostBuild.List("bin/$toolset/debug/link-static*/b_dt.lib") + + BoostBuild.List("bin/$toolset/debug*/a_dt.exe") + + BoostBuild.List("bin/$toolset/debug*/b_dt.lib") + BoostBuild.List("c/a_dt.exe") + - BoostBuild.List("bin/$toolset/release/link-static*/a_rt.exe") + - BoostBuild.List("bin/$toolset/release/link-static*/b_rt.lib") + + BoostBuild.List("bin/$toolset/release*/a_rt.exe") + + BoostBuild.List("bin/$toolset/release*/b_rt.lib") + BoostBuild.List("c/a_rt.exe")) variants = ["debug", "release", "link=static,shared"] diff --git a/test/test_all.py b/test/test_all.py index 591b11aae..d443ef207 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -222,6 +222,7 @@ tests = ["absolute_sources", "expansion", "explicit", "feature_cxxflags", + "feature_relevant", "generator_selection", "generators_test", "implicit_dependency",