2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-14 00:32:11 +00:00

Add a new rule configure.choose that adds properties associated with the first target from a list that successfully builds.

This commit is contained in:
Steven Watanabe
2017-12-19 13:30:09 -07:00
parent 8aa702aaf4
commit 3ae87ff496
2 changed files with 276 additions and 2 deletions

View File

@@ -222,6 +222,89 @@ rule try-build ( targets * : ps : what : retry ? )
return $(result) ;
}
# Attempts to build several sets of virtual targets. Returns the
# the index of the first set that builds.
rule try-find-build ( ps : what : * )
{
local args = 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ;
# The outer layer only needs to check $(what), but we
# also need to check the individual elements, in case
# the set of targets has changed since the last build.
local cache-name = $(what) $($(args)[1]) [ $(ps).raw ] ;
cache-name = $(cache-name:J=-) ;
local value = [ config-cache.get $(cache-name) ] ;
local result ;
local jam-targets ;
# Check whether we need to force rebuild configure targets
if --reconfigure in [ modules.peek : ARGV ]
{
local all-targets ;
for local t in $($(args)[2-])
{
all-targets += [ virtual-target.traverse $(t) ] ;
}
for local t in [ sequence.unique $(all-targets) ]
{
$(t).always ;
}
}
if $(value)
{
local none = none ; # What to show when the argument
local name = $(value) ;
if $(name) != none
{
name = [ CALC $(name) + 2 ] ;
}
local x = [ PAD " - $(what)" : $(.width) ] ;
local y = [ PAD $($(name)[1]) : 3 ] ;
result = $(value) ;
log-check-result "$(x) : $(y) (cached)" ;
}
else
{
local x = [ PAD " - $(what)" : $(.width) ] ;
for local i in $(args)
{
local jam-targets ;
for local t in $($(i)[2-])
{
jam-targets += [ $(t).actualize ] ;
}
if [ UPDATE_NOW $(jam-targets) :
$(.log-fd) : ignore-minus-n : ignore-minus-q ]
{
result = [ CALC $(i) - 2 ] ;
log-check-result "$(x) : $($(i)[1])" ;
break ;
}
}
if ! $(result)
{
result = none ;
}
}
if ! $(value)
{
if $(result)
{
config-cache.set $(cache-name) : $(result) ;
}
else
{
config-cache.set $(cache-name) : $(result) ;
}
}
if $(result) != none
{
return $(result) ;
}
}
# Attempt to build a metatarget named by 'metatarget-reference'
# in context of 'project' with properties 'ps'.
# Returns non-empty value if build is OK.
@@ -248,6 +331,68 @@ rule builds-raw ( metatarget-reference : project : ps : what : retry ? )
}
}
# Attempt to build a metatarget named by 'metatarget-reference'
# in context of 'project' with properties 'ps'.
# Returns the 1-based index of the first target
# that builds.
rule find-builds-raw ( project : ps : what : * )
{
local result ;
local args = 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ;
if ! $(.$(what)-tested.$(ps))
{
.$(what)-tested.$(ps) = true ;
local targets.$(i) what.$(i) ;
for local i in $(args)
{
if ! $($(i))
{
break ;
}
targets.$(i) = [ targets.generate-from-reference
$($(i)[1]) : $(project) : $(ps) ] ;
# ignore usage requirements
targets.$(i) = $(targets.$(i)[2-]) ;
if $($(i)[2])
{
what.$(i) = $($(i)[2]) ;
}
else
{
local t = [ targets.resolve-reference
$($(i)[1]) : $(project) ] ;
what.$(i) = [ $(t[1]).name ] ;
}
}
result = [ try-find-build $(ps) : $(what)
: $(what.4) $(targets.4)
: $(what.5) $(targets.5)
: $(what.6) $(targets.6)
: $(what.7) $(targets.7)
: $(what.8) $(targets.8)
: $(what.9) $(targets.9)
: $(what.10) $(targets.10)
: $(what.11) $(targets.11)
: $(what.12) $(targets.12)
: $(what.13) $(targets.13)
: $(what.14) $(targets.14)
: $(what.15) $(targets.15)
: $(what.16) $(targets.16)
: $(what.17) $(targets.17)
: $(what.18) $(targets.18)
: $(what.19) $(targets.19) ] ;
.$(what)-result.$(ps) = $(result) ;
return $(result) ;
}
else
{
return $(.$(what)-result.$(ps)) ;
}
}
local rule get-relevant-features ( )
{
local relevant = [ feature.expand <configure> ] ;
@@ -286,6 +431,19 @@ rule builds ( metatarget-reference : properties * : what ? : retry ? )
$(retry) ] ;
}
rule find-builds ( what : properties * : * )
{
local relevant = [ property.select [ get-relevant-features ] : $(properties) ] ;
local ps = [ property-set.create $(relevant) ] ;
local t = [ targets.current ] ;
local p = [ $(t).project ] ;
return [ find-builds-raw $(p) : $(ps) : $(what) :
$(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) :
$(10) : $(11) : $(12) : $(13) : $(14) : $(15) :
$(16) : $(17) : $(18) : $(19) ] ;
}
# Called by Boost.Build startup code to specify the file to receive the
# configuration check results. Should never be called by user code.
@@ -330,6 +488,57 @@ class check-target-builds-worker
}
}
class configure-choose-worker
{
import configure ;
import property ;
rule __init__ ( message : * )
{
self.message = $(message) ;
for i in 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
{
local name = [ CALC $(i) - 1 ] ;
self.targets.$(name) = $($(i)[1]) ;
if ! $($(i)[2]:G) # Check whether the second argument is a property
{
self.what.$(name) = $($(i)[2]) ;
self.props.$(name) = $($(i)[3-]) ;
}
else
{
self.props.$(name) = $($(i)[2-]) ;
}
}
}
rule check ( properties * )
{
local i = [ configure.find-builds $(self.message) : $(properties)
: $(self.targets.1) $(self.what.1)
: $(self.targets.2) $(self.what.2)
: $(self.targets.3) $(self.what.3)
: $(self.targets.4) $(self.what.4)
: $(self.targets.5) $(self.what.5)
: $(self.targets.6) $(self.what.6)
: $(self.targets.7) $(self.what.7)
: $(self.targets.8) $(self.what.8)
: $(self.targets.9) $(self.what.9)
: $(self.targets.10) $(self.what.10)
: $(self.targets.11) $(self.what.11)
: $(self.targets.12) $(self.what.12)
: $(self.targets.13) $(self.what.13)
: $(self.targets.14) $(self.what.14)
: $(self.targets.15) $(self.what.15)
: $(self.targets.16) $(self.what.16)
: $(self.targets.17) $(self.what.17)
: $(self.targets.18) $(self.what.18)
: $(self.targets.19) $(self.what.19) ] ;
if $(self.props.$(i))
{
return [ property.evaluate-conditionals-in-context $(self.props.$(i)) : $(properties) ] ;
}
}
}
rule check-target-builds ( target message ? : true-properties * :
false-properties * )
@@ -339,5 +548,19 @@ rule check-target-builds ( target message ? : true-properties * :
return <conditional>@$(instance).check ;
}
# Usage:
# [ configure.choose "architecture"
# : /config//x86 x86 <architecture>x86
# : /config//mips mips <architecture>mips
# ]
rule choose ( message : * )
{
local instance = [ new configure-choose-worker $(message)
: $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9)
: $(10) : $(11) : $(12) : $(13) : $(14) : $(15) : $(16)
: $(17) : $(18) : $(19) ] ;
return <conditional>@$(instance).check ;
}
IMPORT $(__name__) : check-target-builds : : check-target-builds ;

View File

@@ -9,7 +9,7 @@
import BoostBuild
def test_basic():
def test_check_target_builds():
t = BoostBuild.Tester(use_test_config=0)
t.write("Jamroot", """
import configure ;
@@ -67,4 +67,55 @@ obj bar : foo.cpp :
t.cleanup()
test_basic()
def test_choose():
t = BoostBuild.Tester(use_test_config=0)
t.write("Jamroot", """
import configure ;
obj pass : pass.cpp ;
obj fail : fail.cpp ;
explicit pass fail ;
obj foo : foo.cpp :
[ configure.choose "which one?" : fail <define>FAIL : pass <define>PASS ] ;
""")
t.write("pass.cpp", "void f() {}\n")
t.write("fail.cpp", "#error fail.cpp\n")
t.write("foo.cpp", """
#ifndef PASS
#error PASS not defined
#endif
#ifdef FAIL
#error FAIL is defined
#endif
""")
t.run_build_system()
t.expect_output_lines([
" - which one? : pass"])
t.expect_addition("bin/$toolset/debug*/pass.obj")
t.expect_addition("bin/$toolset/debug*/foo.obj")
t.expect_nothing_more()
# An up-to-date build should use the cache
t.run_build_system()
t.expect_output_lines([
" - which one? : pass (cached)"])
t.expect_nothing_more()
# -a should re-run everything, including configuration checks
t.run_build_system(["-a"])
t.expect_output_lines([
" - which one? : pass"])
t.expect_touch("bin/$toolset/debug*/pass.obj")
t.expect_touch("bin/$toolset/debug*/foo.obj")
t.expect_nothing_more()
# --reconfigure should re-run configuration checks only
t.run_build_system(["--reconfigure"])
t.expect_output_lines([
" - which one? : pass"])
t.expect_touch("bin/$toolset/debug*/pass.obj")
t.expect_nothing_more()
t.cleanup()
test_check_target_builds()
test_choose()