From caa491f503c58724138a3dcd468aa2ff229837a0 Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Mon, 3 Mar 2003 07:47:14 +0000 Subject: [PATCH] Prevent the 'make' rule perform reduntant builds. Thanks to Kirill Lapshin for the bug report. * new/make.jam (make-target-class.construct): Pass the result through 'virtual-target.register'. * new/virtual-target.jam (register): Ignore incidental properties when deciding if targets are equivivalent. * test/make_rule.py: Add new test. [SVN r17701] --- new/make.jam | 2 +- new/virtual-target.jam | 20 ++++++++++++++----- test/make_rule.py | 40 +++++++++++++++++++++++++++++++++++++ v2/build/virtual-target.jam | 20 ++++++++++++++----- v2/test/make_rule.py | 40 +++++++++++++++++++++++++++++++++++++ v2/tools/make.jam | 2 +- 6 files changed, 112 insertions(+), 12 deletions(-) diff --git a/new/make.jam b/new/make.jam index 2eefa16bf..933e33036 100644 --- a/new/make.jam +++ b/new/make.jam @@ -30,7 +30,7 @@ rule make-target-class ( name : project : sources * : requirements * local a = [ new action $(t) : $(source-targets) : $(self.make-rule) : $(property-set) ] ; $(t).action $(a) ; - return $(t) ; + return [ virtual-target.register $(t) ] ; } } diff --git a/new/virtual-target.jam b/new/virtual-target.jam index 78fa8511b..d29ab1fb4 100644 --- a/new/virtual-target.jam +++ b/new/virtual-target.jam @@ -705,18 +705,28 @@ rule register ( target ) { local a1 = [ $(t).action ] ; local a2 = [ $(target).action ] ; - + if ! $(result) { if ! $(a1) && ! $(a2) { result = $(t) ; } - else if $(a1) && $(a2) && [ $(a1).action-name ] = [ $(a2).action-name ] - && [ $(a1).properties-ps ] = [ $(a2).properties-ps ] && [ $(a1).sources ] = [ $(a2).sources ] + else { - result = $(t) ; - } + if $(a1) && $(a2) && [ $(a1).action-name ] = [ $(a2).action-name ] && + [ $(a1).sources ] = [ $(a2).sources ] + { + local ps1 = [ $(a1).properties-ps ] ; + local ps2 = [ $(a2).properties-ps ] ; + local p1 = [ $(ps1).base ] [ $(ps1).free ] [ $(ps1).dependency ] ; + local p2 = [ $(ps2).base ] [ $(ps2).free ] [ $(ps2).dependency ] ; + if $(p1) = $(p2) + { + result = $(t) ; + } + } + } } } if ! $(result) diff --git a/test/make_rule.py b/test/make_rule.py index a572fb940..58e9fab2b 100644 --- a/test/make_rule.py +++ b/test/make_rule.py @@ -28,5 +28,45 @@ t.run_build_system() t.expect_addition("bin/$toolset/debug/foo.bar") t.fail_test(find(t.read("bin/$toolset/debug/foo.bar"), "foobar") == -1) +# Regression test. Make sure that if main target requested two times, +# and build request differ only in incidental properties, the main target +# if created only once. The bug was discovered by Kirill Lapshin. + +t.write("Jamfile", """ +# Make sure that incidental property does not +# cause second creation of 'hello1.cpp'. +exe a : dir/hello1.cpp ; +exe b : dir/hello1.cpp/true ; +""") + +t.write("project-root.jam", """ +import gcc ; + +rule copy-file ( targets * : sources * : * ) +{ + copy-file-action $(targets) : $(sources) ; +} + +actions copy-file-action +{ + cp $(>) $(<) +} + +IMPORT $(__name__) : copy-file : : copy-file ; +""") + +t.write("dir/Jamfile", """ +make hello1.cpp : hello.cpp : copy-file ; + +""") + +t.write("dir/hello.cpp", """ +int main() +{ + return 1; +} +""") +t.run_build_system("-d2") +t.fail_test(t.stdout().count("copy-file") != 1) t.cleanup() diff --git a/v2/build/virtual-target.jam b/v2/build/virtual-target.jam index 78fa8511b..d29ab1fb4 100644 --- a/v2/build/virtual-target.jam +++ b/v2/build/virtual-target.jam @@ -705,18 +705,28 @@ rule register ( target ) { local a1 = [ $(t).action ] ; local a2 = [ $(target).action ] ; - + if ! $(result) { if ! $(a1) && ! $(a2) { result = $(t) ; } - else if $(a1) && $(a2) && [ $(a1).action-name ] = [ $(a2).action-name ] - && [ $(a1).properties-ps ] = [ $(a2).properties-ps ] && [ $(a1).sources ] = [ $(a2).sources ] + else { - result = $(t) ; - } + if $(a1) && $(a2) && [ $(a1).action-name ] = [ $(a2).action-name ] && + [ $(a1).sources ] = [ $(a2).sources ] + { + local ps1 = [ $(a1).properties-ps ] ; + local ps2 = [ $(a2).properties-ps ] ; + local p1 = [ $(ps1).base ] [ $(ps1).free ] [ $(ps1).dependency ] ; + local p2 = [ $(ps2).base ] [ $(ps2).free ] [ $(ps2).dependency ] ; + if $(p1) = $(p2) + { + result = $(t) ; + } + } + } } } if ! $(result) diff --git a/v2/test/make_rule.py b/v2/test/make_rule.py index a572fb940..58e9fab2b 100644 --- a/v2/test/make_rule.py +++ b/v2/test/make_rule.py @@ -28,5 +28,45 @@ t.run_build_system() t.expect_addition("bin/$toolset/debug/foo.bar") t.fail_test(find(t.read("bin/$toolset/debug/foo.bar"), "foobar") == -1) +# Regression test. Make sure that if main target requested two times, +# and build request differ only in incidental properties, the main target +# if created only once. The bug was discovered by Kirill Lapshin. + +t.write("Jamfile", """ +# Make sure that incidental property does not +# cause second creation of 'hello1.cpp'. +exe a : dir/hello1.cpp ; +exe b : dir/hello1.cpp/true ; +""") + +t.write("project-root.jam", """ +import gcc ; + +rule copy-file ( targets * : sources * : * ) +{ + copy-file-action $(targets) : $(sources) ; +} + +actions copy-file-action +{ + cp $(>) $(<) +} + +IMPORT $(__name__) : copy-file : : copy-file ; +""") + +t.write("dir/Jamfile", """ +make hello1.cpp : hello.cpp : copy-file ; + +""") + +t.write("dir/hello.cpp", """ +int main() +{ + return 1; +} +""") +t.run_build_system("-d2") +t.fail_test(t.stdout().count("copy-file") != 1) t.cleanup() diff --git a/v2/tools/make.jam b/v2/tools/make.jam index 2eefa16bf..933e33036 100644 --- a/v2/tools/make.jam +++ b/v2/tools/make.jam @@ -30,7 +30,7 @@ rule make-target-class ( name : project : sources * : requirements * local a = [ new action $(t) : $(source-targets) : $(self.make-rule) : $(property-set) ] ; $(t).action $(a) ; - return $(t) ; + return [ virtual-target.register $(t) ] ; } }