From c55ca9170f54d227c2a6731b392a99a3d3eabb1e Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Wed, 25 Dec 2002 07:18:34 +0000 Subject: [PATCH] Work on BB14: allow target suffixes to depend on build properties. * new/builtin.jam Introduce "os" feature. * new/gcc.jam Make object suffix "o" on all platforms. * new/property.jam (property-map): New class. * new/type.jam (.suffixes): Global propety-map instance, to keep properties->suffix mapping. (set-generated-target-suffix): New rule (generated-target-suffix): New argument 'properties'. * new/virtual-target.jam (abstract-file-target.actual-name): Pass properties to type.generated-target-suffix. * test/project_test4.py Don't specify expected list of build properties, since it's not stable. Check head of error message only. [SVN r16700] --- new/builtin.jam | 5 +++ new/gcc.jam | 6 ++++ new/property.jam | 64 +++++++++++++++++++++++++++++++++++++ new/type.jam | 28 +++++++++++++--- new/virtual-target.jam | 10 ++++-- test/project_test4.py | 15 +++------ v2/build/property.jam | 64 +++++++++++++++++++++++++++++++++++++ v2/build/type.jam | 28 +++++++++++++--- v2/build/virtual-target.jam | 10 ++++-- v2/gcc.jam | 6 ++++ v2/test/project_test4.py | 15 +++------ v2/tools/builtin.jam | 5 +++ 12 files changed, 222 insertions(+), 34 deletions(-) diff --git a/new/builtin.jam b/new/builtin.jam index 62f279faf..016b9197e 100644 --- a/new/builtin.jam +++ b/new/builtin.jam @@ -20,6 +20,11 @@ import toolset ; import errors : error ; import symlink ; +# This feature is used to determine which OS we're on. +# In future, this may become and +local os = [ modules.peek : OS ] ; +feature os : $(os) : propagated link-incompatible ; + feature toolset : : implicit propagated link-incompatible symmetric ; feature link : shared static : propagated ; feature link-runtime : shared static : propagated ; diff --git a/new/gcc.jam b/new/gcc.jam index 224730f7f..0b74fd5fe 100644 --- a/new/gcc.jam +++ b/new/gcc.jam @@ -2,10 +2,16 @@ import property ; import generators ; import os ; +import type ; feature.extend toolset : gcc ; feature.subfeature toolset gcc : version : : optional ; +# Make the "o" suffix used for gcc toolset on all +# platforms +type.set-generated-target-suffix OBJ : gcc : o ; + + # Initializes the gcc toolset # Each argument has the form: # version binary-name [path] diff --git a/new/property.jam b/new/property.jam index 307bea63e..3093649e4 100644 --- a/new/property.jam +++ b/new/property.jam @@ -7,6 +7,8 @@ import feature ; import utility : ungrist ; import sequence : unique ; import errors : error ; +import class : class ; + # Refines 'properties' by overriding any elements for which a different # value is specified in 'requirements'. If the resulting property set @@ -312,6 +314,51 @@ rule translate-paths ( properties * : path ) return $(result) ; } +# Class which maintains a property set -> string +# mapping +rule property-map ( ) +{ + self.next-flag = 1 ; + + # Associate 'value' with 'properties' + rule insert ( properties + : value ) + { + self.all-flags += $(self.next-flag) ; + self.properties.$(self.next-flag) = $(properties) ; + self.value.$(self.next-flag) = $(value) ; + + self.next-flag = [ numbers.increment $(self.next-flag) ] ; + } + + # Return the value associated with 'properties' + # or any subset of it. If more than one + # subset has value assigned to it, return the + # value for the longest subset, if it's unique. + rule find ( properties + ) + { + # First find all matches + local matches ; + local match-ranks ; + for local i in $(self.all-flags) + { + if $(self.properties.$(i)) in $(properties) + { + matches += $(i) ; + match-ranks += [ sequence.length + $(self.properties.$(i)) ] ; + } + } + local best = [ sequence.select-highest-ranked + $(matches) : $(match-ranks) ] ; + if $(best[2]) + { + errors.error "Ambiguous key" ; + } + return $(self.value.$(best)) ; + } +} + +class property-map ; local rule __test__ ( ) @@ -402,5 +449,22 @@ local rule __test__ ( ) assert.result a : select include : a gcc ; + + + pm = [ new property-map ] ; + $(pm).insert gcc : o ; + $(pm).insert gcc NT : obj ; + $(pm).insert gcc CYGWIN : obj ; + + assert.equal o + : [ $(pm).find gcc ] ; + + assert.equal obj + : [ $(pm).find gcc NT ] ; + + try ; + $(pm).find gcc NT CYGWIN ; + catch "Ambiguous key" ; + } diff --git a/new/type.jam b/new/type.jam index b4c507a0c..d3751ae33 100644 --- a/new/type.jam +++ b/new/type.jam @@ -10,6 +10,7 @@ import feature ; import generators : * ; import class : class new ; import errors ; +import property ; feature.feature target-type : : composite optional ; @@ -18,6 +19,9 @@ feature.feature main-target-type : : optional incidental ; feature.feature base-target-type : : composite optional free ; # feature.feature main-target-type : : composite optional incidental ; +# Store suffixes for generated targets +.suffixes = [ new property-map ] ; + # Registers a target type, possible derived from a 'base-type'. # If 'suffixes' are provided, they given all the suffixes that mean a file is of 'type'. # Also, the first element gives the suffix to be used when constructing and object of @@ -44,7 +48,13 @@ rule register ( type : suffixes * : base-type ? : main ? ) { .types += $(type) ; .bases.$(type) = $(base-type) ; - .suffix.$(type) = $(suffixes[1]) ; + + if $(suffixes) + { + $(.suffixes).insert $(type) : $(suffixes[1]) ; + } + + .type.$(suffixes) = $(type) ; feature.extend target-type : $(type) ; @@ -117,10 +127,20 @@ rule is-derived ( type base ) } } -# Returns suffix that should be used when generating target of 'type'. -rule generated-target-suffix ( type ) +# Sets a target suffix that should be used when +# generating target of 'type' with the specified +# properties +rule set-generated-target-suffix ( type : properties + : suffix ) { - return $(.suffix.$(type)) ; + $(.suffixes).insert $(type) $(properties) : $(suffix) ; +} + + +# Returns suffix that should be used when generating target of 'type', +# with the specified properties. +rule generated-target-suffix ( type : properties * ) +{ + return [ $(.suffixes).find $(type) $(properties) ] ; } # Returns file type given its suffix. The 'suffix' parameter should include diff --git a/new/virtual-target.jam b/new/virtual-target.jam index 6cd152ecc..a233d7464 100644 --- a/new/virtual-target.jam +++ b/new/virtual-target.jam @@ -297,10 +297,12 @@ rule abstract-file-target ( name local location-grist = [ sequence.join [ regex.split $(project-location) "/" ] : "!" ] ; local grist ; + + local properties ; if $(self.action) { - local p = [ property.remove free incidental : [ $(self.action).properties ] ] ; - local property-grist = [ property.as-path $(p) ] ; + properties = [ property.remove free incidental : [ $(self.action).properties ] ] ; + local property-grist = [ property.as-path $(properties) ] ; grist = $(location-grist)/$(property-grist) ; } @@ -321,7 +323,9 @@ rule abstract-file-target ( name else if $(self.type) { self.actual-name = [ sequence.join <$(grist)>$(self.name) - [ type.generated-target-suffix $(self.type) ] : "." ] ; + [ type.generated-target-suffix $(self.type) : + $(properties) + ] : "." ] ; } else { diff --git a/test/project_test4.py b/test/project_test4.py index f3b8da3e9..448413fdd 100644 --- a/test/project_test4.py +++ b/test/project_test4.py @@ -2,7 +2,7 @@ from BoostBuild import Tester import os -from string import strip +from string import strip, find t = Tester() @@ -45,14 +45,9 @@ t.run_build_system("--no-error-backtrace", stdout=expected, status=None) t.copy("lib/Jamfile3", "lib/Jamfile") -expected="""warning: skipped build of lib/b.obj with properties gcc shared -shared on single on -on false debug -don't know how to make <.>lib/b.obj/on -...skipped <./gcc/debug>a.exe for lack of <.>lib/b.obj/on... -""" - -t.run_build_system(stdout=expected, status=None) +t.run_build_system(status=None) +t.fail_test(find(t.stdout(), "warning: skipped build of lib/b.obj with properties") \ + != 0) # Check that project can be skipped as well t.copy("Jamfile4", "Jamfile") @@ -70,7 +65,7 @@ t.run_build_system("rtti=on", stdout=expected, status=None) # We don't yet make targets depend on Jamfile, so need to start from scratch # The following test is disabled, because of problems related to -# issue 634319 +# issue BB10 #t.set_tree("project-test4") #t.copy("Jamfile2", "Jamfile") diff --git a/v2/build/property.jam b/v2/build/property.jam index 307bea63e..3093649e4 100644 --- a/v2/build/property.jam +++ b/v2/build/property.jam @@ -7,6 +7,8 @@ import feature ; import utility : ungrist ; import sequence : unique ; import errors : error ; +import class : class ; + # Refines 'properties' by overriding any elements for which a different # value is specified in 'requirements'. If the resulting property set @@ -312,6 +314,51 @@ rule translate-paths ( properties * : path ) return $(result) ; } +# Class which maintains a property set -> string +# mapping +rule property-map ( ) +{ + self.next-flag = 1 ; + + # Associate 'value' with 'properties' + rule insert ( properties + : value ) + { + self.all-flags += $(self.next-flag) ; + self.properties.$(self.next-flag) = $(properties) ; + self.value.$(self.next-flag) = $(value) ; + + self.next-flag = [ numbers.increment $(self.next-flag) ] ; + } + + # Return the value associated with 'properties' + # or any subset of it. If more than one + # subset has value assigned to it, return the + # value for the longest subset, if it's unique. + rule find ( properties + ) + { + # First find all matches + local matches ; + local match-ranks ; + for local i in $(self.all-flags) + { + if $(self.properties.$(i)) in $(properties) + { + matches += $(i) ; + match-ranks += [ sequence.length + $(self.properties.$(i)) ] ; + } + } + local best = [ sequence.select-highest-ranked + $(matches) : $(match-ranks) ] ; + if $(best[2]) + { + errors.error "Ambiguous key" ; + } + return $(self.value.$(best)) ; + } +} + +class property-map ; local rule __test__ ( ) @@ -402,5 +449,22 @@ local rule __test__ ( ) assert.result a : select include : a gcc ; + + + pm = [ new property-map ] ; + $(pm).insert gcc : o ; + $(pm).insert gcc NT : obj ; + $(pm).insert gcc CYGWIN : obj ; + + assert.equal o + : [ $(pm).find gcc ] ; + + assert.equal obj + : [ $(pm).find gcc NT ] ; + + try ; + $(pm).find gcc NT CYGWIN ; + catch "Ambiguous key" ; + } diff --git a/v2/build/type.jam b/v2/build/type.jam index b4c507a0c..d3751ae33 100644 --- a/v2/build/type.jam +++ b/v2/build/type.jam @@ -10,6 +10,7 @@ import feature ; import generators : * ; import class : class new ; import errors ; +import property ; feature.feature target-type : : composite optional ; @@ -18,6 +19,9 @@ feature.feature main-target-type : : optional incidental ; feature.feature base-target-type : : composite optional free ; # feature.feature main-target-type : : composite optional incidental ; +# Store suffixes for generated targets +.suffixes = [ new property-map ] ; + # Registers a target type, possible derived from a 'base-type'. # If 'suffixes' are provided, they given all the suffixes that mean a file is of 'type'. # Also, the first element gives the suffix to be used when constructing and object of @@ -44,7 +48,13 @@ rule register ( type : suffixes * : base-type ? : main ? ) { .types += $(type) ; .bases.$(type) = $(base-type) ; - .suffix.$(type) = $(suffixes[1]) ; + + if $(suffixes) + { + $(.suffixes).insert $(type) : $(suffixes[1]) ; + } + + .type.$(suffixes) = $(type) ; feature.extend target-type : $(type) ; @@ -117,10 +127,20 @@ rule is-derived ( type base ) } } -# Returns suffix that should be used when generating target of 'type'. -rule generated-target-suffix ( type ) +# Sets a target suffix that should be used when +# generating target of 'type' with the specified +# properties +rule set-generated-target-suffix ( type : properties + : suffix ) { - return $(.suffix.$(type)) ; + $(.suffixes).insert $(type) $(properties) : $(suffix) ; +} + + +# Returns suffix that should be used when generating target of 'type', +# with the specified properties. +rule generated-target-suffix ( type : properties * ) +{ + return [ $(.suffixes).find $(type) $(properties) ] ; } # Returns file type given its suffix. The 'suffix' parameter should include diff --git a/v2/build/virtual-target.jam b/v2/build/virtual-target.jam index 6cd152ecc..a233d7464 100644 --- a/v2/build/virtual-target.jam +++ b/v2/build/virtual-target.jam @@ -297,10 +297,12 @@ rule abstract-file-target ( name local location-grist = [ sequence.join [ regex.split $(project-location) "/" ] : "!" ] ; local grist ; + + local properties ; if $(self.action) { - local p = [ property.remove free incidental : [ $(self.action).properties ] ] ; - local property-grist = [ property.as-path $(p) ] ; + properties = [ property.remove free incidental : [ $(self.action).properties ] ] ; + local property-grist = [ property.as-path $(properties) ] ; grist = $(location-grist)/$(property-grist) ; } @@ -321,7 +323,9 @@ rule abstract-file-target ( name else if $(self.type) { self.actual-name = [ sequence.join <$(grist)>$(self.name) - [ type.generated-target-suffix $(self.type) ] : "." ] ; + [ type.generated-target-suffix $(self.type) : + $(properties) + ] : "." ] ; } else { diff --git a/v2/gcc.jam b/v2/gcc.jam index 224730f7f..0b74fd5fe 100644 --- a/v2/gcc.jam +++ b/v2/gcc.jam @@ -2,10 +2,16 @@ import property ; import generators ; import os ; +import type ; feature.extend toolset : gcc ; feature.subfeature toolset gcc : version : : optional ; +# Make the "o" suffix used for gcc toolset on all +# platforms +type.set-generated-target-suffix OBJ : gcc : o ; + + # Initializes the gcc toolset # Each argument has the form: # version binary-name [path] diff --git a/v2/test/project_test4.py b/v2/test/project_test4.py index f3b8da3e9..448413fdd 100644 --- a/v2/test/project_test4.py +++ b/v2/test/project_test4.py @@ -2,7 +2,7 @@ from BoostBuild import Tester import os -from string import strip +from string import strip, find t = Tester() @@ -45,14 +45,9 @@ t.run_build_system("--no-error-backtrace", stdout=expected, status=None) t.copy("lib/Jamfile3", "lib/Jamfile") -expected="""warning: skipped build of lib/b.obj with properties gcc shared -shared on single on -on false debug -don't know how to make <.>lib/b.obj/on -...skipped <./gcc/debug>a.exe for lack of <.>lib/b.obj/on... -""" - -t.run_build_system(stdout=expected, status=None) +t.run_build_system(status=None) +t.fail_test(find(t.stdout(), "warning: skipped build of lib/b.obj with properties") \ + != 0) # Check that project can be skipped as well t.copy("Jamfile4", "Jamfile") @@ -70,7 +65,7 @@ t.run_build_system("rtti=on", stdout=expected, status=None) # We don't yet make targets depend on Jamfile, so need to start from scratch # The following test is disabled, because of problems related to -# issue 634319 +# issue BB10 #t.set_tree("project-test4") #t.copy("Jamfile2", "Jamfile") diff --git a/v2/tools/builtin.jam b/v2/tools/builtin.jam index 62f279faf..016b9197e 100644 --- a/v2/tools/builtin.jam +++ b/v2/tools/builtin.jam @@ -20,6 +20,11 @@ import toolset ; import errors : error ; import symlink ; +# This feature is used to determine which OS we're on. +# In future, this may become and +local os = [ modules.peek : OS ] ; +feature os : $(os) : propagated link-incompatible ; + feature toolset : : implicit propagated link-incompatible symmetric ; feature link : shared static : propagated ; feature link-runtime : shared static : propagated ;