mirror of
https://github.com/boostorg/build.git
synced 2026-02-17 01:32:12 +00:00
Implement feature relevance.
* New feature <relevant> which is automatically deduced in most cases. * Features which are not relevant do not affect target paths and do not prevent merging of virtual targets. * generators.jam: generator.run always returns usage-requirements to allow usage-requirements in non-top-level generators. This is necessary because we're using usage-requirements to track relevance from flags. * New rule toolset.uses-features to specify features that the rule checks manually, instead of using toolset.flags. In the future, we should consider restricting the properties actually passed, to detect errors. * Adjust tests to handle the new paths (verified by inspection). * Add temporary option --ignore-relevance to consider all features relevant to aid migration. * New rule property.evaluate-conditional-relevance which helps tracking relevance in <conditional>. * Widely scattered changes to use the new interfaces.
This commit is contained in:
@@ -856,6 +856,60 @@ path-constant DATA : data/a.txt ;
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry id="bbv2.reference.features.relevant"><term><literal>relevant</literal></term>
|
||||
<listitem>
|
||||
|
||||
<indexterm><primary>features</primary><secondary>relevance</secondary></indexterm>
|
||||
<indexterm><primary>relevant</primary></indexterm>
|
||||
|
||||
<para>
|
||||
<emphasis role="bold">Allowed values:</emphasis> the name of any feature.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
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.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A feature will be considered relevant if any of the following are true
|
||||
<itemizedlist>
|
||||
<listitem>It is referenced by <literal>toolset.flags</literal> or <literal>toolset.uses-features</literal></listitem>
|
||||
<listitem>It is used by the requirements of a generator</listitem>
|
||||
<listitem>It is a subfeature of a relevant feature</listitem>
|
||||
<listitem>It has a subfeature which is relevant</listitem>
|
||||
<listitem>It is a composite feature, and any composed feature is relevant</listitem>
|
||||
<listitem>It affects target alternative selection for a main target</listitem>
|
||||
<listitem>It is a propagated feature and is relevant for any dependency</listitem>
|
||||
<listitem>It is relevant for any dependency created by the same main target</listitem>
|
||||
<listitem>It is used in the condition of a conditional property and the corresponding value is relevant</listitem>
|
||||
<listitem>It is explicitly named as relevent</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>Relevant features cannot be automatically deduced in the following cases:</para>
|
||||
<itemizedlist>
|
||||
<listitem>Indirect conditionals. Solution: return properties of the form
|
||||
<literal><relevant>result-feature:<relevant>condition-feature</literal>
|
||||
<note><para>This isn't really a <link linkend="bbv2.reference.variants.propcond">conditional</link>,
|
||||
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</para></note></listitem>
|
||||
<listitem>
|
||||
<para>Action rules that read properties. Solution: add <literal>toolset.uses-features</literal>
|
||||
to tell Boost.Build that the feature is actually used.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Generators and targets that manipulate property-sets directly.
|
||||
Solution: set <literal><relevant></literal> manually.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
</variablelist>
|
||||
</section>
|
||||
@@ -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 <link linkend="bbv2.reference.features.relevant">relevant</link>
|
||||
non-free, non-incidental properties. For example,
|
||||
given a property set containing:
|
||||
<code><toolset>gcc <toolset-gcc:version>4.6.1 <variant>debug
|
||||
<warnings>all <define>_DEBUG <include>/usr/local/include
|
||||
|
||||
@@ -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 <conditional>@$(instance).check ;
|
||||
return <conditional>@$(instance).check
|
||||
[ property.evaluate-conditional-relevance
|
||||
$(true-properties) $(false-properties)
|
||||
: [ configure.get-relevant-features ] <link> ] ;
|
||||
}
|
||||
|
||||
@@ -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 <conditional>@$(instance).check ;
|
||||
return <conditional>@$(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 <conditional>@$(instance).check ;
|
||||
return <conditional>@$(instance).check
|
||||
[ property.evaluate-conditional-relevance
|
||||
[ $(instance).all-properties ]
|
||||
: [ configure.get-relevant-features ] ] ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 "^(.*):<relevant>(.*)$" : $(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.
|
||||
#
|
||||
|
||||
@@ -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>$(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 ] ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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> ] ;
|
||||
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) = <conditional>
|
||||
if ( [ MATCH (:) : $(p:G=) ] && ! ( free in [ feature.attributes $(p:G) ] ) ) || $(p:G) = <conditional>
|
||||
{
|
||||
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.
|
||||
|
||||
@@ -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 <relevant> 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 += <relevant>$(value):<relevant>$(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 += <relevant>$(value):<relevant>$(condition) ;
|
||||
}
|
||||
}
|
||||
return [ sequence.unique $(result) ] ;
|
||||
}
|
||||
|
||||
|
||||
rule expand-subfeatures-in-conditions ( properties * )
|
||||
{
|
||||
local result ;
|
||||
|
||||
@@ -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 <relevant>$(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 <relevant> ]
|
||||
[ $(rproperties).get <relevant> ] ] ;
|
||||
gur = [ property-set.create
|
||||
[ property.change [ $(gur).raw ] : <relevant> ]
|
||||
<relevant>$(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 <relevant> properties
|
||||
local relevant ;
|
||||
for local r in [ $(xusage-requirements).get <relevant> ]
|
||||
{
|
||||
local check = [ MATCH "(.*):<relevant>(.*)" : $(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> ]
|
||||
<relevant>$(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) ] ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 <relevant>$(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.
|
||||
|
||||
@@ -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) ;
|
||||
|
||||
@@ -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 <bison.prefix> ;
|
||||
_ = " " ;
|
||||
|
||||
actions bison
|
||||
{
|
||||
bison $(PREFIX_OPT) -d -o $(<[1]) $(>)
|
||||
bison -p$(_)$(PREFIX) -d -o $(<[1]) $(>)
|
||||
}
|
||||
|
||||
@@ -274,6 +274,7 @@ rule translate-path ( path )
|
||||
}
|
||||
}
|
||||
|
||||
toolset.uses-features doxygen.headers-to-doxyfile : "<doxygen:param>" ;
|
||||
|
||||
# Generates a doxygen configuration file (doxyfile) given a set of C++ sources
|
||||
# and a property list that may contain <doxygen:param> features.
|
||||
@@ -321,6 +322,7 @@ rule headers-to-doxyfile ( target : sources * : properties * )
|
||||
print.text $(text) : true ;
|
||||
}
|
||||
|
||||
toolset.uses-features doxygen.run : <doxygen.rmdir> "<doxygen:param>" ;
|
||||
|
||||
# Run Doxygen. See doxygen-action for a description of the strange properties of
|
||||
# this rule.
|
||||
@@ -406,6 +408,7 @@ rule collect ( target : source : properties * )
|
||||
: <xsl:param>doxygen.xml.path=$(native-path) ;
|
||||
}
|
||||
|
||||
toolset.uses-features doxygen.xml-to-boostbook : <prefix> <reftitle> ;
|
||||
|
||||
# Translate Doxygen XML into BoostBook.
|
||||
#
|
||||
|
||||
10
src/tools/features/relevant-feature.jam
Normal file
10
src/tools/features/relevant-feature.jam
Normal file
@@ -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 ;
|
||||
@@ -25,5 +25,5 @@ rule detect ( properties * )
|
||||
local ps = [ property-set.create $(properties) ] ;
|
||||
local api = [ $(ps).get <threadapi> ] ;
|
||||
if ! $(api) { api = [ get-default $(ps) ] ; }
|
||||
return <threadapi>$(api) ;
|
||||
return <threadapi>$(api) <relevant>threadapi:<relevant>target-os ;
|
||||
}
|
||||
|
||||
@@ -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>$(pch-file) <cflags>-Winvalid-pch ]
|
||||
$(pch-file)
|
||||
[ $(pch-file[1]).add-raw <pch-file>$(pch-file[2-]) <cflags>-Winvalid-pch ]
|
||||
$(pch-file[2-])
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) ] ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,8 +54,9 @@ class lib-generator : generator
|
||||
}
|
||||
property-set = [ $(property-set).add-raw <main-target-type>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 <relevant>link ] $(result[2-]) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <xdll-path>$(extra-xdll-paths) ] ] ;
|
||||
ur = [ $(ur).add $(result[1]) ] ;
|
||||
}
|
||||
return $(ur) $(result) ;
|
||||
return $(ur) $(result[2-]) ;
|
||||
}
|
||||
|
||||
rule extra-usage-requirements ( created-targets * : property-set )
|
||||
|
||||
@@ -38,7 +38,7 @@ class searched-lib-generator : generator
|
||||
|
||||
local search = [ feature.get-values <search> : $(properties) ] ;
|
||||
|
||||
local a = [ new null-action $(property-set) ] ;
|
||||
local a = [ new null-action [ $(property-set).add-raw <relevant>link ] ] ;
|
||||
local lib-name = [ feature.get-values <name> : $(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 : <name>png ;
|
||||
# the 'z' target should be returned, so that apps linking to 'png'
|
||||
# will link to 'z', too.
|
||||
return [ property-set.create <xdll-path>$(search) ]
|
||||
return [ property-set.create <xdll-path>$(search) <relevant>link ]
|
||||
[ virtual-target.register $(t) ] $(sources) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 <flex.prefix> ;
|
||||
|
||||
actions lex
|
||||
{
|
||||
|
||||
@@ -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) ] ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <testing.arg> ;
|
||||
toolset.uses-features mpi.capture-output :
|
||||
<testing.launcher> <testing.execute> <dll-path> <xdll-path> <target-os>
|
||||
<mpi:processes> ;
|
||||
|
||||
rule capture-output ( target : sources * : properties * )
|
||||
{
|
||||
# Use the standard capture-output rule to run the tests
|
||||
|
||||
@@ -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 : <embed-manifest> <embed-manifest-file> ;
|
||||
|
||||
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-header)
|
||||
<pch-file>$(pch-file) ] $(generated) ;
|
||||
return [ $(generated[1]).add-raw <pch-header>$(pch-header)
|
||||
<pch-file>$(pch-file) ] $(generated[2-]) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -878,7 +879,7 @@ local rule set-setup-command ( targets * : properties * )
|
||||
if ! $($(key))
|
||||
{
|
||||
properties = [ feature.expand $(properties) ] ;
|
||||
properties = [ property.select <toolset> <toolset-msvc:version> <architecture> <address-model> <windows-api> : $(properties) ] ;
|
||||
properties = [ property.select <toolset> <toolset-msvc:version> <architecture> <address-model> <windows-api> <relevant> : $(properties) ] ;
|
||||
local ps = [ property-set.create $(properties) <msvc.setup-options>$(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 <debug-symbols> ] = "on"
|
||||
{
|
||||
|
||||
@@ -1243,6 +1243,10 @@ local rule pyd-pythonpath ( source )
|
||||
toolset.flags python.capture-output ARGS <testing.arg> ;
|
||||
toolset.flags python.capture-output INPUT_FILES <testing.input-file> ;
|
||||
|
||||
toolset.uses-features python.capture-output :
|
||||
<testing.launcher> <testing.execute> <dll-path> <xdll-path> <target-os>
|
||||
<pythonpath> ;
|
||||
|
||||
rule capture-output ( target : sources * : properties * )
|
||||
{
|
||||
# Setup up a proper DLL search path. Here, $(sources[1]) is a python module
|
||||
|
||||
@@ -89,6 +89,9 @@ class stlport-target-class : basic-target
|
||||
|
||||
local requirements ;
|
||||
requirements += <stdlib-stlport:version>$(self.version) ;
|
||||
requirements += <relevant>runtime-debugging ;
|
||||
requirements += <relevant>toolset ;
|
||||
requirements += <relevant>runtime-link ;
|
||||
self.requirements = [ property-set.create $(requirements) ] ;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 : <preserve-test-targets> ;
|
||||
toolset.uses-features testing.expect-failure : <preserve-test-targets> ;
|
||||
|
||||
# The action rules called by generators.
|
||||
|
||||
@@ -456,6 +458,9 @@ toolset.flags testing.capture-output ARGS <testing.arg> ;
|
||||
toolset.flags testing.capture-output INPUT_FILES <testing.input-file> ;
|
||||
toolset.flags testing.capture-output LAUNCHER <testing.launcher> ;
|
||||
|
||||
toolset.uses-features testing.capture-output :
|
||||
<testing.launcher> <testing.execute> <dll-path> <xdll-path> <target-os> ;
|
||||
|
||||
if --remove-test-targets in [ modules.peek : ARGV ]
|
||||
{
|
||||
feature.set-default preserve-test-targets : off ;
|
||||
|
||||
@@ -151,6 +151,7 @@ IMPORT xsltproc : register-generator : : generators.register-xslt ;
|
||||
|
||||
rule flags ( rulename )
|
||||
{
|
||||
toolset.uses-features $(rulename) : <xsl:param> <catalog> : unchecked ;
|
||||
toolset.flags $(rulename) XSL-PATH : <xsl:path> : unchecked ;
|
||||
toolset.flags $(rulename) FLAGS : <flags> : unchecked ;
|
||||
}
|
||||
|
||||
@@ -214,8 +214,9 @@ generators.register-linker mock.link : LIB OBJ : EXE : <toolset>mock ;
|
||||
generators.register-linker mock.link.dll : LIB OBJ : SHARED_LIB : <toolset>mock ;
|
||||
generators.register-archiver mock.archive : OBJ : STATIC_LIB : <toolset>mock ;
|
||||
|
||||
toolset.flags mock.compile INCLUDES <include> ;
|
||||
toolset.flags mock.compile DEFINES <define> ;
|
||||
toolset.flags mock.compile OPTIONS <link>shared : -fPIC ;
|
||||
toolset.flags mock.compile INCLUDES : <include> ;
|
||||
toolset.flags mock.compile DEFINES : <define> ;
|
||||
|
||||
actions compile.c
|
||||
{
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
142
test/feature_relevant.py
Normal file
142
test/feature_relevant.py
Normal file
@@ -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 <relevant> 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 : <xxxflags> ;
|
||||
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 : <zzz.enabled>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 : <aaaflags> ;
|
||||
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 <xxxflags> is relevant
|
||||
feature f1 : n y : composite propagated ;
|
||||
feature.compose <f1>y : <xxxflags>-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 <g1>y : <xxxflags>-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
|
||||
<f1>y <f2>y <f3>y <f4>y <f5>y <f6>y <f7>y
|
||||
<g1>y <g2>y <g3>y <g4>y <g5>y <g6>y <g7>y <zzz.enabled>on ;
|
||||
|
||||
rule icond6 ( properties * )
|
||||
{
|
||||
local result ;
|
||||
if <f6>y in $(properties) || <g6>y in $(properties)
|
||||
{
|
||||
result += <xxxflags>-yes6 ;
|
||||
}
|
||||
return $(result)
|
||||
<relevant>xxxflags:<relevant>f6
|
||||
<relevant>xxxflags:<relevant>g6 ;
|
||||
}
|
||||
|
||||
rule icond7 ( properties * )
|
||||
{
|
||||
local result ;
|
||||
if <f7>y in $(properties) || <g7>y in $(properties)
|
||||
{
|
||||
result += <aaaflags>-yes7 ;
|
||||
}
|
||||
return $(result)
|
||||
<relevant>aaaflags:<relevant>f7
|
||||
<relevant>aaaflags:<relevant>g7 ;
|
||||
}
|
||||
|
||||
zzz out : in.yyy
|
||||
: <f2>y:<xxxflags>-no2 <g2>y:<xxxflags>-no2 <relevant>f4 <relevant>g4
|
||||
<conditional>@icond6
|
||||
:
|
||||
: <f5>y:<aaaflags>-yes5 <g5>y:<aaaflags>-yes5 <conditional>@icond7
|
||||
;
|
||||
alias out : : <f3>n ;
|
||||
alias out : : <g3>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()
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -28,8 +28,8 @@ make foo.bar : : creator : <test_feature>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
|
||||
|
||||
@@ -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> <optimization> ;
|
||||
toolset.flags yfc-link KNOWN-PROPERTIES : <toolset> <optimization> ;
|
||||
|
||||
rule yfc-compile ( target : sources * : property-set * )
|
||||
{
|
||||
PROPERTIES on $(target) = [ properties-as-path $(property-set) ] ;
|
||||
|
||||
@@ -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> <optimization> ;
|
||||
toolset.flags yfc-link KNOWN-PROPERTIES : <toolset> <optimization> ;
|
||||
|
||||
|
||||
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 ;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -12,6 +12,8 @@ t = BoostBuild.Tester(use_test_config=False)
|
||||
|
||||
t.write("jamroot.jam", """
|
||||
project : requirements <threading>multi <variant>debug:<link>static ;
|
||||
# Force link to be relevant
|
||||
project : requirements <link>shared:<define>TEST_DLL ;
|
||||
|
||||
build-project sub ;
|
||||
build-project sub2 ;
|
||||
|
||||
@@ -35,7 +35,7 @@ obj test : test.cpp : <implicit-dependency>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 : <implicit-dependency>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 : <implicit-dependency>header2.h <include>. ;
|
||||
""")
|
||||
|
||||
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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -222,6 +222,7 @@ tests = ["absolute_sources",
|
||||
"expansion",
|
||||
"explicit",
|
||||
"feature_cxxflags",
|
||||
"feature_relevant",
|
||||
"generator_selection",
|
||||
"generators_test",
|
||||
"implicit_dependency",
|
||||
|
||||
Reference in New Issue
Block a user