diff --git a/new/build-request.jam b/new/build-request.jam index b1be39e5e..47f896b00 100644 --- a/new/build-request.jam +++ b/new/build-request.jam @@ -21,7 +21,7 @@ local rule apply-to-property-set ( f property-set ) # expand the given build request by combining all property-sets which don't # specify conflicting non-free features. -local rule expand-no-defaults ( property-sets * : feature-space ? ) +rule expand-no-defaults ( property-sets * : feature-space ? ) { feature-space ?= feature ; diff --git a/new/build-system.jam b/new/build-system.jam index 7e013fdb2..3ffbbc48b 100644 --- a/new/build-system.jam +++ b/new/build-system.jam @@ -72,7 +72,7 @@ properties = [ $(build-request).get-at 2 ] ; if $(properties) { - expanded = [ build-request.expand $(properties) ] ; + expanded = [ build-request.expand-no-defaults $(properties) ] ; } diff --git a/new/feature.jam b/new/feature.jam index aa4bed3de..90151278e 100644 --- a/new/feature.jam +++ b/new/feature.jam @@ -710,7 +710,13 @@ rule add-defaults ( properties * ) but \"$(v)\" appears to be the value of an un-expanded implicit feature ; } } - local missing = [ set.difference $(.all-features) : $(properties:G) ] ; + # We don't add default for elements with ":" inside. This catches: + # 1. Conditional properties --- we don't want debug:DEBUG + # to be takes as specified value for + # 2. Free properties with ":" in values. We don't care, since free properties + # don't have defaults. + local xproperties = [ MATCH "^([^:]+)$" : $(properties) ] ; + local missing = [ set.difference $(.all-features) : $(xproperties:G) ] ; return $(properties) [ defaults $(missing) ] ; } @@ -884,9 +890,9 @@ local rule __test__ ( ) : defaults ; - assert.result static foobar on gcc debug - native dummy1 - : add-defaults static foobar on + assert.result static foobar on gcc:FOO + gcc debug native dummy1 + : add-defaults static foobar on gcc:FOO ; assert.result gcc foo stlport 3 /path/to/stlport MAGIC=3 diff --git a/new/property-set.jam b/new/property-set.jam index 7de41e5b1..f140eb0b2 100644 --- a/new/property-set.jam +++ b/new/property-set.jam @@ -128,6 +128,17 @@ local rule property-set ( raw-properties * ) return $(self.run) ; } + rule add-defaults ( ) + { + if ! $(self.defaults) + { + self.defaults = [ property-set.create + [ feature.add-defaults $(self.raw) ] ] ; + } + return $(self.defaults) ; + } + + rule as-path ( ) { if ! $(self.as-path) diff --git a/new/targets.jam b/new/targets.jam index 5270772cb..e55bff475 100644 --- a/new/targets.jam +++ b/new/targets.jam @@ -516,6 +516,10 @@ rule basic-target ( name : project # come from dependencies, the value is not target id, but rather # virtual target names, so generators.construct can use them. + # defaults should be added as soon as possible. For example, conditionals + # might have "debug:..." and won't work if defaults are not + # applied. + rproperties = [ $(rproperties).add-defaults ] ; rproperties = [ $(rproperties).evaluate-conditionals ] ; rproperties = @@ -563,7 +567,7 @@ rule basic-target ( name : project { if ! $(self.generated.$(property-set)) { - local rproperties = [ final-properties $(property-set) ] ; + local rproperties = [ final-properties $(property-set) ] ; if $(rproperties[1]) != "@error" { local source-targets = [ generate-sources $(rproperties) ] ; diff --git a/test/default_features.py b/test/default_features.py new file mode 100644 index 000000000..44f2143d7 --- /dev/null +++ b/test/default_features.py @@ -0,0 +1,50 @@ +#!/usr/bin/python + +# Copyright (C) Vladimir Prus 2003. Permission to copy, use, modify, sell and +# distribute this software is granted provided this copyright notice appears in +# all copies. This software is provided "as is" without express or implied +# warranty, and with no claim as to its suitability for any purpose. + +# Test that features with default values are always present +# in build properties of any target. + +from BoostBuild import Tester, List + +t = Tester() + +# Declare *non-propagated* feature foo. +t.write("project-root.jam", """ +import feature : feature ; + +feature foo : on off ; +""") + +# Note that 'on' won't be propagated +# to 'd/l'. +t.write("Jamfile", """ +exe hello : hello.cpp d/l ; +""") +t.write("hello.cpp", """ +void foo(); +int main() +{ + foo(); + return 1; +} + +""") + +t.write("d/Jamfile", """ +lib l : l.cpp : on:FOO ; +""") +t.write("l.cpp", """ +#ifdef FOO +void foo() {} +#endif + +""") + +t.run_build_system() +t.expect_addition("bin/$toolset/debug/hello.exe") + +t.cleanup() diff --git a/test/test_all.py b/test/test_all.py index 834662f7d..f98343c7c 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -84,6 +84,7 @@ tests = [ "project_test1", "alias", "alternatives", "unused", + "default_features", ] if os.name == 'posix': diff --git a/v2/build/build-request.jam b/v2/build/build-request.jam index b1be39e5e..47f896b00 100644 --- a/v2/build/build-request.jam +++ b/v2/build/build-request.jam @@ -21,7 +21,7 @@ local rule apply-to-property-set ( f property-set ) # expand the given build request by combining all property-sets which don't # specify conflicting non-free features. -local rule expand-no-defaults ( property-sets * : feature-space ? ) +rule expand-no-defaults ( property-sets * : feature-space ? ) { feature-space ?= feature ; diff --git a/v2/build/feature.jam b/v2/build/feature.jam index aa4bed3de..90151278e 100644 --- a/v2/build/feature.jam +++ b/v2/build/feature.jam @@ -710,7 +710,13 @@ rule add-defaults ( properties * ) but \"$(v)\" appears to be the value of an un-expanded implicit feature ; } } - local missing = [ set.difference $(.all-features) : $(properties:G) ] ; + # We don't add default for elements with ":" inside. This catches: + # 1. Conditional properties --- we don't want debug:DEBUG + # to be takes as specified value for + # 2. Free properties with ":" in values. We don't care, since free properties + # don't have defaults. + local xproperties = [ MATCH "^([^:]+)$" : $(properties) ] ; + local missing = [ set.difference $(.all-features) : $(xproperties:G) ] ; return $(properties) [ defaults $(missing) ] ; } @@ -884,9 +890,9 @@ local rule __test__ ( ) : defaults ; - assert.result static foobar on gcc debug - native dummy1 - : add-defaults static foobar on + assert.result static foobar on gcc:FOO + gcc debug native dummy1 + : add-defaults static foobar on gcc:FOO ; assert.result gcc foo stlport 3 /path/to/stlport MAGIC=3 diff --git a/v2/build/property-set.jam b/v2/build/property-set.jam index 7de41e5b1..f140eb0b2 100644 --- a/v2/build/property-set.jam +++ b/v2/build/property-set.jam @@ -128,6 +128,17 @@ local rule property-set ( raw-properties * ) return $(self.run) ; } + rule add-defaults ( ) + { + if ! $(self.defaults) + { + self.defaults = [ property-set.create + [ feature.add-defaults $(self.raw) ] ] ; + } + return $(self.defaults) ; + } + + rule as-path ( ) { if ! $(self.as-path) diff --git a/v2/build/targets.jam b/v2/build/targets.jam index 5270772cb..e55bff475 100644 --- a/v2/build/targets.jam +++ b/v2/build/targets.jam @@ -516,6 +516,10 @@ rule basic-target ( name : project # come from dependencies, the value is not target id, but rather # virtual target names, so generators.construct can use them. + # defaults should be added as soon as possible. For example, conditionals + # might have "debug:..." and won't work if defaults are not + # applied. + rproperties = [ $(rproperties).add-defaults ] ; rproperties = [ $(rproperties).evaluate-conditionals ] ; rproperties = @@ -563,7 +567,7 @@ rule basic-target ( name : project { if ! $(self.generated.$(property-set)) { - local rproperties = [ final-properties $(property-set) ] ; + local rproperties = [ final-properties $(property-set) ] ; if $(rproperties[1]) != "@error" { local source-targets = [ generate-sources $(rproperties) ] ; diff --git a/v2/test/default_features.py b/v2/test/default_features.py new file mode 100644 index 000000000..44f2143d7 --- /dev/null +++ b/v2/test/default_features.py @@ -0,0 +1,50 @@ +#!/usr/bin/python + +# Copyright (C) Vladimir Prus 2003. Permission to copy, use, modify, sell and +# distribute this software is granted provided this copyright notice appears in +# all copies. This software is provided "as is" without express or implied +# warranty, and with no claim as to its suitability for any purpose. + +# Test that features with default values are always present +# in build properties of any target. + +from BoostBuild import Tester, List + +t = Tester() + +# Declare *non-propagated* feature foo. +t.write("project-root.jam", """ +import feature : feature ; + +feature foo : on off ; +""") + +# Note that 'on' won't be propagated +# to 'd/l'. +t.write("Jamfile", """ +exe hello : hello.cpp d/l ; +""") +t.write("hello.cpp", """ +void foo(); +int main() +{ + foo(); + return 1; +} + +""") + +t.write("d/Jamfile", """ +lib l : l.cpp : on:FOO ; +""") +t.write("l.cpp", """ +#ifdef FOO +void foo() {} +#endif + +""") + +t.run_build_system() +t.expect_addition("bin/$toolset/debug/hello.exe") + +t.cleanup() diff --git a/v2/test/test_all.py b/v2/test/test_all.py index 834662f7d..f98343c7c 100644 --- a/v2/test/test_all.py +++ b/v2/test/test_all.py @@ -84,6 +84,7 @@ tests = [ "project_test1", "alias", "alternatives", "unused", + "default_features", ] if os.name == 'posix':