diff --git a/v2/build/generators.jam b/v2/build/generators.jam index 5500f4398..a87dab34e 100644 --- a/v2/build/generators.jam +++ b/v2/build/generators.jam @@ -58,6 +58,43 @@ if "--debug-generators" in [ modules.peek : ARGV ] } +# Clears cached viable source target type information except for target types +# and generators with all source types listed as viable. Should be called when +# something invalidates those cached values by possibly causing some new source +# types to become viable. +# +local rule invalidate-extendable-viable-source-target-type-cache ( ) +{ + local generators-with-cached-source-types = $(.vstg-cached-generators) ; + .vstg-cached-generators = ; + for local gen in $(generators-with-cached-source-types) + { + if $(.vstg.$(gen)) = * + { + .vstg-cached-generators += $(gen) ; + } + else + { + .vstg.$(gen) = ; + } + } + + local types-with-cached-source-types = $(.vst-cached-types) ; + .vst-cached-types = ; + for local type in $(types-with-cached-source-types) + { + if $(.vst.$(type)) = * + { + .vst-cached-types += $(gen) ; + } + else + { + .vst.$(type) = ; + } + } +} + + # Outputs a debug message if generators debugging is on. Each element of # 'message' is checked to see if it is a class instance. If so, instead of the # value, the result of 'str' call is output. @@ -643,6 +680,24 @@ rule register ( g ) base = $(base:B) ; } .generators-for-toolset.$(base) += $(g) ; + + + # After adding a new generator that can construct new target types, we need + # to clear the related cached viable source target type information for + # constructing a specific target type or using a specific generator. Cached + # viable source target type lists affected by this are those containing any + # of the target types constructed by the new generator or any of their base + # target types. + # + # A more advanced alternative to clearing that cached viable source target + # type information would be to expand it with additional source types or + # even better - mark it as needing to be expanded on next use. + # + # For now we just clear all the cached viable source target type information + # that does not simply state 'all types' and may implement a more detailed + # algorithm later on if it becomes needed. + + invalidate-extendable-viable-source-target-type-cache ; } @@ -783,6 +838,7 @@ rule viable-source-types ( target-type ) local key = .vst.$(target-type) ; if ! $($(key)) { + .vst-cached-types += $(target-type) ; local v = [ viable-source-types-real $(target-type) ] ; if ! $(v) { @@ -844,6 +900,7 @@ local rule viable-source-types-for-generator ( generator ) local key = .vstg.$(generator) ; if ! $($(key)) { + .vstg-cached-generators += $(generator) ; local v = [ viable-source-types-for-generator-real $(generator) ] ; if ! $(v) { diff --git a/v2/test/generator_selection.py b/v2/test/generator_selection.py new file mode 100755 index 000000000..192683ca7 --- /dev/null +++ b/v2/test/generator_selection.py @@ -0,0 +1,64 @@ +#!/usr/bin/python + +# Copyright 2008 Jurko Gospodnetic +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# Tests that generators get selected correctly. + +import BoostBuild + + +################################################################################ +# +# test_generator_added_after_already_building_a_target_of_its_target_type() +# ------------------------------------------------------------------------- +# +################################################################################ + +def test_generator_added_after_already_building_a_target_of_its_target_type(): + """Regression test for a Boost Build bug causing it to not use a generator + if it got added after already building a targer of its target type. + """ + + t = BoostBuild.Tester() + + t.write("dummy.cpp", "void f() {}\n") + + t.write("jamroot.jam", """ +# Building this dummy target must not cause a later defined CPP target type +# generator not to be recognized as viable. +obj dummy : dummy.cpp ; +alias the-other-obj : Other//other-obj ; +""") + + t.write("Other/source.extension", "A dummy source file.") + + t.write("Other/mygen.jam", """ +import generators ; +import type ; +type.register MY_TYPE : extension ; +generators.register-standard mygen.generate-a-cpp-file : MY_TYPE : CPP ; +rule generate-a-cpp-file { ECHO Generating a CPP file... ; } +actions generate-a-cpp-file { echo void g() {} > "$(<)" } +""") + + t.write("Other/jamfile.jam", """ +import mygen ; +obj other-obj : source.extension ; +""") + + t.run_build_system() + t.expect_output_line("Generating a CPP file...") + + t.cleanup() + + +################################################################################ +# +# main() +# ------ +# +################################################################################ + +test_generator_added_after_already_building_a_target_of_its_target_type() diff --git a/v2/test/test_all.py b/v2/test/test_all.py index 73f14a566..98b7fcbe5 100644 --- a/v2/test/test_all.py +++ b/v2/test/test_all.py @@ -171,7 +171,8 @@ tests = [ "rebuilds", "sort_rule", "ordered_include", "test_result_dumping", - "inherited_dependency" + "inherited_dependency", + "generator_selection" ] if os.name == 'posix':