From e06fd02fd37b68ab97476214222d302ae308cd86 Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Wed, 22 Oct 2003 16:18:08 +0000 Subject: [PATCH] Work-in-progress on better library handling. * new/builtin.jam (link-action.adjust-properties): Remove. (linking-generator.generated-targets): Do what adjust-properties used to do. (linking-generator.run): Convert properties to sources. (exe-generator): New class. [SVN r20455] --- new/builtin.jam | 179 ++++++++++++++++++++------------ test/chain.py | 5 +- test/default_features.py | 6 +- test/generators_test.py | 13 ++- test/glob.py | 6 +- test/project_dependencies.py | 5 +- tools/gcc.jam | 2 +- tools/msvc.jam | 1 - v2/test/chain.py | 5 +- v2/test/default_features.py | 6 +- v2/test/generators_test.py | 13 ++- v2/test/glob.py | 6 +- v2/test/project_dependencies.py | 5 +- v2/tools/builtin.jam | 179 ++++++++++++++++++++------------ v2/tools/gcc.jam | 2 +- v2/tools/msvc.jam | 1 - 16 files changed, 280 insertions(+), 154 deletions(-) diff --git a/new/builtin.jam b/new/builtin.jam index 27b646610..cc35c277c 100644 --- a/new/builtin.jam +++ b/new/builtin.jam @@ -59,7 +59,8 @@ feature library : : free dependency ; feature find-shared-library : : free ; feature find-static-library : : free ; feature library-path : : free path ; -feature library-file : : free path ; +# Internal feature. +feature library-file : : free dependency ; feature uses : : free ; @@ -248,8 +249,8 @@ declare-type : SHARED_LIB : so : LIB : main ; declare-type : SEARCHED_LIB : : LIB : main ; -declare-type NT CYGWIN : EXE : exe : : main ; -declare-type : EXE : : : main ; +declare-type NT CYGWIN : EXE : exe : : ; +declare-type : EXE : : : ; declare-type : PYTHON_EXTENSION : : SHARED_LIB : main ; # We can't give "dll" suffix to PYTHON_EXTENSION, because @@ -282,7 +283,7 @@ rule response-file ( target : sources * : properties * ) local libraries ; for local p in $(properties) { - if $(p:G) = && + if $(p:G) = && ! [ type.is-derived [ $(p:G=).type ] SHARED_LIB ] { libraries += $(p:G=) ; @@ -402,6 +403,9 @@ class lib-target-class : basic-target rule construct ( source-targets * : property-set ) { + local libs = [ $(property-set).get ] ; + source-targets += $(libs:G=) ; + local properties = [ $(property-set).raw ] ; # Determine the needed target type local actual-type ; @@ -423,7 +427,7 @@ class lib-target-class : basic-target : $(property-set) : $(source-targets) : LIB ] ; } - rule compute-usage-requirements ( rproperties : created-targets ) + rule compute-usage-requirements ( rproperties : created-targets * ) { local result = [ basic-target.compute-usage-requirements $(rproperties) ] ; @@ -479,6 +483,44 @@ rule lib ( name : sources * : requirements * : default-build * } IMPORT $(__name__) : lib : : lib ; + +class exe-target-class : typed-target +{ + rule __init__ ( name : project + : sources * : requirements * : default-build * : usage-requirements * ) + { + typed-target.__init__ $(name) : $(project) : EXE + : $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ; + } + + rule construct ( source-targets * : property-set ) + { + local libs = [ $(property-set).get ] ; + source-targets += $(libs:G=) ; + + return [ typed-target.construct $(source-targets) : $(property-set) ] ; + } +} + +rule exe ( name : sources * : requirements * : default-build * + : usage-requirements * ) +{ + local project = [ CALLER_MODULE ] ; + + # This is a circular module dependency, so it must be imported here + import targets ; + targets.main-target-alternative + [ new exe-target-class $(name) : $(project) + : [ targets.main-target-sources $(sources) : $(name) ] + : [ targets.main-target-requirements $(requirements) : $(project) ] + : [ targets.main-target-default-build $(default-build) : $(project) ] + : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ] + ] ; +} +IMPORT $(__name__) : exe : : exe ; + + + class searched-lib-generator : generator { rule __init__ ( ) @@ -577,72 +619,8 @@ class link-action : action action.__init__ $(targets) : $(sources) : $(action-name) : $(properties) ; } - # Find all libraries in sources, and properties - # For each source/property-value, which is instance of searched-lib-target, - # add appropriate or property. - # (replacing the origianal is needed) - # Convert library sources into properties. - # If true is in properties, for each library source - # add property with the absolute path to that library. - rule adjust-properties ( properties * ) - { - # Identify all library sources and all properties - # Remove that latter from 'properties' - - local libraries ; - for local s in $(self.sources) - { - if [ type.is-derived [ $(s).type ] LIB ] - { - libraries += $(s) ; - } - } - local properties2 ; - for local p in $(properties) - { - if $(p:G) = - { - libraries += $(p:G=) ; - } - else - { - properties2 += $(p) ; - } - } - - # Add needed properties - local pwd = [ path.pwd ] ; - local rpaths ; - for local s in $(libraries) - { - if [ class.is-a $(s) : searched-lib-target ] - { - local name = [ $(s).real-name ] ; - if [ $(s).shared ] - { - properties2 += $(name) ; - if $(hardcore-rpath) - { - rpaths += $(search) ; - } - } - else - { - properties2 += $(name) ; - } - } - else - { - properties2 += $(s) ; - } - } - - return $(properties2) ; - } - # Filters out all sources which are of LIB type and actualizes the remaining # sources by calling base method. - # Library sources are handled by "adjust-properties" above. rule actualize-sources ( sources * ) { local real-sources ; @@ -665,6 +643,8 @@ class link-action : action class linking-generator : generator { + import property-set ; + rule __init__ ( id composing ? : # Specify if generator is composing. The generator will be # composing if non-empty string is passed, or parameter is @@ -701,7 +681,68 @@ class linking-generator : generator return $(result) ; } + rule generated-targets ( sources + : property-set : project name ? ) + { + local sources2 ; # sources to pass to inherited rule + local properties2 ; # properties to pass to inherited rule + local libraries ; # sources which are libraries + + # Separate 'sources' into 'libraries' and 'sources2'. + # It is needed because library sources need special treatment. + for local s in $(sources) + { + if [ type.is-derived [ $(s).type ] LIB ] + { + libraries += $(s) ; + } + else + { + sources2 += $(s) ; + } + } + # For all library source, add necessary property. Depending on + # target type, it's either , + # or . + properties2 = [ $(property-set).raw ] ; + for local s in $(libraries) + { + if [ class.is-a $(s) : searched-lib-target ] + { + local name = [ $(s).real-name ] ; + if [ $(s).shared ] + { + properties2 += $(name) ; + } + else + { + properties2 += $(name) ; + } + } + else + { + properties2 += $(s) ; + } + } + + # Sorry, still pass 'sources', which includes library targets. + # We need to set dependency on libraries, which is currently done + # by 'actualize-sources' above, via some secret hook. We need a better + # mechanism, but until it's implemented, need to pass all sources. + local spawn = [ generator.generated-targets $(sources) + : [ property-set.create $(properties2) ] : $(project) $(name) ] ; + + # And we'll also get warning about unused sources :-( + #if $(libraries) + #{ + # for local s in $(spawn) + # { + # $(s).depends $(libraries) ; + # } + #} + return $(spawn) ; + } + rule action-class ( ) { return link-action ; diff --git a/test/chain.py b/test/chain.py index 5fadbee45..8a9554fae 100644 --- a/test/chain.py +++ b/test/chain.py @@ -49,6 +49,9 @@ t.write("a.cpp", "") t.write("dummy.cpp", "// msvc needs at least one object file\n") t.run_build_system() -t.expect_addition("bin/$toolset/debug/a.exe") +n = t.adjust_names("bin/$toolset/debug/main-target-a/a.exe")[0] +n2 = t.adjust_names("bin/$toolset/debug/a.exe")[0] +added = t.unexpected_difference.added_files +t.fail_test(not (n in added) and not (n2 in added)) t.cleanup() diff --git a/test/default_features.py b/test/default_features.py index 3d49deeea..8674fd9a6 100644 --- a/test/default_features.py +++ b/test/default_features.py @@ -51,6 +51,10 @@ void foo() {} """) t.run_build_system() -t.expect_addition("bin/$toolset/debug/hello.exe") + +n = t.adjust_names("bin/$toolset/debug/main-target-hello/hello.exe")[0] +n2 = t.adjust_names("bin/$toolset/debug/hello.exe")[0] +added = t.unexpected_difference.added_files +t.fail_test(not (n in added) and not (n2 in added)) t.cleanup() diff --git a/test/generators_test.py b/test/generators_test.py index 79adb533a..113fa7a42 100644 --- a/test/generators_test.py +++ b/test/generators_test.py @@ -14,9 +14,18 @@ t.expect_addition( List( "a.obj b.obj c.h c.cpp c.obj d_parser.whl d_lexer.dlp d_parser.cpp d_lexer.cpp " + "d_parser.lr0 d_parser.h d_parser_symbols.h x.c x.obj y.x1 y.x2 " - + "y.cpp y.obj e.marked.cpp e.positions e.target.cpp e.obj " - + "a.exe e.exe")) + + "y.cpp y.obj e.marked.cpp e.positions e.target.cpp e.obj ")) ) +ok = 0 +# Target names differ on toolsets. +#print t.unexpected_difference.added_files +#print t.adjust_names("bin/$toolset/debug/main-target-a/a.exe") +if t.adjust_names("bin/$toolset/debug/main-target-a/a.exe")[0] in t.unexpected_difference.added_files: + ok = 1 +elif t.adjust_names("bin/$toolset/debug/a.exe")[0] in t.unexpected_difference.added_files: + ok = 1 + +t.fail_test(ok != 1) t.expect_addition(["lib/bin/$toolset/debug/c.obj", "lib/bin/$toolset/debug/auxilliary.lib", diff --git a/test/glob.py b/test/glob.py index e7484d5e5..291b86333 100644 --- a/test/glob.py +++ b/test/glob.py @@ -38,7 +38,11 @@ lib l : [ glob *.cpp ] ; """) t.run_build_system(subdir="d1") -t.expect_addition("d1/bin/$toolset/debug/a.exe") + +n = t.adjust_names("d1/bin/$toolset/debug/main-target-a/a.exe")[0] +n2 = t.adjust_names("d1/bin/$toolset/debug/a.exe")[0] +added = t.unexpected_difference.added_files +t.fail_test(not (n in added) and not (n2 in added)) t.rm("d2/d/bin") t.run_build_system(subdir="d2/d") diff --git a/test/project_dependencies.py b/test/project_dependencies.py index 1a96faa9f..e6d0dde7f 100644 --- a/test/project_dependencies.py +++ b/test/project_dependencies.py @@ -5,6 +5,8 @@ # cause every main target in the project to # be generated in it's own subdirectory. +# The whole test is somewhat moot now. + from BoostBuild import Tester, List t = Tester() @@ -38,7 +40,8 @@ t.copy("src/a.cpp", "src/b.cpp") t.run_build_system() # Test that there's no "main-target-a" part. -t.expect_addition("src/bin/$toolset/debug/" * List("a.exe b.exe")) +# t.expect_addition("src/bin/$toolset/debug/a.exe") +# t.expect_addition("src/bin/$toolset/debug/b.exe") t.cleanup() diff --git a/tools/gcc.jam b/tools/gcc.jam index dbbd2f5e2..3e8342083 100644 --- a/tools/gcc.jam +++ b/tools/gcc.jam @@ -96,7 +96,7 @@ flags gcc.link OPTIONS ; flags gcc.link LINKPATH ; flags gcc.link FINDLIBS-ST ; flags gcc.link FINDLIBS-SA ; -flags gcc.link LIBRARIES ; +flags gcc.link LIBRARIES ; flags gcc.link LINK-RUNTIME static : static ; flags gcc.link LINK-RUNTIME shared : dynamic ; flags gcc.link RPATH ; diff --git a/tools/msvc.jam b/tools/msvc.jam index 0914544bb..9f7e82d5f 100644 --- a/tools/msvc.jam +++ b/tools/msvc.jam @@ -312,7 +312,6 @@ flags msvc LINKFLAGS wince : /subsystem:windowsce ; flags msvc LINKFLAGS native : /subsystem:native ; flags msvc LINKFLAGS auto : /subsystem:posix ; -flags msvc NEEDLIBS ; flags msvc LINKFLAGS LIB/shared : /DLL ; toolset.flags msvc.link USER_LINKFLAGS ; diff --git a/v2/test/chain.py b/v2/test/chain.py index 5fadbee45..8a9554fae 100644 --- a/v2/test/chain.py +++ b/v2/test/chain.py @@ -49,6 +49,9 @@ t.write("a.cpp", "") t.write("dummy.cpp", "// msvc needs at least one object file\n") t.run_build_system() -t.expect_addition("bin/$toolset/debug/a.exe") +n = t.adjust_names("bin/$toolset/debug/main-target-a/a.exe")[0] +n2 = t.adjust_names("bin/$toolset/debug/a.exe")[0] +added = t.unexpected_difference.added_files +t.fail_test(not (n in added) and not (n2 in added)) t.cleanup() diff --git a/v2/test/default_features.py b/v2/test/default_features.py index 3d49deeea..8674fd9a6 100644 --- a/v2/test/default_features.py +++ b/v2/test/default_features.py @@ -51,6 +51,10 @@ void foo() {} """) t.run_build_system() -t.expect_addition("bin/$toolset/debug/hello.exe") + +n = t.adjust_names("bin/$toolset/debug/main-target-hello/hello.exe")[0] +n2 = t.adjust_names("bin/$toolset/debug/hello.exe")[0] +added = t.unexpected_difference.added_files +t.fail_test(not (n in added) and not (n2 in added)) t.cleanup() diff --git a/v2/test/generators_test.py b/v2/test/generators_test.py index 79adb533a..113fa7a42 100644 --- a/v2/test/generators_test.py +++ b/v2/test/generators_test.py @@ -14,9 +14,18 @@ t.expect_addition( List( "a.obj b.obj c.h c.cpp c.obj d_parser.whl d_lexer.dlp d_parser.cpp d_lexer.cpp " + "d_parser.lr0 d_parser.h d_parser_symbols.h x.c x.obj y.x1 y.x2 " - + "y.cpp y.obj e.marked.cpp e.positions e.target.cpp e.obj " - + "a.exe e.exe")) + + "y.cpp y.obj e.marked.cpp e.positions e.target.cpp e.obj ")) ) +ok = 0 +# Target names differ on toolsets. +#print t.unexpected_difference.added_files +#print t.adjust_names("bin/$toolset/debug/main-target-a/a.exe") +if t.adjust_names("bin/$toolset/debug/main-target-a/a.exe")[0] in t.unexpected_difference.added_files: + ok = 1 +elif t.adjust_names("bin/$toolset/debug/a.exe")[0] in t.unexpected_difference.added_files: + ok = 1 + +t.fail_test(ok != 1) t.expect_addition(["lib/bin/$toolset/debug/c.obj", "lib/bin/$toolset/debug/auxilliary.lib", diff --git a/v2/test/glob.py b/v2/test/glob.py index e7484d5e5..291b86333 100644 --- a/v2/test/glob.py +++ b/v2/test/glob.py @@ -38,7 +38,11 @@ lib l : [ glob *.cpp ] ; """) t.run_build_system(subdir="d1") -t.expect_addition("d1/bin/$toolset/debug/a.exe") + +n = t.adjust_names("d1/bin/$toolset/debug/main-target-a/a.exe")[0] +n2 = t.adjust_names("d1/bin/$toolset/debug/a.exe")[0] +added = t.unexpected_difference.added_files +t.fail_test(not (n in added) and not (n2 in added)) t.rm("d2/d/bin") t.run_build_system(subdir="d2/d") diff --git a/v2/test/project_dependencies.py b/v2/test/project_dependencies.py index 1a96faa9f..e6d0dde7f 100644 --- a/v2/test/project_dependencies.py +++ b/v2/test/project_dependencies.py @@ -5,6 +5,8 @@ # cause every main target in the project to # be generated in it's own subdirectory. +# The whole test is somewhat moot now. + from BoostBuild import Tester, List t = Tester() @@ -38,7 +40,8 @@ t.copy("src/a.cpp", "src/b.cpp") t.run_build_system() # Test that there's no "main-target-a" part. -t.expect_addition("src/bin/$toolset/debug/" * List("a.exe b.exe")) +# t.expect_addition("src/bin/$toolset/debug/a.exe") +# t.expect_addition("src/bin/$toolset/debug/b.exe") t.cleanup() diff --git a/v2/tools/builtin.jam b/v2/tools/builtin.jam index 27b646610..cc35c277c 100644 --- a/v2/tools/builtin.jam +++ b/v2/tools/builtin.jam @@ -59,7 +59,8 @@ feature library : : free dependency ; feature find-shared-library : : free ; feature find-static-library : : free ; feature library-path : : free path ; -feature library-file : : free path ; +# Internal feature. +feature library-file : : free dependency ; feature uses : : free ; @@ -248,8 +249,8 @@ declare-type : SHARED_LIB : so : LIB : main ; declare-type : SEARCHED_LIB : : LIB : main ; -declare-type NT CYGWIN : EXE : exe : : main ; -declare-type : EXE : : : main ; +declare-type NT CYGWIN : EXE : exe : : ; +declare-type : EXE : : : ; declare-type : PYTHON_EXTENSION : : SHARED_LIB : main ; # We can't give "dll" suffix to PYTHON_EXTENSION, because @@ -282,7 +283,7 @@ rule response-file ( target : sources * : properties * ) local libraries ; for local p in $(properties) { - if $(p:G) = && + if $(p:G) = && ! [ type.is-derived [ $(p:G=).type ] SHARED_LIB ] { libraries += $(p:G=) ; @@ -402,6 +403,9 @@ class lib-target-class : basic-target rule construct ( source-targets * : property-set ) { + local libs = [ $(property-set).get ] ; + source-targets += $(libs:G=) ; + local properties = [ $(property-set).raw ] ; # Determine the needed target type local actual-type ; @@ -423,7 +427,7 @@ class lib-target-class : basic-target : $(property-set) : $(source-targets) : LIB ] ; } - rule compute-usage-requirements ( rproperties : created-targets ) + rule compute-usage-requirements ( rproperties : created-targets * ) { local result = [ basic-target.compute-usage-requirements $(rproperties) ] ; @@ -479,6 +483,44 @@ rule lib ( name : sources * : requirements * : default-build * } IMPORT $(__name__) : lib : : lib ; + +class exe-target-class : typed-target +{ + rule __init__ ( name : project + : sources * : requirements * : default-build * : usage-requirements * ) + { + typed-target.__init__ $(name) : $(project) : EXE + : $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ; + } + + rule construct ( source-targets * : property-set ) + { + local libs = [ $(property-set).get ] ; + source-targets += $(libs:G=) ; + + return [ typed-target.construct $(source-targets) : $(property-set) ] ; + } +} + +rule exe ( name : sources * : requirements * : default-build * + : usage-requirements * ) +{ + local project = [ CALLER_MODULE ] ; + + # This is a circular module dependency, so it must be imported here + import targets ; + targets.main-target-alternative + [ new exe-target-class $(name) : $(project) + : [ targets.main-target-sources $(sources) : $(name) ] + : [ targets.main-target-requirements $(requirements) : $(project) ] + : [ targets.main-target-default-build $(default-build) : $(project) ] + : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ] + ] ; +} +IMPORT $(__name__) : exe : : exe ; + + + class searched-lib-generator : generator { rule __init__ ( ) @@ -577,72 +619,8 @@ class link-action : action action.__init__ $(targets) : $(sources) : $(action-name) : $(properties) ; } - # Find all libraries in sources, and properties - # For each source/property-value, which is instance of searched-lib-target, - # add appropriate or property. - # (replacing the origianal is needed) - # Convert library sources into properties. - # If true is in properties, for each library source - # add property with the absolute path to that library. - rule adjust-properties ( properties * ) - { - # Identify all library sources and all properties - # Remove that latter from 'properties' - - local libraries ; - for local s in $(self.sources) - { - if [ type.is-derived [ $(s).type ] LIB ] - { - libraries += $(s) ; - } - } - local properties2 ; - for local p in $(properties) - { - if $(p:G) = - { - libraries += $(p:G=) ; - } - else - { - properties2 += $(p) ; - } - } - - # Add needed properties - local pwd = [ path.pwd ] ; - local rpaths ; - for local s in $(libraries) - { - if [ class.is-a $(s) : searched-lib-target ] - { - local name = [ $(s).real-name ] ; - if [ $(s).shared ] - { - properties2 += $(name) ; - if $(hardcore-rpath) - { - rpaths += $(search) ; - } - } - else - { - properties2 += $(name) ; - } - } - else - { - properties2 += $(s) ; - } - } - - return $(properties2) ; - } - # Filters out all sources which are of LIB type and actualizes the remaining # sources by calling base method. - # Library sources are handled by "adjust-properties" above. rule actualize-sources ( sources * ) { local real-sources ; @@ -665,6 +643,8 @@ class link-action : action class linking-generator : generator { + import property-set ; + rule __init__ ( id composing ? : # Specify if generator is composing. The generator will be # composing if non-empty string is passed, or parameter is @@ -701,7 +681,68 @@ class linking-generator : generator return $(result) ; } + rule generated-targets ( sources + : property-set : project name ? ) + { + local sources2 ; # sources to pass to inherited rule + local properties2 ; # properties to pass to inherited rule + local libraries ; # sources which are libraries + + # Separate 'sources' into 'libraries' and 'sources2'. + # It is needed because library sources need special treatment. + for local s in $(sources) + { + if [ type.is-derived [ $(s).type ] LIB ] + { + libraries += $(s) ; + } + else + { + sources2 += $(s) ; + } + } + # For all library source, add necessary property. Depending on + # target type, it's either , + # or . + properties2 = [ $(property-set).raw ] ; + for local s in $(libraries) + { + if [ class.is-a $(s) : searched-lib-target ] + { + local name = [ $(s).real-name ] ; + if [ $(s).shared ] + { + properties2 += $(name) ; + } + else + { + properties2 += $(name) ; + } + } + else + { + properties2 += $(s) ; + } + } + + # Sorry, still pass 'sources', which includes library targets. + # We need to set dependency on libraries, which is currently done + # by 'actualize-sources' above, via some secret hook. We need a better + # mechanism, but until it's implemented, need to pass all sources. + local spawn = [ generator.generated-targets $(sources) + : [ property-set.create $(properties2) ] : $(project) $(name) ] ; + + # And we'll also get warning about unused sources :-( + #if $(libraries) + #{ + # for local s in $(spawn) + # { + # $(s).depends $(libraries) ; + # } + #} + return $(spawn) ; + } + rule action-class ( ) { return link-action ; diff --git a/v2/tools/gcc.jam b/v2/tools/gcc.jam index dbbd2f5e2..3e8342083 100644 --- a/v2/tools/gcc.jam +++ b/v2/tools/gcc.jam @@ -96,7 +96,7 @@ flags gcc.link OPTIONS ; flags gcc.link LINKPATH ; flags gcc.link FINDLIBS-ST ; flags gcc.link FINDLIBS-SA ; -flags gcc.link LIBRARIES ; +flags gcc.link LIBRARIES ; flags gcc.link LINK-RUNTIME static : static ; flags gcc.link LINK-RUNTIME shared : dynamic ; flags gcc.link RPATH ; diff --git a/v2/tools/msvc.jam b/v2/tools/msvc.jam index 0914544bb..9f7e82d5f 100644 --- a/v2/tools/msvc.jam +++ b/v2/tools/msvc.jam @@ -312,7 +312,6 @@ flags msvc LINKFLAGS wince : /subsystem:windowsce ; flags msvc LINKFLAGS native : /subsystem:native ; flags msvc LINKFLAGS auto : /subsystem:posix ; -flags msvc NEEDLIBS ; flags msvc LINKFLAGS LIB/shared : /DLL ; toolset.flags msvc.link USER_LINKFLAGS ;