diff --git a/src/build/feature.jam b/src/build/feature.jam index 182d39f80..624440b96 100644 --- a/src/build/feature.jam +++ b/src/build/feature.jam @@ -1092,7 +1092,7 @@ rule add-defaults ( properties * ) } } - local worklist = $(properties) ; + local worklist = $(properties) $(more) ; local expanded-from-composite ; local to-expand = $(more) ; while $(worklist) diff --git a/test/expansion.py b/test/expansion.py index ed8690312..d929223ba 100644 --- a/test/expansion.py +++ b/test/expansion.py @@ -7,87 +7,92 @@ import BoostBuild -t = BoostBuild.Tester(use_test_config=False) +t = BoostBuild.Tester(arguments=["--config="], pass_toolset=0) -t.write("a.cpp", """ -#ifdef CF_IS_OFF -int main() {} -#endif -""") +t.write("source.input", "") -t.write("b.cpp", """ -#if defined(CF_1) && !defined(CF_IS_OFF) -int main() {} -#endif -""") +t.write("test-properties.jam", """ +import feature : feature ; +import generators ; +import toolset ; +import type ; -t.write("c.cpp", """ -#ifdef FOO -int main() {} -#endif -""") +# We're not using the toolset at all, and we want to +# suppress toolset initialization to avoid surprises. +feature.extend toolset : null ; -t.write("d.cpp", """ -#ifndef CF_IS_OFF -int main() {} -#endif -""") - -t.write("e.cpp", """ -#if !defined(CF_IS_OFF) && defined(CF_2) && !defined(CF_1) -int main() {} -#endif -""") - -t.write("f.cpp", """ -#if defined(CF_1) -int main() {} -#endif -""") - -t.write("g.cpp", """ -#if defined(FOPT_2) -int main() {} -#endif -""") - -t.write("h.cpp", """ -#if defined(CX_2) -int main() {} -#endif +type.register CHECK : check ; +type.register INPUT : input ; +feature expected-define : : free ; +feature unexpected-define : : free ; +toolset.flags test-properties DEFINES : ; +toolset.flags test-properties EXPECTED : ; +toolset.flags test-properties UNEXPECTED : ; +generators.register-standard test-properties.check : INPUT : CHECK ; +rule check ( target : source : properties * ) +{ + local defines = [ on $(target) return $(DEFINES) ] ; + for local macro in [ on $(target) return $(EXPECTED) ] + { + if ! ( $(macro) in $(defines) ) + { + EXIT expected $(macro) for $(target) in $(properties) : 1 ; + } + } + for local macro in [ on $(target) return $(UNEXPECTED) ] + { + if $(macro) in $(defines) + { + EXIT unexpected $(macro) for $(target) in $(properties) : 1 ; + } + } +} +actions check +{ + echo okay > $(<) +} """) t.write("jamfile.jam", """ +import test-properties ; # See if default value of composite feature 'cf' will be expanded to # CF_IS_OFF. -exe a : a.cpp ; +check a : source.input : CF_IS_OFF ; # See if subfeature in requirements in expanded. -exe b : b.cpp : on-1 ; +check b : source.input : on-1 + CF_1 CF_IS_OFF ; # See if conditional requirements are recursively expanded. -exe c : c.cpp : $toolset:release release:FOO +check c : source.input : null:release + release:FOO FOO ; # Composites specified in the default build should not # be expanded if they are overridden in the the requirements. -exe d : d.cpp : on : off ; +check d : source.input : on CF_IS_OFF : off ; # Overriding a feature should clear subfeatures and # apply default values of subfeatures. -exe e : e.cpp : always : on-1 ; +check e : source.input : always + CF_IS_OFF CF_2 CF_1 + : on-1 ; # Subfeatures should not be changed if the parent feature doesn't change -exe f : f.cpp : on : on-1 ; +check f : source.input : on CF_1 : on-1 ; # If a subfeature is not specific to the value of the parent feature, # then changing the parent value should not clear the subfeature. -exe g : g.cpp : off : on-2 ; +check g : source.input : off FOPT_2 : on-2 ; # If the default value of a composite feature adds an optional # feature which has a subfeature with a default, then that # default should be added. -exe h : h.cpp ; +check h : source.input : CX_2 ; + +# If the default value of a feature is used, then the +# default value of its subfeatures should also be used. +check i : source.input : SF_1 ; """) t.write("jamroot.jam", """ @@ -107,40 +112,23 @@ feature.feature cx2 : on : optional incidental ; feature.subfeature cx2 on : sub : 1 : composite incidental ; feature.compose on : on ; feature.compose 1 : CX_2 ; + +feature.feature sf : a : incidental ; +feature.subfeature sf a : sub : 1 : composite incidental ; +feature.compose 1 : SF_1 ; """) t.expand_toolset("jamfile.jam") t.run_build_system() -t.expect_addition(["bin/$toolset/debug*/a.exe", - "bin/$toolset/debug*/b.exe", - "bin/$toolset/release*/c.exe", - "bin/$toolset/debug*/d.exe", - "bin/$toolset/debug*/e.exe", - "bin/$toolset/debug*/f.exe", - "bin/$toolset/debug*/g.exe", - "bin/$toolset/debug*/h.exe"]) - -t.rm("bin") - - -# Test for issue BB60. - -t.write("test.cpp", """ -#include "header.h" -int main() {} -""") - -t.write("jamfile.jam", """ -project : requirements $toolset:foo ; -exe test : test.cpp : $toolset ; -""") - -t.expand_toolset("jamfile.jam") -t.write("foo/header.h", "\n") -t.write("jamroot.jam", "") - -t.run_build_system() -t.expect_addition("bin/$toolset/debug*/test.exe") +t.expect_addition(["bin/debug/a.check", + "bin/debug/b.check", + "bin/null/release/c.check", + "bin/debug/d.check", + "bin/debug/e.check", + "bin/debug/f.check", + "bin/debug/g.check", + "bin/debug/h.check", + "bin/debug/i.check"]) t.cleanup()