diff --git a/v2/build/generators.jam b/v2/build/generators.jam index a3f04c7fe..77802458d 100644 --- a/v2/build/generators.jam +++ b/v2/build/generators.jam @@ -269,19 +269,8 @@ class generator # all generated targets. See 'generated-targets' method. : property-set # Desired properties for generated targets. : sources + # Source targets. - : multiple ? # Allows the rule to run generator several times and return - # multiple targets of the same type. When this argument is not - # given, 'run' will return the list of targets, which is equal - # in size to the list of target types, and where type of - # each target is the same as the corresponding element of - # target type list. Non-empty value allows to return several - # such target lists, joined together. - ) - { - # multiple = true ; # The tests seem to tolerate this; will - # remove the parameter altogether in the - # next revision to see what I learn -- DWA 2003/5/6 - + ) + { generators.dout [ indent ] " generator" $(self.id) ; generators.dout [ indent ] " multiple:" $(mutliple) ; generators.dout [ indent ] " composing:" $(self.composing) ; @@ -290,12 +279,7 @@ class generator { errors.error "Unsupported source/source-type combination" ; } - - if $(self.source-types[2]) - { - multiple = ; - } - + # We don't run composing generators if no name is specified. The reason # is that composing generator combines several targets, which can have # different names, and it cannot decide which name to give for produced @@ -308,12 +292,12 @@ class generator # (the OBJ -> STATIC_LIB generator is composing) if ! $(self.composing) || $(name) { - run-really $(project) $(name) : $(property-set) : $(sources) : $(multiple) ; + run-really $(project) $(name) : $(property-set) : $(sources) ; } } - rule run-really ( project name ? : property-set : sources + : multiple ? ) + rule run-really ( project name ? : property-set : sources + ) { # Targets that this generator will consume directly. local consumed = ; @@ -328,7 +312,7 @@ class generator else { convert-to-consumable-types $(project) $(name) : - $(property-set) : $(sources) : $(multiple) + $(property-set) : $(sources) : : consumed bypassed ; } @@ -338,7 +322,6 @@ class generator { result = [ construct-result $(consumed) : $(project) $(name) : $(property-set) ] ; - result += $(bypassed) ; } @@ -467,7 +450,7 @@ class generator # handle. The intention is to produce the set of targets can should be # used when generator is run. rule convert-to-consumable-types ( project name ? : - property-set : sources + : multiple ? + property-set : sources + : only-one ? # convert 'source' to only one of source types # if there's more that one possibility, report an # error @@ -510,7 +493,7 @@ class generator if $(missing-types) { local transformed = [ generators.construct-types $(project) $(name) - : $(missing-types) : $(multiple) : $(property-set) : $(sources) ] ; + : $(missing-types) : $(property-set) : $(sources) ] ; # Add targets of right type to 'consumed'. Add others to # 'bypassed'. The 'generators.construct' rule has done @@ -558,9 +541,8 @@ class generator # Converts several files to consumable types. rule convert-multiple-sources-to-consumable-types - ( project : property-set : sources * : consumed-var bypassed-var : multiple ? ) + ( project : property-set : sources * : consumed-var bypassed-var ) { - multiple ?= * ; # We process each source one-by-one, trying to convert it to # a usable type. local failed ; @@ -570,7 +552,7 @@ class generator local _b ; # TODO: need to check for failure on each source. convert-to-consumable-types $(project) : $(property-set) - : $(sources[1]) : $(multiple) : true : _c _b ; + : $(sources[1]) : true : _c _b ; if ! $(_c) { generators.dout [ indent ] " failed to convert " $(sources[1]) ; @@ -832,22 +814,15 @@ local rule viable-source-types-for-generator ( generator ) # Returns usage requirements + list of created targets -local rule try-one-generator-really ( project name ? : generator multiple ? : +local rule try-one-generator-really ( project name ? : generator : target-type : property-set : sources * ) { local targets = [ $(generator).run $(project) $(name) : $(property-set) : $(sources) - : $(multiple) ] ; - - - # Generated targets that are of required types - local result ; - # Generated target of other types. - local extra ; - + local usage-requirements ; if $(targets) && [ class.is-a $(targets[1]) : property-set ] { @@ -859,53 +834,18 @@ local rule try-one-generator-really ( project name ? : generator multiple ? : usage-requirements = [ property-set.empty ] ; } - for local t in $(targets) - { - if [ $(t).type ] = $(target-type) - { - result += $(t) ; - } - else - { - extra += $(t) ; - } - } - - # Now try to convert extra targets - # 'construct' will to its best to return only requested - # target types, so if we receive any extra from that call, - # we don't try to do anything about them. - local extra2 ; - if $(multiple) - { - for local e in $(extra) - { - local try2 = [ construct-types $(project) $(name) - : $(target-type) - : - : $(property-set) - : $(e) ] ; - usage-requirements = [ $(usage-requirements).add $(try2[1]) ] ; - result += $(try2[2-]) ; - } - } - else - { - extra2 = $(extra) ; - } generators.dout [ indent ] " generator" [ $(generator).id ] " spawned " ; - generators.dout [ indent ] " " $(result) -- $(extra2) ; + generators.dout [ indent ] " " $(targets) ; if $(targets) { - result = $(usage-requirements) $(result) ; + return $(usage-requirements) $(targets) ; } - return $(result) $(extra2) ; } # Checks if generator invocation can be pruned, because it's guaranteed # to fail. If so, quickly returns empty list. Otherwise, calls # try-one-generator-really. -local rule try-one-generator ( project name ? : generator multiple ? : +local rule try-one-generator ( project name ? : generator : target-type : property-set : sources * ) { local source-types ; @@ -926,14 +866,14 @@ local rule try-one-generator ( project name ? : generator multiple ? : } else { return [ try-one-generator-really $(project) $(name) - : $(generator) $(multiple) + : $(generator) : $(target-type) : $(property-set) : $(sources) ] ; } } -rule construct-types ( project name ? : target-types + : multiple ? : +rule construct-types ( project name ? : target-types + : property-set : sources + ) { local result ; @@ -941,7 +881,7 @@ rule construct-types ( project name ? : target-types + : multiple ? : local usage-requirements = [ property-set.empty ] ; for local t in $(target-types) { - local r = [ construct $(project) $(name) : $(t) $(multiple) : $(property-set) : + local r = [ construct $(project) $(name) : $(t) : $(property-set) : $(sources) ] ; if $(r) { @@ -1179,7 +1119,7 @@ local rule select-dependency-graph ( options ) # Attempts to construct target by finding viable generators, running them # and selecting the dependency graph local rule construct-really ( - project name ? : target-type multiple ? : property-set : sources * ) + project name ? : target-type : property-set : sources * ) { viable-generators = [ find-viable-generators $(target-type) : $(property-set) ] ; @@ -1193,7 +1133,7 @@ local rule construct-really ( # This variable will be restored on exit from this scope. local .active-generators = $(g) $(.active-generators) ; - local r = [ try-one-generator $(project) $(name) : $(g) $(multiple) : $(target-type) : + local r = [ try-one-generator $(project) $(name) : $(g) : $(target-type) : $(property-set) : $(sources) ] ; if $(r) @@ -1221,7 +1161,7 @@ local rule construct-really ( # Does not return target which are not of 'allowed-type' or of type derived from # it. If 'allowed-type' is not specified, it's defaulted to 'target-type'. # See lib-target-class for use case of this. -rule construct ( project name ? : target-type multiple ? : property-set * : sources * +rule construct ( project name ? : target-type : property-set * : sources * : allowed-type * ) { allowed-type ?= $(target-type) ; @@ -1254,12 +1194,7 @@ rule construct ( project name ? : target-type multiple ? : property-set * : sour increase-indent ; - local m ; - if $(multiple) - { - m = "(may return multiple targets)" ; - } - generators.dout [ indent ] "*** construct" $(target-type) $(m) ; + generators.dout [ indent ] "*** construct" $(target-type) ; for local s in $(sources) { @@ -1268,7 +1203,7 @@ rule construct ( project name ? : target-type multiple ? : property-set * : sour generators.dout [ indent ] " properties:" [ $(property-set).raw ] ; local result = [ construct-really $(project) $(name) - : $(target-type) $(multiple) : $(property-set) : $(sources) ] ; + : $(target-type) : $(property-set) : $(sources) ] ; decrease-indent ; diff --git a/v2/test/generators-test/extra.jam b/v2/test/generators-test/extra.jam index 638a9b764..ef639e1ef 100644 --- a/v2/test/generators-test/extra.jam +++ b/v2/test/generators-test/extra.jam @@ -1,6 +1,7 @@ import type ; import generators ; +import "class" : new ; type.register WHL : whl ; type.register DLP : dlp ; @@ -11,6 +12,46 @@ generators.register-standard extra.whale : WHL : CPP WHL_LR0 H H(%_symbols) ; generators.register-standard extra.dolphin : DLP : CPP ; generators.register-standard extra.wd : WD : WHL(%_parser) DLP(%_lexer) ; +class wd-to-cpp : generator +{ + rule __init__ ( * : * : * ) + { + generator.__init__ $(1) : $(2) : $(3) ; + } + + rule run ( project name ? : property-set : source ) + { + local new-sources ; + if ! [ $(source).type ] in WHL DLP + { + local r1 = [ generators.construct $(project) $(name) + : WHL : $(property-set) : $(source) ] ; + local r2 = [ generators.construct $(project) $(name) + : DLP : $(property-set) : $(source) ] ; + + new-sources = [ sequence.unique $(r1[2-]) $(r2[2-]) ] ; + } + else + { + new-sources = $(source) ; + } + + local result ; + for local i in $(new-sources) + { + local t = [ generators.construct $(project) $(name) : CPP + : $(property-set) : $(i) ] ; + result += $(t[2-]) ; + } + return $(result) ; + } +} +generators.override extra.wd-to-cpp : extra.whale ; +generators.override extra.wd-to-cpp : extra.dolphin ; + + +generators.register [ new wd-to-cpp extra.wd-to-cpp : : CPP ] ; + rule whale ( targets * : sources * : properties * ) { } diff --git a/v2/test/searched_lib.py b/v2/test/searched_lib.py index 2ad628850..4a411ccef 100644 --- a/v2/test/searched_lib.py +++ b/v2/test/searched_lib.py @@ -140,22 +140,4 @@ lib l : : l_f ; t.run_build_system("-n") -# A regression test. When a exe target uses obj target and -# obj target uses searched lib, the path to library was not -# added to 'exe's compile options. This is not a common use -# case, but anyway, the less surprises, the better. - -t.rm(".") -t.write("Jamroot", """ -exe a : a.cpp b ; -obj b : b.cpp s ; -lib s : : foobar ; -""") -t.write("a.cpp", "") -t.write("b.cpp", "") - -t.run_build_system("-n -d+2") -t.fail_test(string.find(t.stdout(), "foobar") == -1) - - t.cleanup() diff --git a/v2/tools/builtin.jam b/v2/tools/builtin.jam index 3780765b3..b81c08b41 100644 --- a/v2/tools/builtin.jam +++ b/v2/tools/builtin.jam @@ -307,7 +307,7 @@ class lib-generator : generator generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ; } - rule run ( project name ? : property-set : sources * : multiple ? ) + rule run ( project name ? : property-set : sources * ) { # The lib generator is composing, and can be only invoked with # explicit name. This check is present in generator.run (and so in @@ -408,7 +408,7 @@ class searched-lib-generator : generator generator.__init__ searched-lib-generator : : SEARCHED_LIB ; } - rule run ( project name ? : property-set : sources * : multiple ? ) + rule run ( project name ? : property-set : sources * ) { if $(name) { @@ -447,7 +447,7 @@ class prebuilt-lib-generator : generator generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ; } - rule run ( project name ? : property-set : sources * : multiple ? ) + rule run ( project name ? : property-set : sources * ) { local f = [ $(property-set).get ] ; return $(f) $(sources) ; @@ -532,7 +532,7 @@ class linking-generator : generator $(requirements) ; } - rule run ( project name ? : property-set : sources + : multiple ? ) + rule run ( project name ? : property-set : sources + ) { sources += [ $(property-set).get ] ; @@ -581,9 +581,10 @@ class linking-generator : generator } local result = [ generator.run $(project) $(name) : $(property-set) - : $(sources) : $(multiple) ] ; - - return [ extra-usage-requirements $(result) : $(property-set) ] $(result) ; + : $(sources) ] ; + + return [ extra-usage-requirements $(result) : $(property-set) ] + $(result) ; } rule extra-usage-requirements ( created-targets * : property-set ) @@ -617,7 +618,7 @@ class linking-generator : generator # the user, but then the user's to blaim for using internal feature. local values = [ $(property-set).get ] ; extra += $(values:G=) ; - + if $(extra) { result = [ property-set.create $(extra) ] ; @@ -687,12 +688,26 @@ class archive-generator : generator $(requirements) ; } - rule run ( project name ? : property-set : sources + : multiple ? ) + rule run ( project name ? : property-set : sources + ) { sources += [ $(property-set).get ] ; local result = [ generator.run $(project) $(name) : $(property-set) - : $(sources) : $(multiple) ] ; + : $(sources) ] ; + + # For static linking, we can't directly link to libraries. + # So, return all LIB sources together with created targets, + # so that dependents link to them. + if [ $(property-set).get ] = static + { + for local t in $(sources) + { + if [ type.is-derived [ $(t).type ] LIB ] + { + result += $(t) ; + } + } + } return $(result) ; } diff --git a/v2/tools/qt.jam b/v2/tools/qt.jam index d1645da24..8b4ba32c8 100644 --- a/v2/tools/qt.jam +++ b/v2/tools/qt.jam @@ -64,7 +64,7 @@ rule init ( prefix ? ) generator.__init__ qt.uic-cpp : UI UIC_H : CPP : qt ; } - rule run ( project name ? : properties * : sources + : multiple ? ) + rule run ( project name ? : properties * : sources + ) { # Consider this: # obj test : test_a.cpp : off ; @@ -81,13 +81,17 @@ rule init ( prefix ? ) { # Construct CPP as usual result = [ generator.run $(project) $(name) - : $(properties) : $(sources) : $(multiple) ] ; - # If OK, add "UIC_H" target to the returned list + : $(properties) : $(sources) ] ; + + # If OK, process UIC_H with moc. It's pretty clear that + # the object generated with UIC will have Q_OBJECT macro. if $(result) { local action = [ $(result[1]).action ] ; local sources = [ $(action).sources ] ; - result += $(sources[2]) ; + local mocced = [ generators.construct $(project) $(name) + : CPP : $(properties) : $(sources[2]) ] ; + result += $(mocced[2-]) ; } } diff --git a/v2/tools/unix.jam b/v2/tools/unix.jam index 2126bcc20..b85ef5809 100644 --- a/v2/tools/unix.jam +++ b/v2/tools/unix.jam @@ -35,10 +35,10 @@ class unix-linking-generator : linking-generator $(requirements) ; } - rule run ( project name ? : property-set : sources + : multiple ? ) + rule run ( project name ? : property-set : sources + ) { local result = [ linking-generator.run $(project) $(name) : $(property-set) - : $(sources) : $(multiple) ] ; + : $(sources) ] ; unix.set-library-order $(sources) : $(property-set) : $(result[2-]) ; @@ -81,10 +81,10 @@ class unix-archive-generator : archive-generator $(requirements) ; } - rule run ( project name ? : property-set : sources + : multiple ? ) + rule run ( project name ? : property-set : sources + ) { local result = [ archive-generator.run $(project) $(name) : $(property-set) - : $(sources) : $(multiple) ] ; + : $(sources) ] ; unix.set-library-order $(sources) : $(property-set) : $(result) ; @@ -107,10 +107,10 @@ class unix-searched-lib-generator : searched-lib-generator return $(self.requirements) ; } - rule run ( project name ? : property-set : sources * : multiple ? ) + rule run ( project name ? : property-set : sources * ) { local result = [ searched-lib-generator.run $(project) $(name) - : $(property-set) : $(sources) : $(multiple) ] ; + : $(property-set) : $(sources) ] ; unix.set-library-order $(sources) : $(property-set) : $(result) ; @@ -126,7 +126,7 @@ class unix-prebuilt-lib-generator : generator generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ; } - rule run ( project name ? : property-set : sources * : multiple ? ) + rule run ( project name ? : property-set : sources * ) { local f = [ $(property-set).get ] ; unix.set-library-order-aux $(f) : $(sources) ;