From e07c805e312010ccb08563601191b784e6c18cd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Hunold?= Date: Fri, 17 Nov 2017 07:51:20 +0100 Subject: [PATCH 01/72] Workaround vsdevcmd_end.bat switching to %USERPROFILE%\Source Fixs #236 and PR #252 --- src/engine/config_toolset.bat | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/engine/config_toolset.bat b/src/engine/config_toolset.bat index 291459e65..b0bdfbb6f 100644 --- a/src/engine/config_toolset.bat +++ b/src/engine/config_toolset.bat @@ -172,7 +172,10 @@ if "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" ( if "_%BOOST_JAM_ARCH%_" == "__" set BOOST_JAM_ARCH=x86 set BOOST_JAM_ARGS=%BOOST_JAM_ARGS% %BOOST_JAM_ARCH% +REM return to current directory as vsdevcmd_end.bat switches to %USERPROFILE%\Source if it exists. +pushd %CD% if "_%VSINSTALLDIR%_" == "__" call :Call_If_Exists "%BOOST_JAM_TOOLSET_ROOT%Auxiliary\Build\vcvarsall.bat" %BOOST_JAM_ARGS% +popd set "BOOST_JAM_CC=cl /nologo /RTC1 /Zi /MTd /Fobootstrap/ /Fdbootstrap/ -DNT -DYYDEBUG -wd4996 kernel32.lib advapi32.lib user32.lib" set "BOOST_JAM_OPT_JAM=/Febootstrap\jam0" set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0" From 5557ee142394fe5adb81b1cc36b709c2ddb7d685 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Fri, 24 Nov 2017 14:03:14 -0700 Subject: [PATCH 02/72] Remove copy/pasted references to zlib. --- src/tools/libjpeg.jam | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/tools/libjpeg.jam b/src/tools/libjpeg.jam index 309b59df6..99accdb30 100644 --- a/src/tools/libjpeg.jam +++ b/src/tools/libjpeg.jam @@ -130,7 +130,7 @@ rule init ( condition = [ property-set.create [ $(condition).base ] ] ; local no-build-from-source ; - # Ignore environmental ZLIB_SOURCE if this initialization + # Ignore environmental LIBJPEG_SOURCE if this initialization # requested to search for a specific pre-built library. if $(library-path) || $(include-path) || $(library-name) { @@ -146,7 +146,7 @@ rule init ( } } - source-path ?= [ modules.peek : ZLIB_SOURCE ] ; + source-path ?= [ modules.peek : LIBJPEG_SOURCE ] ; if $(.configured.$(condition)) { @@ -199,7 +199,6 @@ rule init ( $(source-path) msvc:_CRT_SECURE_NO_DEPRECATE msvc:_SCL_SECURE_NO_DEPRECATE - shared:ZLIB_DLL : : $(source-path) ] ; } From 79a8a04d681b59fe9efd86c293ea6c5b5c077665 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Fri, 24 Nov 2017 14:03:23 -0700 Subject: [PATCH 03/72] Adjust jpeg test to make it pass and add it to the global list of tests. --- test/libjpeg.py | 8 ++++---- test/test_all.py | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/test/libjpeg.py b/test/libjpeg.py index dcf81c9b0..c5a3dc1be 100755 --- a/test/libjpeg.py +++ b/test/libjpeg.py @@ -13,8 +13,8 @@ t = BoostBuild.Tester(arguments=['toolset=mock', '--ignore-site-config', '--user MockToolset.create(t) # Build from source -t.write("libjpeg/jpeg.h", 'libjpeg') -t.write("libjpeg/jpeg.c", 'jpeg') +t.write("libjpeg/jpeglib.h", 'libjpeg') +t.write("libjpeg/jerror.c", 'jpeg') t.write("Jamroot.jam", """ path-constant here : . ; @@ -39,7 +39,7 @@ t.rm('libjpeg') common_stuff = ''' source_file('test.cpp', 'test.cpp') source_file('main.cpp', 'int main() {}') -source_file('jpeg.h.cpp', '#include ') +source_file('jpeg.h.cpp', '#include \\n') action('-c -x c++ $main.cpp -o $main.o') ''' t.write('test.cpp', 'test.cpp') @@ -88,7 +88,7 @@ using libjpeg : : mylibjpeg $(here)/libjpeg $(here)/libjp exe test : test.cpp /libjpeg//libjpeg : : static shared ; """) -t.write('libjpeg/jpeg.h', 'libjpeg') +t.write('libjpeg/jpeglib.h', 'libjpeg') MockToolset.set_expected(t, common_stuff + ''' action('$main.o -L./libjpeg --static-lib=mylibjpeg -o $config.exe') diff --git a/test/test_all.py b/test/test_all.py index fe97acd1a..4ffa51681 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -227,6 +227,7 @@ tests = ["absolute_sources", "inherit_toolset", "inherited_dependency", "inline", + "libjpeg", "lib_source_property", "library_chain", "library_property", From 4e6e4038c866d83da3fbf30a4c49b825bcaa3984 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Fri, 24 Nov 2017 14:39:14 -0700 Subject: [PATCH 04/72] Apply cleanup from zlib to png, tiff, and jpeg as well. --- src/tools/libjpeg.jam | 23 ++++++++++++++--------- src/tools/libpng.jam | 23 ++++++++++++++--------- src/tools/libtiff.jam | 26 +++++++++++++++----------- src/tools/zlib.jam | 1 - 4 files changed, 43 insertions(+), 30 deletions(-) diff --git a/src/tools/libjpeg.jam b/src/tools/libjpeg.jam index 99accdb30..6ee805293 100644 --- a/src/tools/libjpeg.jam +++ b/src/tools/libjpeg.jam @@ -99,7 +99,10 @@ rule init ( : is-default ? # Default configurations are only used when libjpeg - # has not yet been configured. + # has not yet been configured. This option is + # deprecated. A configuration will be treated + # as a default when none of , , + # , and are present. ) { local caller = [ project.current ] ; @@ -129,7 +132,11 @@ rule init ( condition = [ property-set.create $(requirements) ] ; condition = [ property-set.create [ $(condition).base ] ] ; - local no-build-from-source ; + if ! $(library-path) && ! $(include-path) && ! $(source-path) && ! $(library-name) + { + is-default = true ; + } + # Ignore environmental LIBJPEG_SOURCE if this initialization # requested to search for a specific pre-built library. if $(library-path) || $(include-path) || $(library-name) @@ -140,13 +147,11 @@ rule init ( [ property.select : $(options) ] "and" [ property.select : $(options) ] ; } - else - { - no-build-from-source = true ; - } } - - source-path ?= [ modules.peek : LIBJPEG_SOURCE ] ; + else + { + source-path ?= [ modules.peek : LIBJPEG_SOURCE ] ; + } if $(.configured.$(condition)) { @@ -163,7 +168,7 @@ rule init ( } return ; } - else if $(source-path) && ! $(no-build-from-source) + else if $(source-path) { build-name ?= jpeg ; library-id = [ CALC $(library-id) + 1 ] ; diff --git a/src/tools/libpng.jam b/src/tools/libpng.jam index 46e3cc9ae..0cab2eb88 100644 --- a/src/tools/libpng.jam +++ b/src/tools/libpng.jam @@ -93,7 +93,10 @@ rule init ( : is-default ? # Default configurations are only used when libpng - # has not yet been configured. + # has not yet been configured. This option is + # deprecated. A configuration will be treated + # as a default when none of , , + # , and are present. ) { local caller = [ project.current ] ; @@ -120,10 +123,14 @@ rule init ( local build-name = [ property.select : $(options) ] ; build-name = $(build-name:G=) ; + if ! $(library-path) && ! $(include-path) && ! $(source-path) && ! $(library-name) + { + is-default = true ; + } + condition = [ property-set.create $(requirements) ] ; condition = [ property-set.create [ $(condition).base ] ] ; - local no-build-from-source ; # Ignore environmental LIBPNG_SOURCE if this initialization # requested to search for a specific pre-built library. if $(library-path) || $(include-path) || $(library-name) @@ -134,13 +141,11 @@ rule init ( [ property.select : $(options) ] "and" [ property.select : $(options) ] ; } - else - { - no-build-from-source = true ; - } } - - source-path ?= [ modules.peek : LIBPNG_SOURCE ] ; + else + { + source-path ?= [ modules.peek : LIBPNG_SOURCE ] ; + } if $(.configured.$(condition)) { @@ -157,7 +162,7 @@ rule init ( } return ; } - else if $(source-path) && ! $(no-build-from-source) + else if $(source-path) { build-name ?= png ; library-id = [ CALC $(library-id) + 1 ] ; diff --git a/src/tools/libtiff.jam b/src/tools/libtiff.jam index cbd8ad015..94b94cb10 100644 --- a/src/tools/libtiff.jam +++ b/src/tools/libtiff.jam @@ -96,7 +96,10 @@ rule init ( : is-default ? # Default configurations are only used when libtiff - # has not yet been configured. + # has not yet been configured. This option is + # deprecated. A configuration will be treated + # as a default when none of , , + # , and are present. ) { local caller = [ project.current ] ; @@ -123,11 +126,15 @@ rule init ( local build-name = [ property.select : $(options) ] ; build-name = $(build-name:G=) ; + if ! $(library-path) && ! $(include-path) && ! $(source-path) && ! $(library-name) + { + is-default = true ; + } + condition = [ property-set.create $(requirements) ] ; condition = [ property-set.create [ $(condition).base ] ] ; - local no-build-from-source ; - # Ignore environmental ZLIB_SOURCE if this initialization + # Ignore environmental LIBTIFF_SOURCE if this initialization # requested to search for a specific pre-built library. if $(library-path) || $(include-path) || $(library-name) { @@ -137,13 +144,11 @@ rule init ( [ property.select : $(options) ] "and" [ property.select : $(options) ] ; } - else - { - no-build-from-source = true ; - } } - - source-path ?= [ modules.peek : ZLIB_SOURCE ] ; + else + { + source-path ?= [ modules.peek : LIBTIFF_SOURCE ] ; + } if $(.configured.$(condition)) { @@ -160,7 +165,7 @@ rule init ( } return ; } - else if $(source-path) && ! $(no-build-from-source) + else if $(source-path) { build-name ?= tiff ; library-id = [ CALC $(library-id) + 1 ] ; @@ -196,7 +201,6 @@ rule init ( $(source-path) msvc:_CRT_SECURE_NO_DEPRECATE msvc:_SCL_SECURE_NO_DEPRECATE - shared:ZLIB_DLL : : $(source-path) ] ; } diff --git a/src/tools/zlib.jam b/src/tools/zlib.jam index 45dc4767a..4651e35a7 100644 --- a/src/tools/zlib.jam +++ b/src/tools/zlib.jam @@ -132,7 +132,6 @@ rule init ( condition = [ property-set.create $(requirements) ] ; condition = [ property-set.create [ $(condition).base ] ] ; - local no-build-from-source ; # Ignore environmental ZLIB_SOURCE if this initialization # requested to search for a specific pre-built library. if $(library-path) || $(include-path) || $(library-name) From 50f13ef34a2f17e1b703f740f7b915c5301ebda0 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Fri, 24 Nov 2017 16:31:24 -0700 Subject: [PATCH 05/72] jpeglib.h requires stdio.h to be included first. --- src/build/ac.jam | 26 +++++++++++++++++++++----- src/tools/libjpeg.jam | 4 ++++ test/libjpeg.py | 2 +- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/build/ac.jam b/src/build/ac.jam index c01dc5997..8f73f329b 100644 --- a/src/build/ac.jam +++ b/src/build/ac.jam @@ -11,6 +11,7 @@ import modules ; import "class" ; import errors ; import configure ; +import feature ; import project ; import virtual-target ; import generators ; @@ -22,11 +23,21 @@ project.initialize $(__name__) ; .project = [ project.current ] ; project ac ; +feature.feature ac.print-text : : free ; + rule generate-include ( target : sources * : properties * ) { - local header = [ property.select : $(properties) ] ; print.output $(target) ; - print.text "#include <$(header:G=)>\n" : true ; + local text = [ property.select : $(properties) ] ; + if $(text) + { + print.text $(text:G=) : true ; + } + else + { + local header = [ property.select : $(properties) ] ; + print.text "#include <$(header:G=)>\n" : true ; + } } rule generate-main ( target : sources * : properties * ) @@ -35,7 +46,7 @@ rule generate-main ( target : sources * : properties * ) print.text "int main() {}" : true ; } -rule find-include-path ( properties : header : provided-path ? ) +rule find-include-path ( properties : header : provided-path ? : test-source ? ) { if $(provided-path) && [ path.exists [ path.root $(header) $(provided-path) ] ] { @@ -43,7 +54,7 @@ rule find-include-path ( properties : header : provided-path ? ) } else { - local a = [ class.new action : ac.generate-include : [ property-set.create $(header) ] ] ; + local a = [ class.new action : ac.generate-include : [ property-set.create $(header) $(test-source) ] ] ; # Create a new CPP target named after the header. # Replace dots (".") in target basename for portability. local basename = [ regex.replace $(header:D=) "[.]" "_" ] ; @@ -143,6 +154,11 @@ class ac-library : basic-target self.default-names = $(names) ; } + rule set-header-test ( source ) + { + self.header-test = $(source) ; + } + rule reconfigure ( include-path ? : library-path ? : library-name ? ) { if $(include-path) || $(library-path) || $(library-name) @@ -236,7 +252,7 @@ class ac-library : basic-target } else { - local includes = [ ac.find-include-path $(property-set) : $(self.header) : $(include-path) ] ; + local includes = [ ac.find-include-path $(property-set) : $(self.header) : $(include-path) : $(self.header-test) ] ; local library = [ ac.find-library $(property-set) : $(libnames) : $(library-path) ] ; if $(includes) && $(library) { diff --git a/src/tools/libjpeg.jam b/src/tools/libjpeg.jam index 6ee805293..f6b7ec91e 100644 --- a/src/tools/libjpeg.jam +++ b/src/tools/libjpeg.jam @@ -25,6 +25,9 @@ import property-set ; header = jpeglib.h ; +# jpeglib.h requires stdio.h to be included first. +header-test = "#include \n#include \n" ; + names = jpeg ; sources = jaricom.c jcapimin.c jcapistd.c jcarith.c jccoefct.c jccolor.c @@ -229,6 +232,7 @@ rule init ( local mt = [ new ac-library libjpeg : $(.project) : $(condition) : $(include-path) : $(library-path) : $(library-name) : $(root) ] ; $(mt).set-header $(header) ; + $(mt).set-header-test $(header-test) ; $(mt).set-default-names $(names) ; targets.main-target-alternative $(mt) ; } diff --git a/test/libjpeg.py b/test/libjpeg.py index c5a3dc1be..d98c5da90 100755 --- a/test/libjpeg.py +++ b/test/libjpeg.py @@ -39,7 +39,7 @@ t.rm('libjpeg') common_stuff = ''' source_file('test.cpp', 'test.cpp') source_file('main.cpp', 'int main() {}') -source_file('jpeg.h.cpp', '#include \\n') +source_file('jpeg.h.cpp', '#include \\n#include \\n') action('-c -x c++ $main.cpp -o $main.o') ''' t.write('test.cpp', 'test.cpp') From 6cea15c958ba3a5a60d6de40236a1f2cdbde20ae Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Mon, 27 Nov 2017 11:52:27 -0700 Subject: [PATCH 06/72] Prevent --dump-tests from executing prematurely in the face of configuration checks and skipping some output. --- src/build-system.jam | 21 +++++++++++++-------- src/tools/testing.jam | 16 ++++++---------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/build-system.jam b/src/build-system.jam index 185526c70..e38a448fb 100644 --- a/src/build-system.jam +++ b/src/build-system.jam @@ -101,16 +101,21 @@ rule set-default-toolset ( toolset : version ? ) .default-toolset-version = $(version) ; } -rule set-pre-build-hook ( function ) +rule add-pre-build-hook ( function ) { - .pre-build-hook = $(function) ; + .pre-build-hook += $(function) ; } -rule set-post-build-hook ( function ) +rule add-post-build-hook ( function ) { - .post-build-hook = $(function) ; + .post-build-hook += $(function) ; } +# Old names for backwards compatibility +IMPORT build-system : add-pre-build-hook : build-system : set-pre-build-hook ; +IMPORT build-system : add-post-build-hook : build-system : set-post-build-hook ; +EXPORT build-system : set-pre-build-hook set-post-build-hook ; + ################################################################################ # # Local rules. @@ -963,9 +968,9 @@ local rule should-clean-project ( project ) { configure.print-configure-checks-summary ; - if $(.pre-build-hook) + for local function in $(.pre-build-hook) { - $(.pre-build-hook) ; + $(function) ; } DEPENDS all : $(actual-targets) ; @@ -980,9 +985,9 @@ local rule should-clean-project ( project ) { UPDATE_NOW $(.out-xml) : : ignore-minus-n ; } - if $(.post-build-hook) + for local function in $(.post-build-hook) { - $(.post-build-hook) $(ok) ; + $(function) $(ok) ; } # Prevent automatic update of the 'all' target, now that we have # explicitly updated what we wanted. diff --git a/src/tools/testing.jam b/src/tools/testing.jam index 55576f136..0f8b646d2 100644 --- a/src/tools/testing.jam +++ b/src/tools/testing.jam @@ -34,6 +34,7 @@ import alias ; +import build-system ; import "class" ; import common ; import errors ; @@ -213,6 +214,11 @@ rule dump-tests } } +if ( --dump-tests in [ modules.peek : ARGV ] ) +{ + IMPORT testing : dump-tests : : testing.dump-tests ; + build-system.add-pre-build-hook testing.dump-tests ; +} # Given a project location in normalized form (slashes are forward), compute the # name of the Boost library. @@ -359,16 +365,6 @@ rule expect-failure ( target : dependency + : properties * ) rule **passed** { remove-test-targets $(<) ; - - # Dump all the tests, if needed. We do it here, since dump should happen - # only after all Jamfiles have been read, and there is no such place - # currently defined (but there should be). - if ! $(.dumped-tests) && ( --dump-tests in [ modules.peek : ARGV ] ) - { - .dumped-tests = true ; - dump-tests ; - } - # Force deletion of the target, in case any dependencies failed to build. RMOLD $(<) ; } From 0c3089d3c0b548f4355c0351d0118ea5166639f7 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Mon, 4 Dec 2017 17:54:49 -0700 Subject: [PATCH 07/72] Fix link-fail on Windows. FAIL_EXPECTED now works correctly for targets that have multiple updating actions. Fixes #259. --- src/engine/make1.c | 21 ++--- test/core_fail_expected.py | 74 +++++++++++++++ test/test_all.py | 1 + test/testing_support.py | 180 +++++++++++++++++++++++++++++++++++++ 4 files changed, 266 insertions(+), 10 deletions(-) create mode 100644 test/core_fail_expected.py diff --git a/src/engine/make1.c b/src/engine/make1.c index 0876bdc91..0e9c532bc 100644 --- a/src/engine/make1.c +++ b/src/engine/make1.c @@ -572,11 +572,22 @@ static void make1c( state const * const pState ) /* Tally success/failure for those we tried to update. */ if ( t->progress == T_MAKE_RUNNING ) + { + /* Invert OK/FAIL target status when FAIL_EXPECTED has been applied. */ + if ( t->flags & T_FLAG_FAIL_EXPECTED && !globs.noexec ) + { + switch ( t->status ) + { + case EXEC_CMD_FAIL: t->status = EXEC_CMD_OK; break; + case EXEC_CMD_OK: t->status = EXEC_CMD_FAIL; break; + } + } switch ( t->status ) { case EXEC_CMD_OK: ++counts->made; break; case EXEC_CMD_FAIL: ++counts->failed; break; } + } /* Tell parents their dependency has been built. */ { @@ -833,16 +844,6 @@ static void make1c_closure /* Store the target's status. */ t->status = status_orig; - /* Invert OK/FAIL target status when FAIL_EXPECTED has been applied. */ - if ( t->flags & T_FLAG_FAIL_EXPECTED && !globs.noexec ) - { - switch ( t->status ) - { - case EXEC_CMD_FAIL: t->status = EXEC_CMD_OK; break; - case EXEC_CMD_OK: t->status = EXEC_CMD_FAIL; break; - } - } - /* Ignore failures for actions marked as 'ignore'. */ if ( t->status == EXEC_CMD_FAIL && cmd->rule->actions->flags & RULE_IGNORE ) diff --git a/test/core_fail_expected.py b/test/core_fail_expected.py new file mode 100644 index 000000000..2823076b3 --- /dev/null +++ b/test/core_fail_expected.py @@ -0,0 +1,74 @@ +#!/usr/bin/python + +# Copyright 2017 Steven Watanabe +# 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) + +import BoostBuild + +def test_basic(): + t = BoostBuild.Tester(pass_toolset=0) + + t.write("file.jam", """\ + actions fail + { + invalid-dd0eeb5899734622 + } + + FAIL_EXPECTED t1 ; + fail t1 ; + + UPDATE t1 ; + """) + + t.run_build_system(["-ffile.jam"]) + + t.cleanup() + +def test_error(): + t = BoostBuild.Tester(pass_toolset=0) + + t.write("file.jam", """\ + actions pass + { + echo okay + } + + FAIL_EXPECTED t1 ; + fail t1 ; + + UPDATE t1 ; + """) + + t.run_build_system(["-ffile.jam"], status=1) + + t.cleanup() + +def test_multiple_actions(): + t = BoostBuild.Tester(pass_toolset=0) + + t.write("file.jam", """\ + actions fail + { + invalid-dd0eeb5899734622 + } + + actions pass + { + exit 0 + } + + FAIL_EXPECTED t1 ; + fail t1 ; + pass t1 ; + + UPDATE t1 ; + """) + + t.run_build_system(["-ffile.jam"]) + + t.cleanup() + +test_basic() +test_error() +test_multiple_actions() diff --git a/test/test_all.py b/test/test_all.py index 4ffa51681..c99ff0825 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -187,6 +187,7 @@ tests = ["absolute_sources", "core_actions_quietly", "core_at_file", "core_bindrule", + "core_fail_expected", "core_jamshell", "core_multifile_actions", "core_nt_cmd_line", diff --git a/test/testing_support.py b/test/testing_support.py index c76a1f2a7..ade730899 100755 --- a/test/testing_support.py +++ b/test/testing_support.py @@ -1,6 +1,7 @@ #!/usr/bin/python # Copyright 2008 Jurko Gospodnetic +# Copyright 2017 Steven Watanabe # 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) @@ -8,6 +9,179 @@ import BoostBuild +def test_run(): + t = BoostBuild.Tester(use_test_config=False) + + t.write("pass.cpp", "int main() {}\n") + t.write("fail-compile.cpp", "#error expected to fail\n") + t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") + t.write("fail-run.cpp", "int main() { return 1; }\n") + + t.write("Jamroot.jam", """import testing ; +run pass.cpp ; +run fail-compile.cpp ; +run fail-link.cpp ; +run fail-run.cpp ; +""") + + t.run_build_system(status=1) + t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") + t.expect_addition("bin/pass.test/$toolset/debug/pass.exe") + t.expect_addition("bin/pass.test/$toolset/debug/pass.output") + t.expect_addition("bin/pass.test/$toolset/debug/pass.run") + t.expect_addition("bin/pass.test/$toolset/debug/pass.test") + + t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") + + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.exe") + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.output") + + t.expect_nothing_more() + + t.cleanup() + +def test_run_fail(): + t = BoostBuild.Tester(use_test_config=False) + + t.write("pass.cpp", "int main() {}\n") + t.write("fail-compile.cpp", "#error expected to fail\n") + t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") + t.write("fail-run.cpp", "int main() { return 1; }\n") + + t.write("Jamroot.jam", """import testing ; +run-fail pass.cpp ; +run-fail fail-compile.cpp ; +run-fail fail-link.cpp ; +run-fail fail-run.cpp ; +""") + + t.run_build_system(status=1) + t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") + t.expect_addition("bin/pass.test/$toolset/debug/pass.exe") + t.expect_addition("bin/pass.test/$toolset/debug/pass.output") + + t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") + + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.exe") + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.output") + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.run") + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.test") + + t.expect_nothing_more() + + t.cleanup() + +def test_link(): + t = BoostBuild.Tester(use_test_config=False) + + t.write("pass.cpp", "int main() {}\n") + t.write("fail-compile.cpp", "#error expected to fail\n") + t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") + t.write("fail-run.cpp", "int main() { return 1; }\n") + + t.write("Jamroot.jam", """import testing ; +link pass.cpp ; +link fail-compile.cpp ; +link fail-link.cpp ; +link fail-run.cpp ; +""") + + t.run_build_system(status=1) + t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") + t.expect_addition("bin/pass.test/$toolset/debug/pass.exe") + t.expect_addition("bin/pass.test/$toolset/debug/pass.test") + + t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") + + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.exe") + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.test") + + t.expect_nothing_more() + + t.cleanup() + +def test_link_fail(): + t = BoostBuild.Tester(use_test_config=False) + + t.write("pass.cpp", "int main() {}\n") + t.write("fail-compile.cpp", "#error expected to fail\n") + t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") + t.write("fail-run.cpp", "int main() { return 1; }\n") + + t.write("Jamroot.jam", """import testing ; +link-fail pass.cpp ; +link-fail fail-compile.cpp ; +link-fail fail-link.cpp ; +link-fail fail-run.cpp ; +""") + + t.run_build_system(status=1) + t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") + + t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") + t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.exe") + t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.test") + + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") + + t.expect_nothing_more() + + t.cleanup() + +def test_compile(): + t = BoostBuild.Tester(use_test_config=False) + + t.write("pass.cpp", "int main() {}\n") + t.write("fail-compile.cpp", "#error expected to fail\n") + t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") + t.write("fail-run.cpp", "int main() { return 1; }\n") + + t.write("Jamroot.jam", """import testing ; +compile pass.cpp ; +compile fail-compile.cpp ; +compile fail-link.cpp ; +compile fail-run.cpp ; +""") + + t.run_build_system(status=1) + t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") + t.expect_addition("bin/pass.test/$toolset/debug/pass.test") + + t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") + t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.test") + + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.test") + + t.expect_nothing_more() + + t.cleanup() + +def test_compile_fail(): + t = BoostBuild.Tester(use_test_config=False) + + t.write("pass.cpp", "int main() {}\n") + t.write("fail-compile.cpp", "#error expected to fail\n") + t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") + t.write("fail-run.cpp", "int main() { return 1; }\n") + + t.write("Jamroot.jam", """import testing ; +compile-fail pass.cpp ; +compile-fail fail-compile.cpp ; +compile-fail fail-link.cpp ; +compile-fail fail-run.cpp ; +""") + + t.run_build_system(status=1) + t.expect_addition("bin/fail-compile.test/$toolset/debug/fail-compile.obj") + t.expect_addition("bin/fail-compile.test/$toolset/debug/fail-compile.test") + + t.expect_nothing_more() + + t.cleanup() ################################################################################ # @@ -58,4 +232,10 @@ testing.compile-fail "invalid source.cpp" ; # ################################################################################ +test_run() +test_run_fail() +test_link() +test_link_fail() +test_compile() +test_compile_fail() test_files_with_spaces_in_their_name() From 192dedd2ee3ab4b339e618e153dce335e8587907 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 5 Dec 2017 18:26:09 -0700 Subject: [PATCH 08/72] Fix debug builds of the debugger. Fixes #245. Fixes #246. --- src/engine/debugger.c | 4 ++-- src/engine/jam.c | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/engine/debugger.c b/src/engine/debugger.c index bb996031f..b58371d2b 100644 --- a/src/engine/debugger.c +++ b/src/engine/debugger.c @@ -1102,7 +1102,7 @@ static void debug_start_child( int argc, const char * * argv ) PROCESS_INFORMATION pi = { NULL, NULL, 0, 0 }; STARTUPINFO si = { sizeof( STARTUPINFO ), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - assert( DEBUG_STATE == DEBUG_NO_CHILD ); + assert( debug_state == DEBUG_NO_CHILD ); if ( ! CreatePipe( &pipe1[ 0 ], &pipe1[ 1 ], &sa, 0 ) ) { printf("internal error\n"); @@ -1189,7 +1189,7 @@ static void debug_start_child( int argc, const char * * argv ) int read_fd; int pid; int i; - assert( DEBUG_STATE == DEBUG_NO_CHILD ); + assert( debug_state == DEBUG_NO_CHILD ); pipe(pipe1); pipe(pipe2); pid = fork(); diff --git a/src/engine/jam.c b/src/engine/jam.c index 92686fc8d..4bca2fd7b 100644 --- a/src/engine/jam.c +++ b/src/engine/jam.c @@ -269,6 +269,7 @@ int main( int argc, char * * argv, char * * arg_environ ) #endif cwd_init(); + constants_init(); #ifdef JAM_DEBUGGER @@ -449,8 +450,6 @@ int main( int argc, char * * argv, char * * arg_environ ) /* ++globs.noexec; */ } - constants_init(); - { PROFILE_ENTER( MAIN ); From 994bad539a35d7be386a34da5be48146a0d128fe Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 5 Dec 2017 19:27:11 -0700 Subject: [PATCH 09/72] hash requires the first element of the struct to be the key. --- src/engine/filesys.c | 1 + src/engine/filesys.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/engine/filesys.c b/src/engine/filesys.c index e9612bb2f..cf6cd492c 100644 --- a/src/engine/filesys.c +++ b/src/engine/filesys.c @@ -88,6 +88,7 @@ file_archive_info_t * file_archive_info( OBJECT * const path, int * found ) if ( !*found ) { + archive->name = path_key; archive->file = 0; archive->members = FL0; } diff --git a/src/engine/filesys.h b/src/engine/filesys.h index b13853d17..24c0556d9 100644 --- a/src/engine/filesys.h +++ b/src/engine/filesys.h @@ -53,6 +53,7 @@ typedef file_info_t * * FILELISTITER; /* also &FILEITEM equivalent */ typedef struct file_archive_info_t { + OBJECT * name; file_info_t * file; FILELIST * members; } file_archive_info_t; From 4269c9e663b8975fe6e116d1242919de1af17494 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Wed, 6 Dec 2017 08:59:17 -0700 Subject: [PATCH 10/72] Revert "Fix link-fail on Windows. FAIL_EXPECTED now works correctly for targets that have multiple updating actions. Fixes #259." This reverts commit 0c3089d3c0b548f4355c0351d0118ea5166639f7. --- src/engine/make1.c | 21 +++-- test/core_fail_expected.py | 74 --------------- test/test_all.py | 1 - test/testing_support.py | 180 ------------------------------------- 4 files changed, 10 insertions(+), 266 deletions(-) delete mode 100644 test/core_fail_expected.py diff --git a/src/engine/make1.c b/src/engine/make1.c index 0e9c532bc..0876bdc91 100644 --- a/src/engine/make1.c +++ b/src/engine/make1.c @@ -572,22 +572,11 @@ static void make1c( state const * const pState ) /* Tally success/failure for those we tried to update. */ if ( t->progress == T_MAKE_RUNNING ) - { - /* Invert OK/FAIL target status when FAIL_EXPECTED has been applied. */ - if ( t->flags & T_FLAG_FAIL_EXPECTED && !globs.noexec ) - { - switch ( t->status ) - { - case EXEC_CMD_FAIL: t->status = EXEC_CMD_OK; break; - case EXEC_CMD_OK: t->status = EXEC_CMD_FAIL; break; - } - } switch ( t->status ) { case EXEC_CMD_OK: ++counts->made; break; case EXEC_CMD_FAIL: ++counts->failed; break; } - } /* Tell parents their dependency has been built. */ { @@ -844,6 +833,16 @@ static void make1c_closure /* Store the target's status. */ t->status = status_orig; + /* Invert OK/FAIL target status when FAIL_EXPECTED has been applied. */ + if ( t->flags & T_FLAG_FAIL_EXPECTED && !globs.noexec ) + { + switch ( t->status ) + { + case EXEC_CMD_FAIL: t->status = EXEC_CMD_OK; break; + case EXEC_CMD_OK: t->status = EXEC_CMD_FAIL; break; + } + } + /* Ignore failures for actions marked as 'ignore'. */ if ( t->status == EXEC_CMD_FAIL && cmd->rule->actions->flags & RULE_IGNORE ) diff --git a/test/core_fail_expected.py b/test/core_fail_expected.py deleted file mode 100644 index 2823076b3..000000000 --- a/test/core_fail_expected.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/python - -# Copyright 2017 Steven Watanabe -# 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) - -import BoostBuild - -def test_basic(): - t = BoostBuild.Tester(pass_toolset=0) - - t.write("file.jam", """\ - actions fail - { - invalid-dd0eeb5899734622 - } - - FAIL_EXPECTED t1 ; - fail t1 ; - - UPDATE t1 ; - """) - - t.run_build_system(["-ffile.jam"]) - - t.cleanup() - -def test_error(): - t = BoostBuild.Tester(pass_toolset=0) - - t.write("file.jam", """\ - actions pass - { - echo okay - } - - FAIL_EXPECTED t1 ; - fail t1 ; - - UPDATE t1 ; - """) - - t.run_build_system(["-ffile.jam"], status=1) - - t.cleanup() - -def test_multiple_actions(): - t = BoostBuild.Tester(pass_toolset=0) - - t.write("file.jam", """\ - actions fail - { - invalid-dd0eeb5899734622 - } - - actions pass - { - exit 0 - } - - FAIL_EXPECTED t1 ; - fail t1 ; - pass t1 ; - - UPDATE t1 ; - """) - - t.run_build_system(["-ffile.jam"]) - - t.cleanup() - -test_basic() -test_error() -test_multiple_actions() diff --git a/test/test_all.py b/test/test_all.py index c99ff0825..4ffa51681 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -187,7 +187,6 @@ tests = ["absolute_sources", "core_actions_quietly", "core_at_file", "core_bindrule", - "core_fail_expected", "core_jamshell", "core_multifile_actions", "core_nt_cmd_line", diff --git a/test/testing_support.py b/test/testing_support.py index ade730899..c76a1f2a7 100755 --- a/test/testing_support.py +++ b/test/testing_support.py @@ -1,7 +1,6 @@ #!/usr/bin/python # Copyright 2008 Jurko Gospodnetic -# Copyright 2017 Steven Watanabe # 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) @@ -9,179 +8,6 @@ import BoostBuild -def test_run(): - t = BoostBuild.Tester(use_test_config=False) - - t.write("pass.cpp", "int main() {}\n") - t.write("fail-compile.cpp", "#error expected to fail\n") - t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") - t.write("fail-run.cpp", "int main() { return 1; }\n") - - t.write("Jamroot.jam", """import testing ; -run pass.cpp ; -run fail-compile.cpp ; -run fail-link.cpp ; -run fail-run.cpp ; -""") - - t.run_build_system(status=1) - t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") - t.expect_addition("bin/pass.test/$toolset/debug/pass.exe") - t.expect_addition("bin/pass.test/$toolset/debug/pass.output") - t.expect_addition("bin/pass.test/$toolset/debug/pass.run") - t.expect_addition("bin/pass.test/$toolset/debug/pass.test") - - t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") - - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.exe") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.output") - - t.expect_nothing_more() - - t.cleanup() - -def test_run_fail(): - t = BoostBuild.Tester(use_test_config=False) - - t.write("pass.cpp", "int main() {}\n") - t.write("fail-compile.cpp", "#error expected to fail\n") - t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") - t.write("fail-run.cpp", "int main() { return 1; }\n") - - t.write("Jamroot.jam", """import testing ; -run-fail pass.cpp ; -run-fail fail-compile.cpp ; -run-fail fail-link.cpp ; -run-fail fail-run.cpp ; -""") - - t.run_build_system(status=1) - t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") - t.expect_addition("bin/pass.test/$toolset/debug/pass.exe") - t.expect_addition("bin/pass.test/$toolset/debug/pass.output") - - t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") - - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.exe") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.output") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.run") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.test") - - t.expect_nothing_more() - - t.cleanup() - -def test_link(): - t = BoostBuild.Tester(use_test_config=False) - - t.write("pass.cpp", "int main() {}\n") - t.write("fail-compile.cpp", "#error expected to fail\n") - t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") - t.write("fail-run.cpp", "int main() { return 1; }\n") - - t.write("Jamroot.jam", """import testing ; -link pass.cpp ; -link fail-compile.cpp ; -link fail-link.cpp ; -link fail-run.cpp ; -""") - - t.run_build_system(status=1) - t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") - t.expect_addition("bin/pass.test/$toolset/debug/pass.exe") - t.expect_addition("bin/pass.test/$toolset/debug/pass.test") - - t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") - - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.exe") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.test") - - t.expect_nothing_more() - - t.cleanup() - -def test_link_fail(): - t = BoostBuild.Tester(use_test_config=False) - - t.write("pass.cpp", "int main() {}\n") - t.write("fail-compile.cpp", "#error expected to fail\n") - t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") - t.write("fail-run.cpp", "int main() { return 1; }\n") - - t.write("Jamroot.jam", """import testing ; -link-fail pass.cpp ; -link-fail fail-compile.cpp ; -link-fail fail-link.cpp ; -link-fail fail-run.cpp ; -""") - - t.run_build_system(status=1) - t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") - - t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") - t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.exe") - t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.test") - - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") - - t.expect_nothing_more() - - t.cleanup() - -def test_compile(): - t = BoostBuild.Tester(use_test_config=False) - - t.write("pass.cpp", "int main() {}\n") - t.write("fail-compile.cpp", "#error expected to fail\n") - t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") - t.write("fail-run.cpp", "int main() { return 1; }\n") - - t.write("Jamroot.jam", """import testing ; -compile pass.cpp ; -compile fail-compile.cpp ; -compile fail-link.cpp ; -compile fail-run.cpp ; -""") - - t.run_build_system(status=1) - t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") - t.expect_addition("bin/pass.test/$toolset/debug/pass.test") - - t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") - t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.test") - - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.test") - - t.expect_nothing_more() - - t.cleanup() - -def test_compile_fail(): - t = BoostBuild.Tester(use_test_config=False) - - t.write("pass.cpp", "int main() {}\n") - t.write("fail-compile.cpp", "#error expected to fail\n") - t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") - t.write("fail-run.cpp", "int main() { return 1; }\n") - - t.write("Jamroot.jam", """import testing ; -compile-fail pass.cpp ; -compile-fail fail-compile.cpp ; -compile-fail fail-link.cpp ; -compile-fail fail-run.cpp ; -""") - - t.run_build_system(status=1) - t.expect_addition("bin/fail-compile.test/$toolset/debug/fail-compile.obj") - t.expect_addition("bin/fail-compile.test/$toolset/debug/fail-compile.test") - - t.expect_nothing_more() - - t.cleanup() ################################################################################ # @@ -232,10 +58,4 @@ testing.compile-fail "invalid source.cpp" ; # ################################################################################ -test_run() -test_run_fail() -test_link() -test_link_fail() -test_compile() -test_compile_fail() test_files_with_spaces_in_their_name() From d81254cba0872051001aed38a0c229edc4436458 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 12 Dec 2017 09:59:21 -0700 Subject: [PATCH 11/72] Fix link-fail on Windows, Take 2. FAIL_EXPECTED now works correctly for targets that have multiple updating actions. Fixes #259. --- src/engine/make1.c | 47 +++++++--- test/core_fail_expected.py | 139 ++++++++++++++++++++++++++++ test/test_all.py | 1 + test/testing_support.py | 180 +++++++++++++++++++++++++++++++++++++ 4 files changed, 355 insertions(+), 12 deletions(-) create mode 100644 test/core_fail_expected.py diff --git a/src/engine/make1.c b/src/engine/make1.c index 0876bdc91..ecc892755 100644 --- a/src/engine/make1.c +++ b/src/engine/make1.c @@ -572,11 +572,42 @@ static void make1c( state const * const pState ) /* Tally success/failure for those we tried to update. */ if ( t->progress == T_MAKE_RUNNING ) + { + /* Invert OK/FAIL target status when FAIL_EXPECTED has been applied. */ + if ( t->flags & T_FLAG_FAIL_EXPECTED && !globs.noexec ) + { + switch ( t->status ) + { + case EXEC_CMD_FAIL: t->status = EXEC_CMD_OK; break; + case EXEC_CMD_OK: t->status = EXEC_CMD_FAIL; break; + } + + /* Printing failure has to be delayed until the last + * action is completed for FAIL_EXPECTED targets. + * Do it here. + */ + if ( t->status == EXEC_CMD_FAIL ) + { + out_printf( "...failed %s ", object_str( t->actions->action->rule->name ) ); + out_printf( "%s", object_str( t->boundname ) ); + out_printf( "...\n" ); + } + + /* Handle -q */ + if ( t->status == EXEC_CMD_FAIL && globs.quitquick ) + ++quit; + + /* Delete the target on failure. */ + if ( !( t->flags & ( T_FLAG_PRECIOUS | T_FLAG_NOTFILE ) ) && + !unlink( object_str( t->boundname ) ) ) + out_printf( "...removing %s\n", object_str( t->boundname ) ); + } switch ( t->status ) { case EXEC_CMD_OK: ++counts->made; break; case EXEC_CMD_FAIL: ++counts->failed; break; } + } /* Tell parents their dependency has been built. */ { @@ -833,16 +864,6 @@ static void make1c_closure /* Store the target's status. */ t->status = status_orig; - /* Invert OK/FAIL target status when FAIL_EXPECTED has been applied. */ - if ( t->flags & T_FLAG_FAIL_EXPECTED && !globs.noexec ) - { - switch ( t->status ) - { - case EXEC_CMD_FAIL: t->status = EXEC_CMD_OK; break; - case EXEC_CMD_OK: t->status = EXEC_CMD_FAIL; break; - } - } - /* Ignore failures for actions marked as 'ignore'. */ if ( t->status == EXEC_CMD_FAIL && cmd->rule->actions->flags & RULE_IGNORE ) @@ -873,7 +894,8 @@ static void make1c_closure } /* Print command text on failure. */ - if ( t->status == EXEC_CMD_FAIL && DEBUG_MAKE ) + if ( t->status == EXEC_CMD_FAIL && DEBUG_MAKE && + ! ( t->flags & T_FLAG_FAIL_EXPECTED ) ) { if ( !DEBUG_EXEC ) out_printf( "%s\n", cmd->buf->value ); @@ -891,7 +913,8 @@ static void make1c_closure ++intr; ++quit; } - if ( t->status == EXEC_CMD_FAIL && globs.quitquick ) + if ( t->status == EXEC_CMD_FAIL && globs.quitquick && + ! ( t->flags & T_FLAG_FAIL_EXPECTED ) ) ++quit; /* If the command was not successful remove all of its targets not marked as diff --git a/test/core_fail_expected.py b/test/core_fail_expected.py new file mode 100644 index 000000000..0865a0b7a --- /dev/null +++ b/test/core_fail_expected.py @@ -0,0 +1,139 @@ +#!/usr/bin/python + +# Copyright 2017 Steven Watanabe +# 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) + +import BoostBuild + +def test_basic(): + t = BoostBuild.Tester(pass_toolset=0) + + t.write("file.jam", """\ + actions fail + { + invalid-dd0eeb5899734622 + } + + FAIL_EXPECTED t1 ; + fail t1 ; + + UPDATE t1 ; + """) + + t.run_build_system(["-ffile.jam"]) + t.expect_output_lines("...failed*", False) + t.expect_nothing_more() + + t.cleanup() + +def test_error(): + t = BoostBuild.Tester(pass_toolset=0) + + t.write("file.jam", """\ + actions pass + { + echo okay >$(<) + } + + FAIL_EXPECTED t1 ; + pass t1 ; + + UPDATE t1 ; + """) + + t.run_build_system(["-ffile.jam"], status=1) + t.expect_output_lines("...failed pass t1...") + t.expect_nothing_more() + + t.cleanup() + +def test_multiple_actions(): + """FAIL_EXPECTED targets are considered to pass if the first + updating action fails. Further actions will be skipped.""" + t = BoostBuild.Tester(pass_toolset=0) + + t.write("file.jam", """\ + actions fail + { + invalid-dd0eeb5899734622 + } + + actions pass + { + echo okay >$(<) + } + + FAIL_EXPECTED t1 ; + fail t1 ; + pass t1 ; + + UPDATE t1 ; + """) + + t.run_build_system(["-ffile.jam", "-d1"]) + t.expect_output_lines("...failed*", False) + t.expect_output_lines("pass t1", False) + t.expect_nothing_more() + + t.cleanup() + +def test_quitquick(): + """Tests that FAIL_EXPECTED targets do not cause early exit + on failure.""" + t = BoostBuild.Tester(pass_toolset=0) + + t.write("file.jam", """\ + actions fail + { + invalid-dd0eeb5899734622 + } + + actions pass + { + echo okay >$(<) + } + + FAIL_EXPECTED t1 ; + fail t1 ; + + pass t2 ; + + UPDATE t1 t2 ; + """) + + t.run_build_system(["-ffile.jam", "-q", "-d1"]) + t.expect_output_lines("pass t2") + t.expect_addition("t2") + t.expect_nothing_more() + + t.cleanup() + +def test_quitquick_error(): + """FAIL_EXPECTED targets should cause early exit if they unexpectedly pass.""" + t = BoostBuild.Tester(pass_toolset=0) + + t.write("file.jam", """\ + actions pass + { + echo okay >$(<) + } + + FAIL_EXPECTED t1 ; + pass t1 ; + pass t2 ; + + UPDATE t1 t2 ; + """) + + t.run_build_system(["-ffile.jam", "-q", "-d1"], status=1) + t.expect_output_lines("pass t2", False) + t.expect_nothing_more() + + t.cleanup() + +test_basic() +test_error() +test_multiple_actions() +test_quitquick() +test_quitquick_error() diff --git a/test/test_all.py b/test/test_all.py index 4ffa51681..c99ff0825 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -187,6 +187,7 @@ tests = ["absolute_sources", "core_actions_quietly", "core_at_file", "core_bindrule", + "core_fail_expected", "core_jamshell", "core_multifile_actions", "core_nt_cmd_line", diff --git a/test/testing_support.py b/test/testing_support.py index c76a1f2a7..ade730899 100755 --- a/test/testing_support.py +++ b/test/testing_support.py @@ -1,6 +1,7 @@ #!/usr/bin/python # Copyright 2008 Jurko Gospodnetic +# Copyright 2017 Steven Watanabe # 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) @@ -8,6 +9,179 @@ import BoostBuild +def test_run(): + t = BoostBuild.Tester(use_test_config=False) + + t.write("pass.cpp", "int main() {}\n") + t.write("fail-compile.cpp", "#error expected to fail\n") + t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") + t.write("fail-run.cpp", "int main() { return 1; }\n") + + t.write("Jamroot.jam", """import testing ; +run pass.cpp ; +run fail-compile.cpp ; +run fail-link.cpp ; +run fail-run.cpp ; +""") + + t.run_build_system(status=1) + t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") + t.expect_addition("bin/pass.test/$toolset/debug/pass.exe") + t.expect_addition("bin/pass.test/$toolset/debug/pass.output") + t.expect_addition("bin/pass.test/$toolset/debug/pass.run") + t.expect_addition("bin/pass.test/$toolset/debug/pass.test") + + t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") + + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.exe") + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.output") + + t.expect_nothing_more() + + t.cleanup() + +def test_run_fail(): + t = BoostBuild.Tester(use_test_config=False) + + t.write("pass.cpp", "int main() {}\n") + t.write("fail-compile.cpp", "#error expected to fail\n") + t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") + t.write("fail-run.cpp", "int main() { return 1; }\n") + + t.write("Jamroot.jam", """import testing ; +run-fail pass.cpp ; +run-fail fail-compile.cpp ; +run-fail fail-link.cpp ; +run-fail fail-run.cpp ; +""") + + t.run_build_system(status=1) + t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") + t.expect_addition("bin/pass.test/$toolset/debug/pass.exe") + t.expect_addition("bin/pass.test/$toolset/debug/pass.output") + + t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") + + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.exe") + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.output") + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.run") + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.test") + + t.expect_nothing_more() + + t.cleanup() + +def test_link(): + t = BoostBuild.Tester(use_test_config=False) + + t.write("pass.cpp", "int main() {}\n") + t.write("fail-compile.cpp", "#error expected to fail\n") + t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") + t.write("fail-run.cpp", "int main() { return 1; }\n") + + t.write("Jamroot.jam", """import testing ; +link pass.cpp ; +link fail-compile.cpp ; +link fail-link.cpp ; +link fail-run.cpp ; +""") + + t.run_build_system(status=1) + t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") + t.expect_addition("bin/pass.test/$toolset/debug/pass.exe") + t.expect_addition("bin/pass.test/$toolset/debug/pass.test") + + t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") + + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.exe") + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.test") + + t.expect_nothing_more() + + t.cleanup() + +def test_link_fail(): + t = BoostBuild.Tester(use_test_config=False) + + t.write("pass.cpp", "int main() {}\n") + t.write("fail-compile.cpp", "#error expected to fail\n") + t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") + t.write("fail-run.cpp", "int main() { return 1; }\n") + + t.write("Jamroot.jam", """import testing ; +link-fail pass.cpp ; +link-fail fail-compile.cpp ; +link-fail fail-link.cpp ; +link-fail fail-run.cpp ; +""") + + t.run_build_system(status=1) + t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") + + t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") + t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.exe") + t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.test") + + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") + + t.expect_nothing_more() + + t.cleanup() + +def test_compile(): + t = BoostBuild.Tester(use_test_config=False) + + t.write("pass.cpp", "int main() {}\n") + t.write("fail-compile.cpp", "#error expected to fail\n") + t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") + t.write("fail-run.cpp", "int main() { return 1; }\n") + + t.write("Jamroot.jam", """import testing ; +compile pass.cpp ; +compile fail-compile.cpp ; +compile fail-link.cpp ; +compile fail-run.cpp ; +""") + + t.run_build_system(status=1) + t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") + t.expect_addition("bin/pass.test/$toolset/debug/pass.test") + + t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") + t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.test") + + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") + t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.test") + + t.expect_nothing_more() + + t.cleanup() + +def test_compile_fail(): + t = BoostBuild.Tester(use_test_config=False) + + t.write("pass.cpp", "int main() {}\n") + t.write("fail-compile.cpp", "#error expected to fail\n") + t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") + t.write("fail-run.cpp", "int main() { return 1; }\n") + + t.write("Jamroot.jam", """import testing ; +compile-fail pass.cpp ; +compile-fail fail-compile.cpp ; +compile-fail fail-link.cpp ; +compile-fail fail-run.cpp ; +""") + + t.run_build_system(status=1) + t.expect_addition("bin/fail-compile.test/$toolset/debug/fail-compile.obj") + t.expect_addition("bin/fail-compile.test/$toolset/debug/fail-compile.test") + + t.expect_nothing_more() + + t.cleanup() ################################################################################ # @@ -58,4 +232,10 @@ testing.compile-fail "invalid source.cpp" ; # ################################################################################ +test_run() +test_run_fail() +test_link() +test_link_fail() +test_compile() +test_compile_fail() test_files_with_spaces_in_their_name() From 8cfe656d863861a60088ba934ab31f48b19ef35a Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 12 Dec 2017 12:18:02 -0700 Subject: [PATCH 12/72] Fix rebuilding of configure checks with --reconfigure or -a. --- src/build/config-cache.jam | 3 ++ src/build/configure.jam | 16 +++++++++ test/configure.py | 70 ++++++++++++++++++++++++++++++++++++++ test/test_all.py | 1 + 4 files changed, 90 insertions(+) create mode 100644 test/configure.py diff --git a/src/build/config-cache.jam b/src/build/config-cache.jam index ff69ff6f6..d97ec45d5 100644 --- a/src/build/config-cache.jam +++ b/src/build/config-cache.jam @@ -67,6 +67,9 @@ rule load ( cache-file ) cache-file = [ path.native $(cache-file) ] ; if [ path.exists $(cache-file) ] && ! ( --reconfigure in [ modules.peek : ARGV ] ) { + FILE_CONTENTS on $(cache-file) = "" ; + config-cache.write $(cache-file) ; + UPDATE_NOW $(cache-file) : [ modules.peek configure : .log-fd ] : ignore-minus-n ; include $(cache-file) ; } .cache-file = $(cache-file) ; diff --git a/src/build/configure.jam b/src/build/configure.jam index 78683d6a0..ff0f2b561 100644 --- a/src/build/configure.jam +++ b/src/build/configure.jam @@ -20,7 +20,9 @@ import targets ; import config-cache ; import feature ; import modules ; +import sequence ; import utility ; +import virtual-target ; # The configure feature allows external definition of what features are @@ -154,6 +156,20 @@ rule try-build ( targets * : ps : what : retry ? ) local result ; local jam-targets ; + # Check whether we need to force rebuild configure targets + if --reconfigure in [ modules.peek : ARGV ] + { + local all-targets ; + for local t in $(targets) + { + all-targets += [ virtual-target.traverse $(t) ] ; + } + for local t in [ sequence.unique $(all-targets) ] + { + $(t).always ; + } + } + for local t in $(targets) { jam-targets += [ $(t).actualize ] ; diff --git a/test/configure.py b/test/configure.py new file mode 100644 index 000000000..62c884683 --- /dev/null +++ b/test/configure.py @@ -0,0 +1,70 @@ +#!/usr/bin/python + +# Copyright 2017 Steven Watanabe +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Tests configure.check-target-builds and friends + +import BoostBuild + +def test_basic(): + t = BoostBuild.Tester(use_test_config=0) + t.write("Jamroot", """ +import configure ; +obj pass : pass.cpp ; +obj fail : fail.cpp ; +explicit pass fail ; +obj foo : foo.cpp : + [ configure.check-target-builds pass : PASS : FAIL ] ; +obj bar : foo.cpp : + [ configure.check-target-builds fail : FAIL : PASS ] ; +""") + t.write("pass.cpp", "void f() {}\n") + t.write("fail.cpp", "#error fail.cpp\n") + t.write("foo.cpp", """ +#ifndef PASS +#error PASS not defined +#endif +#ifdef FAIL +#error FAIL is defined +#endif +""") + t.run_build_system() + t.expect_output_lines([ + " - pass builds : yes", + " - fail builds : no"]) + t.expect_addition("bin/$toolset/debug/pass.obj") + t.expect_addition("bin/$toolset/debug/foo.obj") + t.expect_addition("bin/$toolset/debug/bar.obj") + t.expect_nothing_more() + + # An up-to-date build should use the cache + t.run_build_system() + t.expect_output_lines([ + " - pass builds : yes (cached)", + " - fail builds : no (cached)"]) + t.expect_nothing_more() + + # -a should re-run everything, including configuration checks + t.run_build_system(["-a"]) + t.expect_output_lines([ + " - pass builds : yes", + " - fail builds : no"]) + t.expect_touch("bin/$toolset/debug/pass.obj") + t.expect_touch("bin/$toolset/debug/foo.obj") + t.expect_touch("bin/$toolset/debug/bar.obj") + t.expect_nothing_more() + + # --reconfigure should re-run configuration checks only + t.run_build_system(["--reconfigure"]) + t.expect_output_lines([ + " - pass builds : yes", + " - fail builds : no"]) + t.expect_touch("bin/$toolset/debug/pass.obj") + t.expect_nothing_more() + + t.cleanup() + +test_basic() diff --git a/test/test_all.py b/test/test_all.py index c99ff0825..9d40be506 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -181,6 +181,7 @@ tests = ["absolute_sources", "conditionals3", "conditionals_multiple", "configuration", + "configure", "copy_time", "core_action_output", "core_action_status", From b000980cd3d4ae1760ef226e19c2a121cf11d820 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 12 Dec 2017 12:18:52 -0700 Subject: [PATCH 13/72] Make the caching of symlink/hardlink/junction detection more consistent. --- src/tools/link.jam | 20 ++++++++++---------- test/link.py | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/tools/link.jam b/src/tools/link.jam index 50ec485c6..3cf6e46f7 100644 --- a/src/tools/link.jam +++ b/src/tools/link.jam @@ -34,7 +34,7 @@ actions touch { $(TOUCH) "$(<)" } -rule can-symlink ( project : ps ) +rule can-symlink ( project ) { if ! $(.can-symlink) { @@ -45,7 +45,7 @@ rule can-symlink ( project : ps ) local target = [ new file-target test-symlink : : $(project) : [ new action $(source-target) : link.mklink ] ] ; - if [ configure.try-build $(target) : $(ps) : "symlinks supported" ] + if [ configure.try-build $(target) : [ property-set.empty ] : "symlinks supported" ] { .can-symlink = true ; } @@ -64,7 +64,7 @@ if [ os.name ] = NT { # Test for Windows junctions (mklink /J) -rule can-junction ( project : ps ) +rule can-junction ( project ) { if ! $(.can-junction) { @@ -75,7 +75,7 @@ rule can-junction ( project : ps ) local target = [ new file-target test-junction : : $(project) : [ new action $(source-target) : link.junction ] ] ; - if [ configure.try-build $(target) : $(ps) : "junctions supported" ] + if [ configure.try-build $(target) : [ property-set.empty ] : "junctions supported" ] { .can-junction = true ; } @@ -96,13 +96,13 @@ else .can-junction = false ; -rule can-junction ( project : ps ) +rule can-junction ( project ) { } } -rule can-hardlink ( project : ps ) +rule can-hardlink ( project ) { if ! $(.can-hardlink) { @@ -119,7 +119,7 @@ rule can-hardlink ( project : ps ) : [ new property-set symlink ] ] ] ; - if [ configure.try-build $(target) : $(ps) : "hardlinks supported" ] + if [ configure.try-build $(target) : [ property-set.empty ] : "hardlinks supported" ] { .can-hardlink = true ; } @@ -192,10 +192,10 @@ class symlink-target-class : basic-target # If we have symlinks, don't bother checking # for hardlinks and junctions. - if ! [ link.can-symlink $(self.project) : $(property-set) ] + if ! [ link.can-symlink $(self.project) ] { - link.can-junction $(self.project) : $(property-set) ; - link.can-hardlink $(self.project) : $(property-set) ; + link.can-junction $(self.project) ; + link.can-hardlink $(self.project) ; } if [ $(property-set).get ] diff --git a/test/link.py b/test/link.py index 4f83e1b09..e0524ef0e 100755 --- a/test/link.py +++ b/test/link.py @@ -279,8 +279,8 @@ def test_update_file_link(params1, params2): .has-files = [ glob include/file1.h ] ; rule can-link ( properties * ) { - if ( ! [ link.can-symlink $(.project) : [ property-set.empty ] ] ) && - ( ! [ link.can-hardlink $(.project) : [ property-set.empty ] ] ) + if ( ! [ link.can-symlink $(.project) ] ) && + ( ! [ link.can-hardlink $(.project) ] ) { ECHO links unsupported ; } From dbff38df17892f50a35f9aa576b616a066956d78 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Thu, 14 Dec 2017 10:21:05 -0700 Subject: [PATCH 14/72] Subfeature expansion should not strip trailing dashes. This was caused by the fact that a list containing only empty strings is evaluated as false, thus causing the while loop to terminate prematurely. Fixes #207. --- src/build/feature.jam | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/build/feature.jam b/src/build/feature.jam index e58edcbed..4dbe107bb 100644 --- a/src/build/feature.jam +++ b/src/build/feature.jam @@ -371,12 +371,8 @@ local rule expand-subfeatures-aux ( local result = $(components[1]:G=$(feature)) ; - local subvalues = $(components[2-]) ; - while $(subvalues) + for local subvalue in $(components[2-]) { - local subvalue = $(subvalues[1]) ; # Pop the head off of subvalues. - subvalues = $(subvalues[2-]) ; - local subfeature = [ find-implied-subfeature $(feature) $(subvalue) : $(value) ] ; @@ -385,7 +381,7 @@ local rule expand-subfeatures-aux ( { result = $(components:J=-) ; result = $(result:G=$(feature)) ; - subvalues = ; # Stop looping. + break ; } else { @@ -1202,6 +1198,9 @@ rule __test__ ( ) assert.result foo=x-y : expand-subfeatures foo=x-y ; + assert.result minus=- + : expand-subfeatures minus=- ; + assert.result gcc 3.0.1 : expand-subfeatures gcc-3.0.1 ; From 7369dd2631b857514a181dc0c3f005e57790c760 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Thu, 14 Dec 2017 12:26:24 -0700 Subject: [PATCH 15/72] Use the right setup scripts for several tools. Previously, the first setup script processed would be applied unconditionally, because api was not defined which leaves the condition blank, and later setup scripts would be applied to winapi=phone, because api was not properly localized. --- src/tools/msvc.jam | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/tools/msvc.jam b/src/tools/msvc.jam index f5e56e0c4..9b76225ab 100644 --- a/src/tools/msvc.jam +++ b/src/tools/msvc.jam @@ -1189,18 +1189,19 @@ local rule configure-really ( version ? : options * ) local cpu-assembler = $(assembler) ; cpu-assembler ?= $(default-assembler-$(c)) ; - toolset.flags msvc.compile .RC $(api)/$(cpu-conditions) : $(setup-$(c))$(resource-compiler) ; - toolset.flags msvc.compile .IDL $(api)/$(cpu-conditions) : $(setup-$(c))$(idl-compiler) ; - toolset.flags msvc.compile .MC $(api)/$(cpu-conditions) : $(setup-$(c))$(mc-compiler) ; - toolset.flags msvc.link .MT $(api)/$(cpu-conditions) : $(setup-$(c))$(manifest-tool) -nologo ; - - for api in desktop store phone + for local api in desktop store phone { local setup-script = $(setup-$(c)) ; if $(api) = phone { setup-script = $(setup-phone-$(c)) ; } + + toolset.flags msvc.compile .RC $(api)/$(cpu-conditions) : $(setup-script)$(resource-compiler) ; + toolset.flags msvc.compile .IDL $(api)/$(cpu-conditions) : $(setup-script)$(idl-compiler) ; + toolset.flags msvc.compile .MC $(api)/$(cpu-conditions) : $(setup-script)$(mc-compiler) ; + toolset.flags msvc.link .MT $(api)/$(cpu-conditions) : $(setup-script)$(manifest-tool) -nologo ; + if $(api) = desktop { toolset.flags msvc.compile .CC $(api)/$(cpu-conditions) : $(setup-script)$(compiler) /Zm800 -nologo ; From e31489760cd64c40bc4d058fc632224121bd160d Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Fri, 15 Dec 2017 15:15:54 -0700 Subject: [PATCH 16/72] breakpoints should work even if they're hit repeatedly. --- src/engine/debugger.c | 31 ++++++--- src/engine/function.c | 17 ++++- test/debugger.py | 146 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 181 insertions(+), 13 deletions(-) diff --git a/src/engine/debugger.c b/src/engine/debugger.c index b58371d2b..e2f235b9b 100644 --- a/src/engine/debugger.c +++ b/src/engine/debugger.c @@ -469,7 +469,8 @@ void debug_on_instruction( FRAME * frame, OBJECT * file, int line ) { int breakpoint_id; assert( debug_is_debugging() ); - if ( debug_state == DEBUG_NEXT && debug_depth <= 0 && debug_line != line ) + if ( debug_state == DEBUG_NEXT && + ( debug_depth < 0 || ( debug_depth == 0 && debug_line != line ) ) ) { debug_file = file; debug_line = line; @@ -483,14 +484,15 @@ void debug_on_instruction( FRAME * frame, OBJECT * file, int line ) debug_frame = frame; debug_end_stepping(); } - else if ( debug_state == DEBUG_FINISH && debug_depth <= 0 ) + else if ( debug_state == DEBUG_FINISH && debug_depth < 0 ) { debug_file = file; debug_line = line; debug_frame = frame; debug_end_stepping(); } - else if ( ( debug_file == NULL || ! object_equal( file, debug_file ) || line != debug_line ) && + else if ( ( debug_file == NULL || ! object_equal( file, debug_file ) || + line != debug_line || debug_depth != 0 ) && ( breakpoint_id = handle_line_breakpoint( file, line ) ) ) { debug_file = file; @@ -498,12 +500,19 @@ void debug_on_instruction( FRAME * frame, OBJECT * file, int line ) debug_frame = frame; debug_on_breakpoint( breakpoint_id ); } + else if ( ( debug_state == DEBUG_RUN || debug_state == DEBUG_FINISH ) && + ( debug_depth < 0 || ( debug_depth == 0 && debug_line != line ) ) ) + { + debug_file = NULL; + debug_line = 0; + } } void debug_on_enter_function( FRAME * frame, OBJECT * name, OBJECT * file, int line ) { int breakpoint_id; assert( debug_is_debugging() ); + ++debug_depth; if ( debug_state == DEBUG_STEP && file ) { debug_file = file; @@ -519,18 +528,18 @@ void debug_on_enter_function( FRAME * frame, OBJECT * name, OBJECT * file, int l debug_frame = frame; debug_on_breakpoint( breakpoint_id ); } - else if ( debug_state == DEBUG_NEXT || debug_state == DEBUG_FINISH ) - { - ++debug_depth; - } } void debug_on_exit_function( OBJECT * name ) { assert( debug_is_debugging() ); - if ( debug_state == DEBUG_NEXT || debug_state == DEBUG_FINISH ) + --debug_depth; + if ( debug_depth < 0 ) { - --debug_depth; + /* The current location is no longer valid + after we return from the containing function. */ + debug_file = NULL; + debug_line = 0; } } @@ -544,11 +553,13 @@ static int child_pid; static void debug_child_continue( int argc, const char * * argv ) { debug_state = DEBUG_RUN; + debug_depth = 0; } static void debug_child_step( int argc, const char * * argv ) { debug_state = DEBUG_STEP; + debug_depth = 0; } static void debug_child_next( int argc, const char * * argv ) @@ -560,7 +571,7 @@ static void debug_child_next( int argc, const char * * argv ) static void debug_child_finish( int argc, const char * * argv ) { debug_state = DEBUG_FINISH; - debug_depth = 1; + debug_depth = 0; } static void debug_child_kill( int argc, const char * * argv ) diff --git a/src/engine/function.c b/src/engine/function.c index 46ec40fea..d426f5386 100644 --- a/src/engine/function.c +++ b/src/engine/function.c @@ -2434,12 +2434,17 @@ static void compile_append_chain( PARSE * parse, compiler * c ) } } -static void compile_parse( PARSE * parse, compiler * c, int result_location ) +static void compile_emit_debug(compiler * c, int line) { #ifdef JAM_DEBUGGER if ( debug_is_debugging() ) - compile_emit( c, INSTR_DEBUG_LINE, parse->line ); + compile_emit( c, INSTR_DEBUG_LINE, line ); #endif +} + +static void compile_parse( PARSE * parse, compiler * c, int result_location ) +{ + compile_emit_debug(c, parse->line); if ( parse->type == PARSE_APPEND ) { compile_append_chain( parse, c ); @@ -2495,6 +2500,7 @@ static void compile_parse( PARSE * parse, compiler * c, int result_location ) compile_emit( c, INSTR_FOR_INIT, 0 ); compile_set_label( c, top ); compile_emit_branch( c, INSTR_FOR_LOOP, end ); + compile_emit_debug( c, parse->line ); compile_emit( c, INSTR_SET, var ); compile_push_break_scope( c, end ); @@ -2649,6 +2655,7 @@ static void compile_parse( PARSE * parse, compiler * c, int result_location ) group->elems, 0 ) )->s ); var_parse_group_free( group ); compile_parse( parse->right, c, RESULT_STACK ); + compile_emit_debug(c, parse->line); compile_emit( c, INSTR_PUSH_LOCAL, name ); compile_push_cleanup( c, INSTR_POP_LOCAL, name ); compile_parse( parse->third, c, nested_result ); @@ -2660,6 +2667,7 @@ static void compile_parse( PARSE * parse, compiler * c, int result_location ) var_parse_group_compile( group, c ); var_parse_group_free( group ); compile_parse( parse->right, c, RESULT_STACK ); + compile_emit_debug(c, parse->line); compile_emit( c, INSTR_PUSH_LOCAL_GROUP, 0 ); compile_push_cleanup( c, INSTR_POP_LOCAL_GROUP, 0 ); compile_parse( parse->third, c, nested_result ); @@ -2671,6 +2679,7 @@ static void compile_parse( PARSE * parse, compiler * c, int result_location ) { compile_parse( parse->left, c, RESULT_STACK ); compile_parse( parse->right, c, RESULT_STACK ); + compile_emit_debug(c, parse->line); compile_emit( c, INSTR_PUSH_LOCAL_GROUP, 0 ); compile_push_cleanup( c, INSTR_POP_LOCAL_GROUP, 0 ); compile_parse( parse->third, c, nested_result ); @@ -2820,6 +2829,7 @@ static void compile_parse( PARSE * parse, compiler * c, int result_location ) group->elems, 0 ) )->s ); var_parse_group_free( group ); compile_parse( parse->right, c, RESULT_STACK ); + compile_emit_debug(c, parse->line); if ( result_location != RESULT_NONE ) { compile_emit( c, INSTR_SET_RESULT, 1 ); @@ -2831,6 +2841,7 @@ static void compile_parse( PARSE * parse, compiler * c, int result_location ) var_parse_group_compile( group, c ); var_parse_group_free( group ); compile_parse( parse->right, c, RESULT_STACK ); + compile_emit_debug(c, parse->line); if ( result_location != RESULT_NONE ) { compile_emit( c, INSTR_SET_RESULT, 1 ); @@ -2842,6 +2853,7 @@ static void compile_parse( PARSE * parse, compiler * c, int result_location ) { compile_parse( parse->left, c, RESULT_STACK ); compile_parse( parse->right, c, RESULT_STACK ); + compile_emit_debug(c, parse->line); if ( result_location != RESULT_NONE ) { compile_emit( c, INSTR_SET_RESULT, 1 ); @@ -2875,6 +2887,7 @@ static void compile_parse( PARSE * parse, compiler * c, int result_location ) compile_parse( parse->third, c, RESULT_STACK ); compile_parse( parse->right, c, RESULT_STACK ); + compile_emit_debug(c, parse->line); switch ( parse->num ) { case ASSIGN_APPEND: compile_emit( c, INSTR_APPEND_ON, 0 ); break; diff --git a/test/debugger.py b/test/debugger.py index 9edfa84c0..7b696a0fc 100644 --- a/test/debugger.py +++ b/test/debugger.py @@ -97,6 +97,9 @@ Breakpoint 1, f ( ) at test.jam:8 """) t.cleanup() +# Note: step doesn't need to worry about breakpoints, +# as it always stops at the next line executed. + def test_next(): t = make_tester() t.write("test.jam", """\ @@ -137,6 +140,51 @@ Breakpoint 1, f ( ) at test.jam:7 """) t.cleanup() +def test_next_breakpoint(): + """next should stop if it encounters a breakpoint. + If the normal end point happens to be a breakpoint, + then it should be reported as normal stepping.""" + t = make_tester() + t.write("test.jam", """\ + rule f ( recurse ? ) + { + if $(recurse) { f ; } + a = 1 ; + } + rule g ( ) + { + b = 2 ; + } + f true ; + g ; + """) + run(t, """\ +(b2db) break f +Breakpoint 1 set at f +(b2db) break g +Breakpoint 2 set at g +(b2db) break test.jam:4 +Breakpoint 3 set at test.jam:4 +(b2db) run -ftest.jam +Starting program: {{bjam}} -ftest.jam +Breakpoint 1, f ( true ) at test.jam:3 +3 if $(recurse) { f ; } +(b2db) next +Breakpoint 1, f ( ) at test.jam:3 +3 if $(recurse) { f ; } +(b2db) next +4 a = 1 ; +(b2db) next +4 a = 1 ; +(b2db) next +11 g ; +(b2db) next +Breakpoint 2, g ( ) at test.jam:8 +8 b = 2 ; +(b2db) quit +""") + t.cleanup() + def test_finish(): t = make_tester() t.write("test.jam", """\ @@ -178,7 +226,100 @@ Breakpoint 1, f ( ) at test.jam:3 (b2db) quit """) t.cleanup() - + +def test_finish_breakpoints(): + """finish should stop when it reaches a breakpoint.""" + t = make_tester() + t.write("test.jam", """\ + rule f ( recurse * ) + { + if $(recurse) + { + a = [ f $(recurse[2-]) ] ; + } + } + rule g ( list * ) + { + for local v in $(list) + { + x = $(v) ; + } + } + f 1 2 ; + g 1 2 ; + """) + run(t, """\ +(b2db) break test.jam:5 +Breakpoint 1 set at test.jam:5 +(b2db) break test.jam:12 +Breakpoint 2 set at test.jam:12 +(b2db) run -ftest.jam +Starting program: {{bjam}} -ftest.jam +Breakpoint 1, f ( 1 2 ) at test.jam:5 +5 a = [ f $(recurse[2-]) ] ; +(b2db) finish +Breakpoint 1, f ( 2 ) at test.jam:5 +5 a = [ f $(recurse[2-]) ] ; +(b2db) finish +5 a = [ f $(recurse[2-]) ] ; +(b2db) finish +16 g 1 2 ; +(b2db) finish +Breakpoint 2, g ( 1 2 ) at test.jam:12 +12 x = $(v) ; +(b2db) finish +Breakpoint 2, g ( 1 2 ) at test.jam:12 +12 x = $(v) ; +(b2db) quit +""") + t.cleanup() + +def test_continue_breakpoints(): + """continue should stop when it reaches a breakpoint""" + t = make_tester() + t.write("test.jam", """\ + rule f ( recurse * ) + { + if $(recurse) + { + a = [ f $(recurse[2-]) ] ; + } + } + rule g ( list * ) + { + for local v in $(list) + { + x = $(v) ; + } + } + f 1 2 ; + g 1 2 ; + """) + run(t, """\ +(b2db) break test.jam:5 +Breakpoint 1 set at test.jam:5 +(b2db) break test.jam:12 +Breakpoint 2 set at test.jam:12 +(b2db) run -ftest.jam +Starting program: {{bjam}} -ftest.jam +Breakpoint 1, f ( 1 2 ) at test.jam:5 +5 a = [ f $(recurse[2-]) ] ; +(b2db) continue +Breakpoint 1, f ( 2 ) at test.jam:5 +5 a = [ f $(recurse[2-]) ] ; +(b2db) continue +Breakpoint 1, f ( 1 2 ) at test.jam:5 +5 a = [ f $(recurse[2-]) ] ; +(b2db) continue +Breakpoint 2, g ( 1 2 ) at test.jam:12 +12 x = $(v) ; +(b2db) continue +Breakpoint 2, g ( 1 2 ) at test.jam:12 +12 x = $(v) ; +(b2db) quit +""") + t.cleanup() + def test_breakpoints(): """Tests the interaction between the following commands: break, clear, delete, disable, enable""" @@ -519,7 +660,10 @@ test_run() test_exit_status() test_step() test_next() +test_next_breakpoint() test_finish() +test_finish_breakpoints() +test_continue_breakpoints() test_breakpoints() test_breakpoints_running() test_backtrace() From ff8709997ea6868587e08067716cfcda32e2ac65 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Fri, 15 Dec 2017 16:00:32 -0700 Subject: [PATCH 17/72] Fix new tests for Windows, matching 40e7f0e8dd080c3bec9df6b5ff49149ed4349260 --- test/configure.py | 14 ++++---- test/testing_support.py | 76 ++++++++++++++++++++--------------------- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/test/configure.py b/test/configure.py index 62c884683..00b007ac2 100644 --- a/test/configure.py +++ b/test/configure.py @@ -35,9 +35,9 @@ obj bar : foo.cpp : t.expect_output_lines([ " - pass builds : yes", " - fail builds : no"]) - t.expect_addition("bin/$toolset/debug/pass.obj") - t.expect_addition("bin/$toolset/debug/foo.obj") - t.expect_addition("bin/$toolset/debug/bar.obj") + t.expect_addition("bin/$toolset/debug*/pass.obj") + t.expect_addition("bin/$toolset/debug*/foo.obj") + t.expect_addition("bin/$toolset/debug*/bar.obj") t.expect_nothing_more() # An up-to-date build should use the cache @@ -52,9 +52,9 @@ obj bar : foo.cpp : t.expect_output_lines([ " - pass builds : yes", " - fail builds : no"]) - t.expect_touch("bin/$toolset/debug/pass.obj") - t.expect_touch("bin/$toolset/debug/foo.obj") - t.expect_touch("bin/$toolset/debug/bar.obj") + t.expect_touch("bin/$toolset/debug*/pass.obj") + t.expect_touch("bin/$toolset/debug*/foo.obj") + t.expect_touch("bin/$toolset/debug*/bar.obj") t.expect_nothing_more() # --reconfigure should re-run configuration checks only @@ -62,7 +62,7 @@ obj bar : foo.cpp : t.expect_output_lines([ " - pass builds : yes", " - fail builds : no"]) - t.expect_touch("bin/$toolset/debug/pass.obj") + t.expect_touch("bin/$toolset/debug*/pass.obj") t.expect_nothing_more() t.cleanup() diff --git a/test/testing_support.py b/test/testing_support.py index ade730899..f6dd5412c 100755 --- a/test/testing_support.py +++ b/test/testing_support.py @@ -25,17 +25,17 @@ run fail-run.cpp ; """) t.run_build_system(status=1) - t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") - t.expect_addition("bin/pass.test/$toolset/debug/pass.exe") - t.expect_addition("bin/pass.test/$toolset/debug/pass.output") - t.expect_addition("bin/pass.test/$toolset/debug/pass.run") - t.expect_addition("bin/pass.test/$toolset/debug/pass.test") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.obj") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.exe") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.output") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.run") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.test") - t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") + t.expect_addition("bin/fail-link.test/$toolset/debug*/fail-link.obj") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.exe") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.output") + t.expect_addition("bin/fail-run.test/$toolset/debug*/fail-run.obj") + t.expect_addition("bin/fail-run.test/$toolset/debug*/fail-run.exe") + t.expect_addition("bin/fail-run.test/$toolset/debug*/fail-run.output") t.expect_nothing_more() @@ -57,17 +57,17 @@ run-fail fail-run.cpp ; """) t.run_build_system(status=1) - t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") - t.expect_addition("bin/pass.test/$toolset/debug/pass.exe") - t.expect_addition("bin/pass.test/$toolset/debug/pass.output") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.obj") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.exe") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.output") - t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") + t.expect_addition("bin/fail-link.test/$toolset/debug*/fail-link.obj") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.exe") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.output") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.run") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.test") + t.expect_addition("bin/fail-run.test/$toolset/debug*/fail-run.obj") + t.expect_addition("bin/fail-run.test/$toolset/debug*/fail-run.exe") + t.expect_addition("bin/fail-run.test/$toolset/debug*/fail-run.output") + t.expect_addition("bin/fail-run.test/$toolset/debug*/fail-run.run") + t.expect_addition("bin/fail-run.test/$toolset/debug*/fail-run.test") t.expect_nothing_more() @@ -89,15 +89,15 @@ link fail-run.cpp ; """) t.run_build_system(status=1) - t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") - t.expect_addition("bin/pass.test/$toolset/debug/pass.exe") - t.expect_addition("bin/pass.test/$toolset/debug/pass.test") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.obj") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.exe") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.test") - t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") + t.expect_addition("bin/fail-link.test/$toolset/debug*/fail-link.obj") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.exe") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.test") + t.expect_addition("bin/fail-run.test/$toolset/debug*/fail-run.obj") + t.expect_addition("bin/fail-run.test/$toolset/debug*/fail-run.exe") + t.expect_addition("bin/fail-run.test/$toolset/debug*/fail-run.test") t.expect_nothing_more() @@ -119,13 +119,13 @@ link-fail fail-run.cpp ; """) t.run_build_system(status=1) - t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.obj") - t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") - t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.exe") - t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.test") + t.expect_addition("bin/fail-link.test/$toolset/debug*/fail-link.obj") + t.expect_addition("bin/fail-link.test/$toolset/debug*/fail-link.exe") + t.expect_addition("bin/fail-link.test/$toolset/debug*/fail-link.test") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") + t.expect_addition("bin/fail-run.test/$toolset/debug*/fail-run.obj") t.expect_nothing_more() @@ -147,14 +147,14 @@ compile fail-run.cpp ; """) t.run_build_system(status=1) - t.expect_addition("bin/pass.test/$toolset/debug/pass.obj") - t.expect_addition("bin/pass.test/$toolset/debug/pass.test") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.obj") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.test") - t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.obj") - t.expect_addition("bin/fail-link.test/$toolset/debug/fail-link.test") + t.expect_addition("bin/fail-link.test/$toolset/debug*/fail-link.obj") + t.expect_addition("bin/fail-link.test/$toolset/debug*/fail-link.test") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.obj") - t.expect_addition("bin/fail-run.test/$toolset/debug/fail-run.test") + t.expect_addition("bin/fail-run.test/$toolset/debug*/fail-run.obj") + t.expect_addition("bin/fail-run.test/$toolset/debug*/fail-run.test") t.expect_nothing_more() @@ -176,8 +176,8 @@ compile-fail fail-run.cpp ; """) t.run_build_system(status=1) - t.expect_addition("bin/fail-compile.test/$toolset/debug/fail-compile.obj") - t.expect_addition("bin/fail-compile.test/$toolset/debug/fail-compile.test") + t.expect_addition("bin/fail-compile.test/$toolset/debug*/fail-compile.obj") + t.expect_addition("bin/fail-compile.test/$toolset/debug*/fail-compile.test") t.expect_nothing_more() From 4d58880c2085c969c3e41f1f56b86b31aee3875a Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 16 Dec 2017 12:15:45 -0700 Subject: [PATCH 18/72] Move the msvc setup scripts from TEMP into the build directory. They are created as virtual-targets, so --clean-all should work as well. The scripts will also be auto-updated if their timestamps are older than the originals. Refs #257. --- src/tools/msvc.jam | 275 +++++++++++++++++++++++++++++---------------- 1 file changed, 177 insertions(+), 98 deletions(-) diff --git a/src/tools/msvc.jam b/src/tools/msvc.jam index 9b76225ab..f096e64f4 100644 --- a/src/tools/msvc.jam +++ b/src/tools/msvc.jam @@ -31,11 +31,14 @@ import midl ; import os ; import path ; import pch ; +import project ; import property ; +import property-set ; import rc ; import set ; import toolset ; import type ; +import virtual-target ; type.register MANIFEST : manifest ; @@ -138,7 +141,7 @@ rule init ( # # # Whether to rewrite setup scripts. New scripts will be output in - # TEMP directory and will be used instead of originals in build actions. + # build tree and will be used instead of originals in build actions. # Possible values: # * on - rewrite scripts, if they do not already exist (default) # * always - always rewrite scripts, even if they already exist @@ -325,7 +328,7 @@ if [ os.name ] in NT actions archive { if exist "$(<[1])" DEL "$(<[1])" - $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")" + $(.SETUP) $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")" } } else @@ -333,10 +336,14 @@ else actions archive { $(.RM) "$(<[1])" - $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")" + $(.SETUP) $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")" } } +rule compile.asm ( targets + : sources * : properties * ) +{ + set-setup-command $(targets) : $(properties) ; +} # For the assembler the following options are turned on by default: # @@ -346,12 +353,13 @@ else # actions compile.asm { - $(.ASM) -c -Zp4 -Cp -Cx -D$(DEFINES) $(ASMFLAGS) $(USER_ASMFLAGS) -Fo "$(<:W)" "$(>:W)" + $(.SETUP) $(.ASM) -c -Zp4 -Cp -Cx -D$(DEFINES) $(ASMFLAGS) $(USER_ASMFLAGS) -Fo "$(<:W)" "$(>:W)" } rule compile.c ( targets + : sources * : properties * ) { + set-setup-command $(targets) : $(properties) ; C++FLAGS on $(targets[1]) = ; get-rspline $(targets) : -TC ; compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ; @@ -360,6 +368,7 @@ rule compile.c ( targets + : sources * : properties * ) rule compile.c.preprocess ( targets + : sources * : properties * ) { + set-setup-command $(targets) : $(properties) ; C++FLAGS on $(targets[1]) = ; get-rspline $(targets) : -TC ; preprocess-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ; @@ -368,6 +377,7 @@ rule compile.c.preprocess ( targets + : sources * : properties * ) rule compile.c.pch ( targets + : sources * : properties * ) { + set-setup-command $(targets) : $(properties) ; C++FLAGS on $(targets[1]) = ; get-rspline $(targets[1]) : -TC ; get-rspline $(targets[2]) : -TC ; @@ -405,12 +415,12 @@ toolset.flags msvc YLOPTION : "-Yl" ; # actions compile-c-c++ bind PDB_NAME { - $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -Fo"$(<[1]:W)" $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" $(.CC.FILTER) + $(.SETUP) $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -Fo"$(<[1]:W)" $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" $(.CC.FILTER) } actions preprocess-c-c++ bind PDB_NAME { - $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -E $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" >"$(<[1]:W)" + $(.SETUP) $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -E $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" >"$(<[1]:W)" } rule compile-c-c++ ( targets + : sources * ) @@ -437,7 +447,7 @@ rule preprocess-c-c++ ( targets + : sources * ) # syntax highlighting in the messy N-quoted code below. actions compile-c-c++-pch { - $(.CC) @"@($(<[1]:W).rsp:E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE))" "@($(<[1]:W).cpp:E=#include $(.escaped-double-quote)$(>[1]:D=)$(.escaped-double-quote)$(.nl))" $(.CC.FILTER) + $(.SETUP) $(.CC) @"@($(<[1]:W).rsp:E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE))" "@($(<[1]:W).cpp:E=#include $(.escaped-double-quote)$(>[1]:D=)$(.escaped-double-quote)$(.nl))" $(.CC.FILTER) } @@ -446,18 +456,20 @@ actions compile-c-c++-pch # given as one of the source parameters. actions compile-c-c++-pch-s { - $(.CC) @"@($(<[1]:W).rsp:E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE))" $(.CC.FILTER) + $(.SETUP) $(.CC) @"@($(<[1]:W).rsp:E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE))" $(.CC.FILTER) } rule compile.c++ ( targets + : sources * : properties * ) { + set-setup-command $(targets) : $(properties) ; get-rspline $(targets) : -TP ; compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ; } rule compile.c++.preprocess ( targets + : sources * : properties * ) { + set-setup-command $(targets) : $(properties) ; get-rspline $(targets) : -TP ; preprocess-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ; } @@ -465,6 +477,7 @@ rule compile.c++.preprocess ( targets + : sources * : properties * ) rule compile.c++.pch ( targets + : sources * : properties * ) { + set-setup-command $(targets) : $(properties) ; get-rspline $(targets[1]) : -TP ; get-rspline $(targets[2]) : -TP ; local pch-source = [ on $(<) return $(PCH_SOURCE) ] ; @@ -479,31 +492,45 @@ rule compile.c++.pch ( targets + : sources * : properties * ) } } +rule compile.idl ( targets + : sources * : properties * ) +{ + set-setup-command $(targets) : $(properties) ; +} # See midl.jam for details. # actions compile.idl { - $(.IDL) /nologo @"@($(<[1]:W).rsp:E=$(.nl)"$(>:W)" $(.nl)-D$(DEFINES) $(.nl)"-I$(INCLUDES:W)" $(.nl)-U$(UNDEFS) $(.nl)$(MIDLFLAGS) $(.nl)/tlb "$(<[1]:W)" $(.nl)/h "$(<[2]:W)" $(.nl)/iid "$(<[3]:W)" $(.nl)/proxy "$(<[4]:W)" $(.nl)/dlldata "$(<[5]:W)")" + $(.SETUP) $(.IDL) /nologo @"@($(<[1]:W).rsp:E=$(.nl)"$(>:W)" $(.nl)-D$(DEFINES) $(.nl)"-I$(INCLUDES:W)" $(.nl)-U$(UNDEFS) $(.nl)$(MIDLFLAGS) $(.nl)/tlb "$(<[1]:W)" $(.nl)/h "$(<[2]:W)" $(.nl)/iid "$(<[3]:W)" $(.nl)/proxy "$(<[4]:W)" $(.nl)/dlldata "$(<[5]:W)")" $(.TOUCH_FILE) "$(<[4]:W)" $(.TOUCH_FILE) "$(<[5]:W)" } +rule compile.mc ( targets + : sources * : properties * ) +{ + set-setup-command $(targets) : $(properties) ; +} actions compile.mc { - $(.MC) $(MCFLAGS) -h "$(<[1]:DW)" -r "$(<[2]:DW)" "$(>:W)" + $(.SETUP) $(.MC) $(MCFLAGS) -h "$(<[1]:DW)" -r "$(<[2]:DW)" "$(>:W)" } +rule compile.rc ( targets + : sources * : properties * ) +{ + set-setup-command $(targets) : $(properties) ; +} + actions compile.rc { - $(.RC) -l 0x409 -U$(UNDEFS) -D$(DEFINES) -I"$(INCLUDES:W)" -fo "$(<:W)" "$(>:W)" + $(.SETUP) $(.RC) -l 0x409 -U$(UNDEFS) -D$(DEFINES) -I"$(INCLUDES:W)" -fo "$(<:W)" "$(>:W)" } rule link ( targets + : sources * : properties * ) { + set-setup-command $(targets) : $(properties) ; if on in $(properties) { if [ feature.get-values : $(properties) ] @@ -520,6 +547,7 @@ rule link ( targets + : sources * : properties * ) rule link.dll ( targets + : sources * : properties * ) { + set-setup-command $(targets) : $(properties) ; DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ; if on in $(properties) { @@ -549,44 +577,44 @@ if [ os.name ] in NT { actions link bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE { - $(.LD) $(LINKFLAGS) /out:"$(<[1]:W)" /LIBPATH:"$(LINKPATH:W)" $(OPTIONS) @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")" + $(.SETUP) $(.LD) $(LINKFLAGS) /out:"$(<[1]:W)" /LIBPATH:"$(LINKPATH:W)" $(OPTIONS) @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")" if %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL% } actions manifest { if exist "$(<[1]).manifest" ( - $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);1" + $(.SETUP) $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);1" ) } actions manifest.user bind EMBED_MANIFEST_FILE { - $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);1" + $(.SETUP) $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);1" } actions link.dll bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE { - $(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(<[2]:W)" /LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" $(OPTIONS) @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")" + $(.SETUP) $(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(<[2]:W)" /LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" $(OPTIONS) @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")" if %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL% } actions manifest.dll { if exist "$(<[1]).manifest" ( - $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);2" + $(.SETUP) $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);2" ) } actions manifest.dll.user bind EMBED_MANIFEST_FILE { - $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);2" + $(.SETUP) $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);2" } } else { actions link bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE { - $(.LD) $(LINKFLAGS) /out:"$(<[1]:W)" /LIBPATH:"$(LINKPATH:W)" $(OPTIONS) @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")" + $(.SETUP) $(.LD) $(LINKFLAGS) /out:"$(<[1]:W)" /LIBPATH:"$(LINKPATH:W)" $(OPTIONS) @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")" } actions manifest @@ -598,19 +626,19 @@ else actions link.dll bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE { - $(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(<[2]:W)" /LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" $(OPTIONS) @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")" + $(.SETUP) $(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(<[2]:W)" /LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" $(OPTIONS) @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")" } actions manifest.dll { if test -e "$(<[1]).manifest"; then - $(.MT) -manifest "$(<[1]:W).manifest" "-outputresource:$(<[1]:W);2" + $(.SETUP) $(.MT) -manifest "$(<[1]:W).manifest" "-outputresource:$(<[1]:W);2" fi } actions manifest.dll.user bind EMBED_MANIFEST_FILE { - $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);2" + $(.SETUP) $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);2" } } @@ -623,6 +651,7 @@ else # rule archive ( targets + : sources * : properties * ) { + set-setup-command $(targets) : $(properties) ; PDB_NAME on $(>) = $(<[1]:S=.pdb) ; LOCATE on $(<[1]:S=.pdb) = [ on $(<[1]) return $(LOCATE) ] ; } @@ -737,72 +766,34 @@ local rule auto-detect-toolset-versions ( ) } } -# Helper rule to generate a faster alternative to MSVC setup scripts. -# We used to call MSVC setup scripts directly in every action, however in -# newer MSVC versions (10.0+) they make long-lasting registry queries -# which have a significant impact on build time. -rule maybe-rewrite-setup ( toolset : setup-script : setup-options : version : rewrite-setup ? ) -{ - local result = $(setup-script)" "$(setup-options) ; - # At the moment we only know how to rewrite scripts with cmd shell. - if ( [ os.name ] in NT ) && ( $(rewrite-setup) != off ) - { - setup-script-id = b2_$(toolset)_$(version)_$(setup-script:B) ; - if $(setup-options)-is-not-empty - { - setup-script-id = $(setup-script-id)_$(setup-options) ; - } - - if $(.$(setup-script-id)) - { - errors.error rewriting setup script for the second time ; - } - - local tmpdir = [ os.environ TEMP ] ; - local replacement = [ path.native $(tmpdir)/$(setup-script-id).cmd ] ; - if ( $(rewrite-setup) = always ) || ( ! [ path.exists $(replacement) ] ) - { - local original-vars = [ SPLIT_BY_CHARACTERS [ SHELL set ] : "\n" ] ; - local new-vars = [ SPLIT_BY_CHARACTERS [ SHELL "$(setup-script) $(setup-options)>nul && set" ] : "\n" ] ; - local diff-vars = [ set.difference $(new-vars) : $(original-vars) ] ; - if $(diff-vars) - { - local target = $(replacement) ; - FILE_CONTENTS on $(target) = "SET "$(diff-vars) ; - ALWAYS $(target) ; - msvc.write-setup-script $(target) ; - UPDATE_NOW $(target) : : ignore-minus-n ; - .$(setup-script-id) = $(replacement) ; - result = "\""$(replacement)"\"" ; - } - } - else - { - result = "\""$(replacement)"\"" ; - } - } - return $(result) ; -} - actions write-setup-script { @($(STDOUT):E=$(FILE_CONTENTS:J=$(.nl))) > "$(<)" } +if [ os.name ] = NT +{ + local rule call-batch-script ( command ) + { + return "call $(command) >nul$(.nl)" ; + } +} +else +{ + # On cygwin, we need to run both the batch script + # and the following command in the same instance + # of cmd.exe. + local rule call-batch-script ( command ) + { + return "cmd.exe /S /C call $(command) \">nul\" \"&&\" " ; + } +} # Local helper rule to create the vcvars setup command for given architecture # and options. # local rule generate-setup-cmd ( version : command : parent : options * : cpu : global-setup ? : default-global-setup-options : default-setup ) { - local setup-prefix = "call " ; - local setup-suffix = " >nul"$(.nl) ; - if ! [ os.name ] in NT - { - setup-prefix = "cmd.exe /S /C call " ; - setup-suffix = " \">nul\" \"&&\" " ; - } - local setup-options ; local setup = [ feature.get-values : $(options) ] ; @@ -833,19 +824,81 @@ local rule generate-setup-cmd ( version : command : parent : options * : cpu : g } } - # Cygwin to Windows path translation. - setup = "\""$(setup:W)"\"" ; - - # Append setup options to the setup name and add the final setup - # prefix & suffix. - setup-options ?= "" ; - local rewrite = [ feature.get-values : $(options) ] ; - setup = [ maybe-rewrite-setup msvc : $(setup:J=" ") : $(setup-options:J=" ") : $(version) : $(rewrite) ] ; - setup = $(setup-prefix)$(setup)$(setup-suffix) ; - - return $(setup) ; + return $(setup) "$(setup-options:J= )" ; } +# Worker for set-setup-command. Usable in a virtual-target.action. +rule adjust-setup-command ( new-setup : setup : properties * ) +{ + local internal = $(new-setup:S=.read) ; + NOTFILE $(internal) ; + local setup-options = [ property.select : $(properties) ] ; + setup-options = $(setup-options:G=:E=) ; + DEPENDS $(internal) : $(setup) ; + DEPENDS $(new-setup) : $(internal) ; + REBUILDS $(new-setup) : $(internal) ; + msvc.read-setup $(internal) : $(setup) ; + msvc.write-setup-script $(new-setup) : $(setup) ; + __ACTION_RULE__ on $(internal) = msvc.rewrite-setup $(setup) $(setup-options) $(new-setup) ; +} + +# This doesn't actually do anything. It's merely +# used as a trigger for __ACTION_RULE__. +actions quietly read-setup { } + +# Calculates the changes to the environment make by setup-script +# Should be used as a callback for __ACTION_RULE__ +local rule rewrite-setup ( setup-script setup-options new-setup : target : * ) +{ + local setup-path = [ on $(setup-script) return $(LOCATE) $(SEARCH) ] ; + setup-path = $(setup-path[1]) ; + local command = "\"$(setup-script:G=:R=$(setup-path))\" $(setup-options)" ; + local original-vars = [ SPLIT_BY_CHARACTERS [ SHELL set ] : "\n" ] ; + local new-vars = [ SPLIT_BY_CHARACTERS [ SHELL "$(command) >nul && set" ] : "\n" ] ; + local diff-vars = [ set.difference $(new-vars) : $(original-vars) ] ; + if $(diff-vars) + { + FILE_CONTENTS on $(new-setup) = "REM $(command)" "SET "$(diff-vars) ; + } +} + +IMPORT msvc : rewrite-setup : : msvc.rewrite-setup ; + +# Helper rule to generate a faster alternative to MSVC setup scripts. +# We used to call MSVC setup scripts directly in every action, however in +# newer MSVC versions (10.0+) they make long-lasting registry queries +# which have a significant impact on build time. +local rule set-setup-command ( targets * : properties * ) +{ + if ! [ on $(targets) return $(.SETUP) ] + { + local setup-script = [ on $(targets) return $(.SETUP-SCRIPT) ] ; + local setup-options = [ on $(targets) return $(.SETUP-OPTIONS) ] ; + local key = .setup-command-$(setup-script:E=)-$(setup-options:E=) ; + if ! $($(key)) + { + properties = [ feature.expand $(properties) ] ; + properties = [ property.select : $(properties) ] ; + local ps = [ property-set.create $(properties) $(setup-options) ] ; + local original = [ virtual-target.from-file $(setup-script) : [ path.pwd ] : $(.project) ] ; + local action = [ new non-scanning-action $(original) : msvc.adjust-setup-command : $(ps) ] ; + local new-setup = [ virtual-target.register [ new file-target msvc-setup.bat exact : : $(.project) : $(action) ] ] ; + local command = [ $(new-setup).actualize ] ; + local path = [ on $(command) return $(LOCATE) ] ; + local block-update = $(command:S=.nup) ; + NOUPDATE $(block-update) ; + NOTFILE $(block-update) ; + DEPENDS $(block-update) : $(command) ; + if [ on $(targets) return $(.REWRITE-SETUP) ] + { + ALWAYS $(command) ; + } + $(key) = [ call-batch-script "\"$(command:WG=:R=$(path))\" $(setup-options:E=)" ] $(block-update) ; + } + DEPENDS $(targets) : $($(key)[2]) ; + .SETUP on $(targets) = $($(key)[1]) ; + } +} # Worker rule for toolset version configuration. Takes an explicit version id or # nothing in case it should configure the default toolset version (the first @@ -1197,22 +1250,41 @@ local rule configure-really ( version ? : options * ) setup-script = $(setup-phone-$(c)) ; } - toolset.flags msvc.compile .RC $(api)/$(cpu-conditions) : $(setup-script)$(resource-compiler) ; - toolset.flags msvc.compile .IDL $(api)/$(cpu-conditions) : $(setup-script)$(idl-compiler) ; - toolset.flags msvc.compile .MC $(api)/$(cpu-conditions) : $(setup-script)$(mc-compiler) ; - toolset.flags msvc.link .MT $(api)/$(cpu-conditions) : $(setup-script)$(manifest-tool) -nologo ; - - if $(api) = desktop + if always in $(options) { - toolset.flags msvc.compile .CC $(api)/$(cpu-conditions) : $(setup-script)$(compiler) /Zm800 -nologo ; + toolset.flags msvc .REWRITE-SETUP $(api)/$(cpu-conditions) : true ; + } + + if ! $(setup-script) + { + # Should we try to set up some error handling or fallbacks here? + } + else if off in $(options) || [ os.name ] != NT + { + toolset.flags msvc .SETUP $(api)/$(cpu-conditions) : [ call-batch-script "\"$(setup-script[1]:W)\" $(setup-script[2-]:E=)" ] ; } else { - toolset.flags msvc.compile .CC $(api)/$(cpu-conditions) : $(setup-script)$(compiler) /Zm800 /ZW /EHsc -nologo ; + toolset.flags msvc .SETUP-SCRIPT $(api)/$(cpu-conditions) : $(setup-script[1]) ; + toolset.flags msvc .SETUP-OPTIONS $(api)/$(cpu-conditions) : $(setup-script[2-]) ; } - toolset.flags msvc.compile .ASM $(api)/$(cpu-conditions) : $(setup-script)$(cpu-assembler) -nologo ; - toolset.flags msvc.link .LD $(api)/$(cpu-conditions) : $(setup-script)$(linker) /NOLOGO /INCREMENTAL:NO ; - toolset.flags msvc.archive .LD $(api)/$(cpu-conditions) : $(setup-script)$(linker) /lib /NOLOGO ; + + toolset.flags msvc.compile .RC $(api)/$(cpu-conditions) : $(resource-compiler) ; + toolset.flags msvc.compile .IDL $(api)/$(cpu-conditions) : $(idl-compiler) ; + toolset.flags msvc.compile .MC $(api)/$(cpu-conditions) : $(mc-compiler) ; + toolset.flags msvc.link .MT $(api)/$(cpu-conditions) : $(manifest-tool) -nologo ; + + if $(api) = desktop + { + toolset.flags msvc.compile .CC $(api)/$(cpu-conditions) : $(compiler) /Zm800 -nologo ; + } + else + { + toolset.flags msvc.compile .CC $(api)/$(cpu-conditions) : $(compiler) /Zm800 /ZW /EHsc -nologo ; + } + toolset.flags msvc.compile .ASM $(api)/$(cpu-conditions) : $(cpu-assembler) -nologo ; + toolset.flags msvc.link .LD $(api)/$(cpu-conditions) : $(linker) /NOLOGO /INCREMENTAL:NO ; + toolset.flags msvc.archive .LD $(api)/$(cpu-conditions) : $(linker) /lib /NOLOGO ; } if $(cc-filter) @@ -1556,6 +1628,13 @@ local rule register-toolset-really ( ) } toolset.flags msvc.archive AROPTIONS ; + + # Create a project to allow building the setup scripts + project.initialize $(__name__) ; + .project = [ project.current ] ; + project msvc ; + + feature.feature msvc.setup-options : : free ; } From ff10c58b99c47fb5a5367bce654fcae9140650e1 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 16 Dec 2017 13:16:21 -0700 Subject: [PATCH 19/72] Fix Windows tests. --- test/BoostBuild.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/BoostBuild.py b/test/BoostBuild.py index a6872dcbc..c4e959f26 100644 --- a/test/BoostBuild.py +++ b/test/BoostBuild.py @@ -707,6 +707,7 @@ class Tester(TestCmd.TestCmd): self.ignore("*.rsp") # Response files. self.ignore("*.tds") # Borland debug symbols. self.ignore("*.manifest") # MSVC DLL manifests. + self.ignore("bin/standalone/msvc/$toolset*/msvc-setup.bat") # Debug builds of bjam built with gcc produce this profiling data. self.ignore("gmon.out") From a96e3fcbc50f77e8179f254e54b33122739cf4f8 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 16 Dec 2017 15:05:46 -0700 Subject: [PATCH 20/72] ignore doesn't handle . --- test/BoostBuild.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/BoostBuild.py b/test/BoostBuild.py index c4e959f26..aaad63ff4 100644 --- a/test/BoostBuild.py +++ b/test/BoostBuild.py @@ -707,7 +707,7 @@ class Tester(TestCmd.TestCmd): self.ignore("*.rsp") # Response files. self.ignore("*.tds") # Borland debug symbols. self.ignore("*.manifest") # MSVC DLL manifests. - self.ignore("bin/standalone/msvc/$toolset*/msvc-setup.bat") + self.ignore("bin/standalone/msvc/*/msvc-setup.bat") # Debug builds of bjam built with gcc produce this profiling data. self.ignore("gmon.out") From 6c3397fac8300afe55be4007faea932771c85199 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 16 Dec 2017 15:19:00 -0700 Subject: [PATCH 21/72] Fix crash when calling a member function that doesn't exist. Fixes #260. --- src/engine/compile.c | 2 +- src/engine/function.c | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/engine/compile.c b/src/engine/compile.c index 6adb83fa2..6ebb4006c 100644 --- a/src/engine/compile.c +++ b/src/engine/compile.c @@ -99,7 +99,7 @@ LIST * evaluate_rule( RULE * rule, OBJECT * rulename, FRAME * frame ) /* Check traditional targets $(<) and sources $(>). */ if ( !rule->actions && !rule->procedure ) - unknown_rule( frame, NULL, frame->module, rule->name ); + unknown_rule( frame, NULL, frame->module, rulename ); /* If this rule will be executed for updating the targets then construct the * action for make(). diff --git a/src/engine/function.c b/src/engine/function.c index d426f5386..2244c3e30 100644 --- a/src/engine/function.c +++ b/src/engine/function.c @@ -533,7 +533,20 @@ static LIST * function_call_member_rule( JAM_FUNCTION * function, FRAME * frame, if ( module->class_module ) { rule = bindrule( rulename, module ); - real_rulename = object_copy( function_rulename( rule->procedure ) ); + if ( rule->procedure ) + { + real_rulename = object_copy( function_rulename( rule->procedure ) ); + } + else + { + string buf[ 1 ]; + string_new( buf ); + string_append( buf, object_str( module->name ) ); + string_push_back( buf, '.' ); + string_append( buf, object_str( rulename ) ); + real_rulename = object_new( buf->value ); + string_free( buf ); + } } else { From bb300dac25933809e0ab29eb323fda7fcdcbb7a8 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 16 Dec 2017 16:11:39 -0700 Subject: [PATCH 22/72] Make test_all.py print more information on failure. --- test/test_all.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_all.py b/test/test_all.py index 9d40be506..c94d8703a 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -96,6 +96,7 @@ def run_tests(critical_tests, other_tests): print("PASSED") else: print("FAILED") + BoostBuild.flush_annotations() else: rs = "succeed" if not passed: From 5391e5303851839ebe1288ef1194696981dcc940 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Mon, 18 Dec 2017 10:13:25 -0700 Subject: [PATCH 23/72] Clear the current project after configuring a toolset from the command line. --- src/build-system.jam | 2 ++ src/build/project.jam | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/build-system.jam b/src/build-system.jam index e38a448fb..a2f64f624 100644 --- a/src/build-system.jam +++ b/src/build-system.jam @@ -463,7 +463,9 @@ local rule process-explicit-toolset-requests "previously configured; attempting to auto-configure now" ; } local t,v = [ MATCH ([^-]+)-?(.+)? : $(toolset) ] ; + project.push-current ; toolset.using $(t,v[1]) : $(t,v[2]) ; + project.pop-current ; } # Make sure we get an appropriate property into the build request in diff --git a/src/build/project.jam b/src/build/project.jam index 2b3386a13..e8834b421 100644 --- a/src/build/project.jam +++ b/src/build/project.jam @@ -833,7 +833,7 @@ rule current ( ) # Temporarily changes the current project to 'project'. Should be followed by # 'pop-current'. # -rule push-current ( project ) +rule push-current ( project ? ) { .saved-current-project += $(.current-project) ; .current-project = $(project) ; From 6fce57e7dae58d9a999bea7ac2984e417d808bcb Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Mon, 18 Dec 2017 11:20:44 -0700 Subject: [PATCH 24/72] Make sure that we can always detect touched files even if we didn't wait for any other reason. --- test/BoostBuild.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/test/BoostBuild.py b/test/BoostBuild.py index aaad63ff4..934451e72 100644 --- a/test/BoostBuild.py +++ b/test/BoostBuild.py @@ -426,6 +426,7 @@ class Tester(TestCmd.TestCmd): return self.previous_tree, dummy = tree.build_tree(self.workdir) + self.wait_for_time_change_since_last_build() if match is None: match = self.match @@ -857,6 +858,22 @@ class Tester(TestCmd.TestCmd): """ self.__wait_for_time_change(path, touch, last_build_time=False) + def wait_for_time_change_since_last_build(self): + """ + Wait for newly assigned file system modification timestamps to + become large enough for the timestamp difference to be + correctly recognized by the Python based testing framework. + Does not care about Jam's timestamp resolution, since we + only need this to detect touched files. + """ + if self.last_build_timestamp: + timestamp_file = "timestamp-3df2f2317e15e4a9" + open(timestamp_file, "wb").close() + self.__wait_for_time_change_impl(timestamp_file, + self.last_build_timestamp, + self.__python_timestamp_resolution(timestamp_file, 0), 0) + os.unlink(timestamp_file) + def __build_timestamp_resolution(self): """ Returns the minimum path modification timestamp resolution supported @@ -1104,7 +1121,12 @@ class Tester(TestCmd.TestCmd): resolution = self.__python_timestamp_resolution(path, build_resolution) assert resolution >= build_resolution + self.__wait_for_time_change_impl(path, start_time, resolution, build_resolution) + if not touch: + os.utime(path, (stats_orig.st_atime, stats_orig.st_mtime)) + + def __wait_for_time_change_impl(self, path, start_time, resolution, build_resolution): # Implementation notes: # * Theoretically time.sleep() API might get interrupted too soon # (never actually encountered). @@ -1161,9 +1183,6 @@ class Tester(TestCmd.TestCmd): break _sleep(max(0.01, start_time - c)) - if not touch: - os.utime(path, (stats_orig.st_atime, stats_orig.st_mtime)) - class List: def __init__(self, s=""): From 0c6d0165b096b9e026c933194eff4e12468f4307 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Mon, 18 Dec 2017 13:09:07 -0700 Subject: [PATCH 25/72] Support nanosecond timestamp resolution for posix. --- src/engine/filesys.c | 32 ++++++++++++++++++++++++++++++++ src/engine/fileunix.c | 21 --------------------- src/engine/filevms.c | 21 --------------------- src/engine/timestamp.c | 4 ++++ 4 files changed, 36 insertions(+), 42 deletions(-) diff --git a/src/engine/filesys.c b/src/engine/filesys.c index cf6cd492c..b975c8f3a 100644 --- a/src/engine/filesys.c +++ b/src/engine/filesys.c @@ -293,6 +293,7 @@ file_info_t * file_query( OBJECT * const path ) return ff; } +#ifndef OS_NT /* * file_query_posix_() - query information about a path using POSIX stat() @@ -330,10 +331,41 @@ void file_query_posix_( file_info_t * const info ) info->is_file = statbuf.st_mode & S_IFREG ? 1 : 0; info->is_dir = statbuf.st_mode & S_IFDIR ? 1 : 0; info->exists = 1; +#if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809 + timestamp_init( &info->time, statbuf.st_mtim.tv_sec, statbuf.st_mtim.tv_nsec ); +#else timestamp_init( &info->time, statbuf.st_mtime, 0 ); +#endif } } +/* + * file_supported_fmt_resolution() - file modification timestamp resolution + * + * Returns the minimum file modification timestamp resolution supported by this + * Boost Jam implementation. File modification timestamp changes of less than + * the returned value might not be recognized. + * + * Does not take into consideration any OS or file system related restrictions. + * + * Return value 0 indicates that any value supported by the OS is also supported + * here. + */ + +void file_supported_fmt_resolution( timestamp * const t ) +{ +#if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809 + timestamp_init( t, 0, 1 ); +#else + /* The current implementation does not support file modification timestamp + * resolution of less than one second. + */ + timestamp_init( t, 1, 0 ); +#endif +} + +#endif + /* * file_remove_atexit() - schedule a path to be removed on program exit diff --git a/src/engine/fileunix.c b/src/engine/fileunix.c index 2d21e5149..5f6815725 100644 --- a/src/engine/fileunix.c +++ b/src/engine/fileunix.c @@ -201,27 +201,6 @@ void file_query_( file_info_t * const info ) } -/* - * file_supported_fmt_resolution() - file modification timestamp resolution - * - * Returns the minimum file modification timestamp resolution supported by this - * Boost Jam implementation. File modification timestamp changes of less than - * the returned value might not be recognized. - * - * Does not take into consideration any OS or file system related restrictions. - * - * Return value 0 indicates that any value supported by the OS is also supported - * here. - */ - -void file_supported_fmt_resolution( timestamp * const t ) -{ - /* The current implementation does not support file modification timestamp - * resolution of less than one second. - */ - timestamp_init( t, 1, 0 ); -} - int file_collect_archive_content_( file_archive_info_t * const archive ); /* diff --git a/src/engine/filevms.c b/src/engine/filevms.c index e94e2634c..ef93b0cdb 100644 --- a/src/engine/filevms.c +++ b/src/engine/filevms.c @@ -162,27 +162,6 @@ void file_query_( file_info_t * const info ) } -/* - * file_supported_fmt_resolution() - file modification timestamp resolution - * - * Returns the minimum file modification timestamp resolution supported by this - * Boost Jam implementation. File modification timestamp changes of less than - * the returned value might not be recognized. - * - * Does not take into consideration any OS or file system related restrictions. - * - * Return value 0 indicates that any value supported by the OS is also supported - * here. - */ - -void file_supported_fmt_resolution( timestamp * const t ) -{ - /* The current implementation does not support file modification timestamp - * resolution of less than one second. - */ - timestamp_init( t, 1, 0 ); -} - /*------------------------------------------------------------------------------ * VMS-specific processing: * diff --git a/src/engine/timestamp.c b/src/engine/timestamp.c index b6fd906ef..8ae7da0bf 100644 --- a/src/engine/timestamp.c +++ b/src/engine/timestamp.c @@ -132,6 +132,10 @@ void timestamp_current( timestamp * const t ) FILETIME ft; GetSystemTimeAsFileTime( &ft ); timestamp_from_filetime( t, &ft ); +#elif defined(_POSIX_TIMERS) + struct timespec ts; + clock_gettime( CLOCK_REALTIME, &ts ); + timestamp_init( t, ts.tv_sec, ts.tv_nsec ); #else /* OS_NT */ timestamp_init( t, time( 0 ), 0 ); #endif /* OS_NT */ From 0388086b3fee2059c4ea3b384283ad1480acb205 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Mon, 18 Dec 2017 15:51:49 -0700 Subject: [PATCH 26/72] Limit --remove-test-targets to the targets generated by the test case. This makes it safe to share object files and executables between test cases. --- src/tools/testing.jam | 77 +++++++++-------------------------------- test/testing_support.py | 47 +++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 60 deletions(-) diff --git a/src/tools/testing.jam b/src/tools/testing.jam index 0f8b646d2..c7383cd03 100644 --- a/src/tools/testing.jam +++ b/src/tools/testing.jam @@ -339,7 +339,7 @@ generators.register-standard testing.unit-test : EXE : UNIT_TEST ; # rule expect-success ( target : dependency + : requirements * ) { - **passed** $(target) : $(dependency) ; + **passed** $(target) : $(dependency) : $(requirements) ; } @@ -356,15 +356,18 @@ rule expect-failure ( target : dependency + : properties * ) RMOLD $(marker) ; DEPENDS $(marker) : $(dependency) ; DEPENDS $(target) : $(marker) ; - **passed** $(target) : $(marker) ; + **passed** $(target) : $(marker) : $(properties) ; } # The rule/action combination used to report successful passing of a test. # -rule **passed** +rule **passed** ( target : sources * : properties * ) { - remove-test-targets $(<) ; + if [ feature.get-values preserve-test-targets : $(properties) ] = off + { + remove-test-targets $(<) ; + } # Force deletion of the target, in case any dependencies failed to build. RMOLD $(<) ; } @@ -453,21 +456,17 @@ toolset.flags testing.capture-output ARGS ; toolset.flags testing.capture-output INPUT_FILES ; toolset.flags testing.capture-output LAUNCHER ; -.preserve-test-targets = on ; if --remove-test-targets in [ modules.peek : ARGV ] { - .preserve-test-targets = off ; + feature.set-default preserve-test-targets : off ; } # Runs executable 'sources' and stores stdout in file 'target'. Unless # --preserve-test-targets command line option has been specified, removes the -# executable. The 'target-to-remove' parameter controls what should be removed: -# - if 'none', does not remove anything, ever -# - if empty, removes 'source' -# - if non-empty and not 'none', contains a list of sources to remove. +# executable. # -rule capture-output ( target : source : properties * : targets-to-remove * ) +rule capture-output ( target : source : properties * ) { output-file on $(target) = $(target:S=.output) ; LOCATE on $(target:S=.output) = [ on $(target) return $(LOCATE) ] ; @@ -485,15 +484,6 @@ rule capture-output ( target : source : properties * : targets-to-remove * ) # bug). DEPENDS $(target) : [ on $(target) return $(INPUT_FILES) ] ; - if $(targets-to-remove) = none - { - targets-to-remove = ; - } - else if ! $(targets-to-remove) - { - targets-to-remove = $(source) ; - } - run-path-setup $(target) : $(source) : $(properties) ; DISABLE_TEST_EXECUTION on $(target) = 0 ; @@ -502,16 +492,6 @@ rule capture-output ( target : source : properties * : targets-to-remove * ) DISABLE_TEST_EXECUTION on $(target) = 1 ; } - if [ feature.get-values preserve-test-targets : $(properties) ] = off - || $(.preserve-test-targets) = off - { - rmtemp-sources $(target) : $(targets-to-remove) ; - for local to-remove in $(targets-to-remove) - { - rmtemp-all-sources $(to-remove) ; - } - } - if ! [ feature.get-values testing.launcher : $(properties) ] { ## On VMS set default launcher to MCR @@ -521,42 +501,19 @@ rule capture-output ( target : source : properties * : targets-to-remove * ) .types-to-remove = EXE OBJ ; -local rule remove-test-targets ( targets + ) +local rule remove-test-targets ( target ) { - if $(.preserve-test-targets) = off - { - rmtemp-all-sources $(target) ; - } -} - -local rule rmtemp-all-sources ( target ) -{ - local sources ; local action = [ on $(target) return $(.action) ] ; - if $(action) + local associated-targets = [ virtual-target.traverse [ $(action).targets ] ] ; + local targets-to-remove ; + for local t in [ sequence.unique $(associated-targets) ] { - local action-sources = [ $(action).sources ] ; - for local source in $(action-sources) + if [ $(t).type ] in $(.types-to-remove) { - local source-type = [ $(source).type ] ; - if $(source-type) in $(.types-to-remove) - { - sources += [ $(source).actual-name ] ; - } - else - { - # ECHO IGNORED: $(source) :: $(source-type) ; - } - } - if $(sources) - { - rmtemp-sources $(target) : $(sources) ; - for local source in $(sources) - { - rmtemp-all-sources $(source) ; - } + targets-to-remove += [ $(t).actual-name ] ; } } + rmtemp-sources $(target) : $(targets-to-remove) ; } local rule rmtemp-sources ( target : sources * ) diff --git a/test/testing_support.py b/test/testing_support.py index f6dd5412c..229d3763d 100755 --- a/test/testing_support.py +++ b/test/testing_support.py @@ -183,6 +183,51 @@ compile-fail fail-run.cpp ; t.cleanup() +def test_remove_test_targets(option): + t = BoostBuild.Tester(use_test_config=False) + + t.write("pass-compile.cpp", "int main() {}\n") + t.write("pass-link.cpp", "int main() {}\n") + t.write("pass-run.cpp", "int main() {}\n") + t.write("fail-compile.cpp", "#error expected to fail\n") + t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") + t.write("fail-run.cpp", "int main() { return 1; }\n") + t.write("source.cpp", "int f();\n") + + t.write("Jamroot.jam", """import testing ; +obj source.o : source.cpp ; +compile pass-compile.cpp ; +link pass-link.cpp source.o ; +run pass-run.cpp source.o ; +compile-fail fail-compile.cpp ; +link-fail fail-link.cpp ; +run-fail fail-run.cpp ; +""") + + t.run_build_system([option]) + + t.expect_addition("bin/$toolset/debug*/source.obj") + + t.expect_addition("bin/pass-compile.test/$toolset/debug*/pass-compile.test") + + t.expect_addition("bin/pass-link.test/$toolset/debug*/pass-link.test") + + t.expect_addition("bin/pass-run.test/$toolset/debug*/pass-run.output") + t.expect_addition("bin/pass-run.test/$toolset/debug*/pass-run.run") + t.expect_addition("bin/pass-run.test/$toolset/debug*/pass-run.test") + + t.expect_addition("bin/fail-compile.test/$toolset/debug*/fail-compile.test") + + t.expect_addition("bin/fail-link.test/$toolset/debug*/fail-link.test") + + t.expect_addition("bin/fail-run.test/$toolset/debug*/fail-run.output") + t.expect_addition("bin/fail-run.test/$toolset/debug*/fail-run.run") + t.expect_addition("bin/fail-run.test/$toolset/debug*/fail-run.test") + + t.expect_nothing_more() + + t.cleanup() + ################################################################################ # # test_files_with_spaces_in_their_name() @@ -238,4 +283,6 @@ test_link() test_link_fail() test_compile() test_compile_fail() +test_remove_test_targets("--remove-test-targets") +test_remove_test_targets("preserve-test-targets=off") test_files_with_spaces_in_their_name() From 8aa702aaf4e2de08df86767f78dcb7947d414ecf Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 19 Dec 2017 10:27:31 -0700 Subject: [PATCH 27/72] Try to fix the build for older versions of XCode. --- src/engine/filesys.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/engine/filesys.c b/src/engine/filesys.c index b975c8f3a..da0e47a2c 100644 --- a/src/engine/filesys.c +++ b/src/engine/filesys.c @@ -332,7 +332,11 @@ void file_query_posix_( file_info_t * const info ) info->is_dir = statbuf.st_mode & S_IFDIR ? 1 : 0; info->exists = 1; #if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809 +#if defined(OS_MACOSX) + timestamp_init( &info->time, statbuf.st_mtimespec.tv_sec, statbuf.st_mtimespec.tv_nsec ); +#else timestamp_init( &info->time, statbuf.st_mtim.tv_sec, statbuf.st_mtim.tv_nsec ); +#endif #else timestamp_init( &info->time, statbuf.st_mtime, 0 ); #endif From 3ae87ff4966b433dc916c13bbc64b57e42d74df6 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 19 Dec 2017 13:30:09 -0700 Subject: [PATCH 28/72] Add a new rule configure.choose that adds properties associated with the first target from a list that successfully builds. --- src/build/configure.jam | 223 ++++++++++++++++++++++++++++++++++++++++ test/configure.py | 55 +++++++++- 2 files changed, 276 insertions(+), 2 deletions(-) diff --git a/src/build/configure.jam b/src/build/configure.jam index ff0f2b561..34ddc70b5 100644 --- a/src/build/configure.jam +++ b/src/build/configure.jam @@ -222,6 +222,89 @@ rule try-build ( targets * : ps : what : retry ? ) return $(result) ; } +# Attempts to build several sets of virtual targets. Returns the +# the index of the first set that builds. +rule try-find-build ( ps : what : * ) +{ + local args = 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; + # The outer layer only needs to check $(what), but we + # also need to check the individual elements, in case + # the set of targets has changed since the last build. + local cache-name = $(what) $($(args)[1]) [ $(ps).raw ] ; + cache-name = $(cache-name:J=-) ; + local value = [ config-cache.get $(cache-name) ] ; + + local result ; + local jam-targets ; + + + # Check whether we need to force rebuild configure targets + if --reconfigure in [ modules.peek : ARGV ] + { + local all-targets ; + for local t in $($(args)[2-]) + { + all-targets += [ virtual-target.traverse $(t) ] ; + } + for local t in [ sequence.unique $(all-targets) ] + { + $(t).always ; + } + } + + if $(value) + { + local none = none ; # What to show when the argument + local name = $(value) ; + if $(name) != none + { + name = [ CALC $(name) + 2 ] ; + } + local x = [ PAD " - $(what)" : $(.width) ] ; + local y = [ PAD $($(name)[1]) : 3 ] ; + result = $(value) ; + log-check-result "$(x) : $(y) (cached)" ; + } + else + { + local x = [ PAD " - $(what)" : $(.width) ] ; + for local i in $(args) + { + local jam-targets ; + for local t in $($(i)[2-]) + { + jam-targets += [ $(t).actualize ] ; + } + if [ UPDATE_NOW $(jam-targets) : + $(.log-fd) : ignore-minus-n : ignore-minus-q ] + { + result = [ CALC $(i) - 2 ] ; + log-check-result "$(x) : $($(i)[1])" ; + break ; + } + } + if ! $(result) + { + result = none ; + } + } + if ! $(value) + { + if $(result) + { + config-cache.set $(cache-name) : $(result) ; + } + else + { + config-cache.set $(cache-name) : $(result) ; + } + } + if $(result) != none + { + return $(result) ; + } +} + # Attempt to build a metatarget named by 'metatarget-reference' # in context of 'project' with properties 'ps'. # Returns non-empty value if build is OK. @@ -248,6 +331,68 @@ rule builds-raw ( metatarget-reference : project : ps : what : retry ? ) } } +# Attempt to build a metatarget named by 'metatarget-reference' +# in context of 'project' with properties 'ps'. +# Returns the 1-based index of the first target +# that builds. +rule find-builds-raw ( project : ps : what : * ) +{ + local result ; + local args = 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; + + if ! $(.$(what)-tested.$(ps)) + { + .$(what)-tested.$(ps) = true ; + local targets.$(i) what.$(i) ; + for local i in $(args) + { + if ! $($(i)) + { + break ; + } + targets.$(i) = [ targets.generate-from-reference + $($(i)[1]) : $(project) : $(ps) ] ; + # ignore usage requirements + targets.$(i) = $(targets.$(i)[2-]) ; + if $($(i)[2]) + { + what.$(i) = $($(i)[2]) ; + } + else + { + local t = [ targets.resolve-reference + $($(i)[1]) : $(project) ] ; + what.$(i) = [ $(t[1]).name ] ; + } + } + + result = [ try-find-build $(ps) : $(what) + : $(what.4) $(targets.4) + : $(what.5) $(targets.5) + : $(what.6) $(targets.6) + : $(what.7) $(targets.7) + : $(what.8) $(targets.8) + : $(what.9) $(targets.9) + : $(what.10) $(targets.10) + : $(what.11) $(targets.11) + : $(what.12) $(targets.12) + : $(what.13) $(targets.13) + : $(what.14) $(targets.14) + : $(what.15) $(targets.15) + : $(what.16) $(targets.16) + : $(what.17) $(targets.17) + : $(what.18) $(targets.18) + : $(what.19) $(targets.19) ] ; + .$(what)-result.$(ps) = $(result) ; + + return $(result) ; + } + else + { + return $(.$(what)-result.$(ps)) ; + } +} + local rule get-relevant-features ( ) { local relevant = [ feature.expand ] ; @@ -286,6 +431,19 @@ rule builds ( metatarget-reference : properties * : what ? : retry ? ) $(retry) ] ; } +rule find-builds ( what : properties * : * ) +{ + local relevant = [ property.select [ get-relevant-features ] : $(properties) ] ; + local ps = [ property-set.create $(relevant) ] ; + local t = [ targets.current ] ; + local p = [ $(t).project ] ; + + return [ find-builds-raw $(p) : $(ps) : $(what) : + $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) : + $(10) : $(11) : $(12) : $(13) : $(14) : $(15) : + $(16) : $(17) : $(18) : $(19) ] ; +} + # Called by Boost.Build startup code to specify the file to receive the # configuration check results. Should never be called by user code. @@ -330,6 +488,57 @@ class check-target-builds-worker } } +class configure-choose-worker +{ + import configure ; + import property ; + rule __init__ ( message : * ) + { + self.message = $(message) ; + for i in 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + { + local name = [ CALC $(i) - 1 ] ; + self.targets.$(name) = $($(i)[1]) ; + if ! $($(i)[2]:G) # Check whether the second argument is a property + { + self.what.$(name) = $($(i)[2]) ; + self.props.$(name) = $($(i)[3-]) ; + } + else + { + self.props.$(name) = $($(i)[2-]) ; + } + } + } + rule check ( properties * ) + { + local i = [ configure.find-builds $(self.message) : $(properties) + : $(self.targets.1) $(self.what.1) + : $(self.targets.2) $(self.what.2) + : $(self.targets.3) $(self.what.3) + : $(self.targets.4) $(self.what.4) + : $(self.targets.5) $(self.what.5) + : $(self.targets.6) $(self.what.6) + : $(self.targets.7) $(self.what.7) + : $(self.targets.8) $(self.what.8) + : $(self.targets.9) $(self.what.9) + : $(self.targets.10) $(self.what.10) + : $(self.targets.11) $(self.what.11) + : $(self.targets.12) $(self.what.12) + : $(self.targets.13) $(self.what.13) + : $(self.targets.14) $(self.what.14) + : $(self.targets.15) $(self.what.15) + : $(self.targets.16) $(self.what.16) + : $(self.targets.17) $(self.what.17) + : $(self.targets.18) $(self.what.18) + : $(self.targets.19) $(self.what.19) ] ; + if $(self.props.$(i)) + { + return [ property.evaluate-conditionals-in-context $(self.props.$(i)) : $(properties) ] ; + } + } +} + rule check-target-builds ( target message ? : true-properties * : false-properties * ) @@ -339,5 +548,19 @@ rule check-target-builds ( target message ? : true-properties * : return @$(instance).check ; } +# Usage: +# [ configure.choose "architecture" +# : /config//x86 x86 x86 +# : /config//mips mips mips +# ] +rule choose ( message : * ) +{ + local instance = [ new configure-choose-worker $(message) + : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) + : $(10) : $(11) : $(12) : $(13) : $(14) : $(15) : $(16) + : $(17) : $(18) : $(19) ] ; + return @$(instance).check ; +} + IMPORT $(__name__) : check-target-builds : : check-target-builds ; diff --git a/test/configure.py b/test/configure.py index 00b007ac2..73b39e9db 100644 --- a/test/configure.py +++ b/test/configure.py @@ -9,7 +9,7 @@ import BoostBuild -def test_basic(): +def test_check_target_builds(): t = BoostBuild.Tester(use_test_config=0) t.write("Jamroot", """ import configure ; @@ -67,4 +67,55 @@ obj bar : foo.cpp : t.cleanup() -test_basic() +def test_choose(): + t = BoostBuild.Tester(use_test_config=0) + t.write("Jamroot", """ +import configure ; +obj pass : pass.cpp ; +obj fail : fail.cpp ; +explicit pass fail ; +obj foo : foo.cpp : + [ configure.choose "which one?" : fail FAIL : pass PASS ] ; +""") + t.write("pass.cpp", "void f() {}\n") + t.write("fail.cpp", "#error fail.cpp\n") + t.write("foo.cpp", """ +#ifndef PASS +#error PASS not defined +#endif +#ifdef FAIL +#error FAIL is defined +#endif +""") + t.run_build_system() + t.expect_output_lines([ + " - which one? : pass"]) + t.expect_addition("bin/$toolset/debug*/pass.obj") + t.expect_addition("bin/$toolset/debug*/foo.obj") + t.expect_nothing_more() + + # An up-to-date build should use the cache + t.run_build_system() + t.expect_output_lines([ + " - which one? : pass (cached)"]) + t.expect_nothing_more() + + # -a should re-run everything, including configuration checks + t.run_build_system(["-a"]) + t.expect_output_lines([ + " - which one? : pass"]) + t.expect_touch("bin/$toolset/debug*/pass.obj") + t.expect_touch("bin/$toolset/debug*/foo.obj") + t.expect_nothing_more() + + # --reconfigure should re-run configuration checks only + t.run_build_system(["--reconfigure"]) + t.expect_output_lines([ + " - which one? : pass"]) + t.expect_touch("bin/$toolset/debug*/pass.obj") + t.expect_nothing_more() + + t.cleanup() + +test_check_target_builds() +test_choose() From f56035d11ae578019b4265c0705fe0480341914c Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 19 Dec 2017 15:59:51 -0700 Subject: [PATCH 29/72] Sync ac with configure. --- src/build/ac.jam | 15 +++++++------- src/build/configure.jam | 46 ++++++++++++++++++----------------------- test/MockToolset.py | 16 ++++++++++++-- test/zlib.py | 24 ++++++++++++++++++++- 4 files changed, 65 insertions(+), 36 deletions(-) diff --git a/src/build/ac.jam b/src/build/ac.jam index 8f73f329b..0255b7793 100644 --- a/src/build/ac.jam +++ b/src/build/ac.jam @@ -61,14 +61,16 @@ rule find-include-path ( properties : header : provided-path ? : test-source ? ) local header-target = $(header:S=:B=$(basename)) ; local cpp = [ class.new file-target $(header-target:S=.cpp) exact : CPP : $(.project) : $(a) ] ; cpp = [ virtual-target.register $(cpp) ] ; + $(cpp).root true ; local result = [ generators.construct $(.project) $(header-target) : OBJ : $(properties) : $(cpp) : true ] ; + configure.maybe-force-rebuild $(result[2-]) ; local jam-targets ; - for t in $(result[2-]) + for local t in $(result[2-]) { jam-targets += [ $(t).actualize ] ; } if [ UPDATE_NOW $(jam-targets) : [ modules.peek configure : .log-fd ] - : ignore-minus-n : ignore-minus-q ] + : ignore-minus-n ] { return %default ; } @@ -107,16 +109,18 @@ rule find-library ( properties : names + : provided-path ? ) [ property-set.empty ] ] ; local main.cpp = [ virtual-target.register [ class.new file-target main-$(name).cpp exact : CPP : $(.project) : $(a) ] ] ; + $(main.cpp).root true ; local test = [ generators.construct $(.project) $(name) : EXE : [ $(properties).add $(lib[1]) ] : $(main.cpp) $(lib[2-]) : true ] ; + configure.maybe-force-rebuild $(test[2-]) ; local jam-targets ; for t in $(test[2-]) { jam-targets += [ $(t).actualize ] ; } if [ UPDATE_NOW $(jam-targets) : [ modules.peek configure : .log-fd ] - : ignore-minus-n : ignore-minus-q ] + : ignore-minus-n ] { result = $(name) $(link-opts[1]) ; names-iter = ; link-opts = ; # break @@ -221,10 +225,7 @@ class ac-library : basic-target library-path ?= [ modules.peek : $(name:U)_LIBPATH ] ; } - local toolset = [ $(property-set).get ] ; - local toolset-version-property = "" ; - local relevant = [ property.select - $(toolset-version-property) : + local relevant = [ property.select [ configure.get-relevant-features ] : [ $(property-set).raw ] ] ; local key = ac-library-$(name)-$(relevant:J=-) ; diff --git a/src/build/configure.jam b/src/build/configure.jam index 34ddc70b5..c5ab97914 100644 --- a/src/build/configure.jam +++ b/src/build/configure.jam @@ -146,18 +146,12 @@ rule print-configure-checks-summary ( ) } } -# Attempts to build a set of virtual targets -rule try-build ( targets * : ps : what : retry ? ) -{ - local cache-name = $(what) [ $(ps).raw ] ; - cache-name = $(cache-name:J=-) ; - local value = [ config-cache.get $(cache-name) ] ; - - local result ; - local jam-targets ; +.reconfigure = [ modules.peek : ARGV ] ; - # Check whether we need to force rebuild configure targets - if --reconfigure in [ modules.peek : ARGV ] +# Handle the --reconfigure option +rule maybe-force-rebuild ( targets * ) +{ + if $(.reconfigure) { local all-targets ; for local t in $(targets) @@ -169,6 +163,19 @@ rule try-build ( targets * : ps : what : retry ? ) $(t).always ; } } +} + +# Attempts to build a set of virtual targets +rule try-build ( targets * : ps : what : retry ? ) +{ + local cache-name = $(what) [ $(ps).raw ] ; + cache-name = $(cache-name:J=-) ; + local value = [ config-cache.get $(cache-name) ] ; + + local result ; + local jam-targets ; + + maybe-force-rebuild $(targets) ; for local t in $(targets) { @@ -237,20 +244,7 @@ rule try-find-build ( ps : what : * ) local result ; local jam-targets ; - - # Check whether we need to force rebuild configure targets - if --reconfigure in [ modules.peek : ARGV ] - { - local all-targets ; - for local t in $($(args)[2-]) - { - all-targets += [ virtual-target.traverse $(t) ] ; - } - for local t in [ sequence.unique $(all-targets) ] - { - $(t).always ; - } - } + maybe-force-rebuild $($(args)[2-]) ; if $(value) { @@ -393,7 +387,7 @@ rule find-builds-raw ( project : ps : what : * ) } } -local rule get-relevant-features ( ) +rule get-relevant-features ( ) { local relevant = [ feature.expand ] ; local result = ; diff --git a/test/MockToolset.py b/test/MockToolset.py index 741959e50..aa280b83a 100755 --- a/test/MockToolset.py +++ b/test/MockToolset.py @@ -18,6 +18,7 @@ parser.add_option('-o', dest="output_file") parser.add_option('-x', dest="language") parser.add_option('-c', dest="compile", action="store_true") parser.add_option('-I', dest="includes", action="append") +parser.add_option('-D', dest="defines", action="append") parser.add_option('-L', dest="library_path", action="append") parser.add_option('--dll', dest="dll", action="store_true") parser.add_option('--archive', dest="archive", action="store_true") @@ -101,6 +102,16 @@ class MockInfo(object): " != ", map(adjust_path, expected_options.includes) return False + if options.defines is None: + options.defines = [] + if expected_options.defines is None: + expected_options.defines = [] + if options.defines != expected_options.defines: + if self.verbose: + print " Failed to match -I ", options.defines, \ + " != ", expected_options.defines + return False + if options.library_path is None: options.library_path = [] if expected_options.library_path is None: @@ -204,15 +215,16 @@ generators.register-linker mock.link.dll : LIB OBJ : SHARED_LIB : mock generators.register-archiver mock.archive : OBJ : STATIC_LIB : mock ; toolset.flags mock.compile INCLUDES ; +toolset.flags mock.compile DEFINES ; actions compile.c { - $(.config-cmd) mock.py -c -x c -I"$(INCLUDES)" "$(>)" -o "$(<)" + $(.config-cmd) mock.py -c -x c -I"$(INCLUDES)" -D"$(DEFINES)" "$(>)" -o "$(<)" } actions compile.c++ { - $(.config-cmd) mock.py -c -x c++ -I"$(INCLUDES)" "$(>)" -o "$(<)" + $(.config-cmd) mock.py -c -x c++ -I"$(INCLUDES)" -D"$(DEFINES)" "$(>)" -o "$(<)" } toolset.flags mock.link USER_OPTIONS ; diff --git a/test/zlib.py b/test/zlib.py index 0bb8269ad..a3dd3a318 100755 --- a/test/zlib.py +++ b/test/zlib.py @@ -25,7 +25,8 @@ alias zlib : /zlib//zlib : : static shared ; MockToolset.set_expected(t, ''' source_file('deflate.c', 'deflate') action('-c -x c -I./zlib -o $deflate.o $deflate.c') -action('--dll $deflate.o -o $deflate.so') +action('-c -x c -I./zlib -DZLIB_DLL -o $deflate-shared.o $deflate.c') +action('--dll $deflate-shared.o -o $deflate.so') action('--archive $deflate.o -o $deflate.a') ''') @@ -116,4 +117,25 @@ t.run_build_system() t.expect_addition('bin/mock/debug/test.exe') t.expect_addition('bin/mock/debug/link-static/test.exe') +# Initialization in explicit location - both static and shared libraries +t.rm('bin') +t.write("Jamroot.jam", """ +path-constant here : . ; +using zlib : : myzlib $(here)/zlib $(here)/zlib ; +exe test : test.cpp /zlib//zlib + : shared:SHARED : static shared ; +""") + +MockToolset.set_expected(t, common_stuff + ''' +action('$main.o -L./zlib --static-lib=myzlib -o $config.exe') +action('$main.o -L./zlib --shared-lib=myzlib -o $config.exe') +action('-c -x c++ $test.cpp -I./zlib -o $test-static.o') +action('-c -x c++ $test.cpp -I./zlib -DSHARED -o $test-shared.o') +action('$test-static.o -L./zlib --static-lib=myzlib -o $test') +action('$test-shared.o -L./zlib --shared-lib=myzlib -o $test') +''') +t.run_build_system() +t.expect_addition('bin/mock/debug/test.exe') +t.expect_addition('bin/mock/debug/link-static/test.exe') + t.cleanup() From 65cd9ce416b96c24015114abc77849a259b80a9d Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 19 Dec 2017 17:05:24 -0700 Subject: [PATCH 30/72] Fix stupid mistake. (On the bright side, the code works anyway.) --- src/build/configure.jam | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/build/configure.jam b/src/build/configure.jam index c5ab97914..3f3f97034 100644 --- a/src/build/configure.jam +++ b/src/build/configure.jam @@ -146,7 +146,10 @@ rule print-configure-checks-summary ( ) } } -.reconfigure = [ modules.peek : ARGV ] ; +if --reconfigure in [ modules.peek : ARGV ] +{ + .reconfigure = true ; +} # Handle the --reconfigure option rule maybe-force-rebuild ( targets * ) From df321f5a3ac1420e8095597ebe52efbce1c1e91c Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 19 Dec 2017 21:52:08 -0700 Subject: [PATCH 31/72] Fix python tests. --- src/tools/python.jam | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/tools/python.jam b/src/tools/python.jam index 406d828b7..71feff689 100644 --- a/src/tools/python.jam +++ b/src/tools/python.jam @@ -1255,10 +1255,7 @@ rule capture-output ( target : sources * : properties * ) PYTHONPATH += [ feature.get-values pythonpath : $(properties) ] ; # After test is run, we remove the Python module, but not the Python script. - local targets-to-remove = $(sources[2-]) ; - targets-to-remove ?= none ; - testing.capture-output $(target) : $(sources[1]) : $(properties) : - $(targets-to-remove) ; + testing.capture-output $(target) : $(sources[1]) : $(properties) ; # PYTHONPATH is different; it will be interpreted by whichever Python is # invoked and so must follow path rules for the target os. The only OSes From d2b64dc55dc38cf54925d6186d198df105157d97 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Wed, 20 Dec 2017 15:33:01 -0700 Subject: [PATCH 32/72] Fix crash in the debugger's backtrace when a built-in function is on the stack. --- src/engine/debugger.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/engine/debugger.c b/src/engine/debugger.c index e2f235b9b..e6788a05f 100644 --- a/src/engine/debugger.c +++ b/src/engine/debugger.c @@ -195,8 +195,11 @@ static void debug_lol_read( FILE * in, LOL * lol ) static void debug_frame_write( FILE * out, FRAME * frame ) { - OBJECT * fullname = make_absolute_path( frame->file ); - debug_object_write( out, frame->file ); + OBJECT * fullname = constant_builtin; + OBJECT * file = frame->file; + if ( file == NULL ) file = constant_builtin; + else fullname = make_absolute_path( frame->file ); + debug_object_write( out, file ); debug_int_write( out, frame->line ); debug_object_write( out, fullname ); debug_lol_write( out, frame->args ); From 6d7c0c752d804fbe0c519e3f5c225281b7bf0a2a Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Thu, 21 Dec 2017 15:16:45 -0700 Subject: [PATCH 33/72] Quote the name of the batch script so that it works when %TMP% contains a space. Fixes #274. --- src/engine/execnt.c | 2 ++ test/space_in_path.py | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/engine/execnt.c b/src/engine/execnt.c index 029aa37c0..9137f585a 100644 --- a/src/engine/execnt.c +++ b/src/engine/execnt.c @@ -1282,7 +1282,9 @@ static void string_new_from_argv( string * result, char const * const * argv ) while ( *argv ) { string_push_back( result, ' ' ); + string_push_back( result, '"' ); string_append( result, *(argv++) ); + string_push_back( result, '"' ); } } diff --git a/test/space_in_path.py b/test/space_in_path.py index 4cd320c5b..5f21ab76e 100755 --- a/test/space_in_path.py +++ b/test/space_in_path.py @@ -7,15 +7,28 @@ # Test that paths containing spaces are handled correctly by actions. import BoostBuild +import os t = BoostBuild.Tester(use_test_config=False) t.write("has space/jamroot.jam", """\ import testing ; unit-test test : test.cpp ; +actions write-file +{ + @(STDOUT:E=okay) >"$(<)" +} +make test.txt : : @write-file ; """) t.write("has space/test.cpp", "int main() {}\n") +tmpdir = t.workpath("has space") +os.environ["TMP"] = tmpdir; # Windows +os.environ["TMPDIR"] = tmpdir; # *nix + t.run_build_system(["has space"]) +t.expect_addition("has space/bin/$toolset/debug*/test.txt") +t.expect_addition("has space/bin/$toolset/debug*/test.passed") + t.cleanup() From 14d745d6914eb816a0bb1d9a966ef49a4e73f259 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Thu, 21 Dec 2017 15:55:23 -0700 Subject: [PATCH 34/72] Localize changes to the environment, so that we don't break later tests run in the same process. --- test/space_in_path.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/test/space_in_path.py b/test/space_in_path.py index 5f21ab76e..f4c6c579a 100755 --- a/test/space_in_path.py +++ b/test/space_in_path.py @@ -23,12 +23,29 @@ make test.txt : : @write-file ; t.write("has space/test.cpp", "int main() {}\n") tmpdir = t.workpath("has space") +try: + oldtmp = os.environ["TMP"] +except: + oldtmp = None +try: + oldtmpdir = os.environ["TMPDIR"] +except: + oldtmpdir = None os.environ["TMP"] = tmpdir; # Windows os.environ["TMPDIR"] = tmpdir; # *nix -t.run_build_system(["has space"]) - -t.expect_addition("has space/bin/$toolset/debug*/test.txt") -t.expect_addition("has space/bin/$toolset/debug*/test.passed") +try: + t.run_build_system(["has space"]) + t.expect_addition("has space/bin/$toolset/debug*/test.txt") + t.expect_addition("has space/bin/$toolset/debug*/test.passed") +finally: + if oldtmp is not None: + os.environ["TMP"] = oldtmp + else: + del os.environ["TMP"] + if oldtmpdir is not None: + os.environ["TMPDIR"] = oldtmpdir + else: + del os.environ["TMPDIR"] t.cleanup() From c594b12b13011cb1b90c868046b32efb26c30444 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 23 Dec 2017 09:46:47 -0700 Subject: [PATCH 35/72] Adjust check for using clock_gettime. --- src/engine/timestamp.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/engine/timestamp.c b/src/engine/timestamp.c index 8ae7da0bf..679cf2982 100644 --- a/src/engine/timestamp.c +++ b/src/engine/timestamp.c @@ -132,7 +132,13 @@ void timestamp_current( timestamp * const t ) FILETIME ft; GetSystemTimeAsFileTime( &ft ); timestamp_from_filetime( t, &ft ); -#elif defined(_POSIX_TIMERS) +#elif defined(_POSIX_TIMERS) && defined(CLOCK_REALTIME) && \ + (!defined(__GLIBC__) || (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17)) + /* Some older versions of XCode define _POSIX_TIMERS, but don't actually + * have clock_gettime. Check CLOCK_REALTIME as well. Prior to glibc 2.17, + * clock_gettime requires -lrt. This is a non-critical feature, so + * we just disable it to keep bootstrapping simple. + */ struct timespec ts; clock_gettime( CLOCK_REALTIME, &ts ); timestamp_init( t, ts.tv_sec, ts.tv_nsec ); From c91455ff75cc5197fbf96d0a46e8bec4b0812a70 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 23 Dec 2017 19:13:41 +0200 Subject: [PATCH 36/72] Add xcode 8, 7.3, 6.4 to Travis (#275) * Add xcode 8, 7.3, 6.4 to Travis * Add xcode 9.x, linux precise to Travis; restrict branches * Restrict branches in Appveyor, too --- .travis.yml | 32 +++++++++++++++++++++++++++++--- appveyor.yml | 5 +++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9413d7206..78090f94c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,9 @@ sudo: false -os: - - linux - - osx +branches: + only: + - master + - develop + - /feature\/.*/ env: matrix: - TRAVIS_EMPTY_JOB_WORKAROUND=true @@ -9,15 +11,39 @@ matrix: exclude: - env: TRAVIS_EMPTY_JOB_WORKAROUND=true include: + - os: linux + dist: precise + env: TOOLSET=gcc + - os: linux + dist: precise + env: TOOLSET=clang - os: linux dist: trusty env: TOOLSET=gcc - os: linux dist: trusty env: TOOLSET=clang + - os: osx + osx_image: xcode9.2 + env: TOOLSET=clang + - os: osx + osx_image: xcode9.1 + env: TOOLSET=clang + - os: osx + osx_image: xcode9 + env: TOOLSET=clang - os: osx osx_image: xcode8.3 env: TOOLSET=clang + - os: osx + osx_image: xcode8 + env: TOOLSET=clang + - os: osx + osx_image: xcode7.3 + env: TOOLSET=clang + - os: osx + osx_image: xcode6.4 + env: TOOLSET=clang language: cpp script: - cd src/engine diff --git a/appveyor.yml b/appveyor.yml index 4b0b6a4c2..cec088573 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,6 +4,11 @@ # # Copyright Rene Rivera 2015-2017. +branches: + only: + - master + - develop + - /feature\/.*/ image: - Visual Studio 2017 From 858ad964c92c49a83bd70f6d0c503cada26651fa Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 23 Dec 2017 15:57:26 -0700 Subject: [PATCH 37/72] Add a mock of gcc as a first step towards testing all toolsets. --- test/gcc.py | 106 +++++++++ test/test_all.py | 1 + test/toolset-mock/Jamroot.jam | 8 + test/toolset-mock/lib.cpp | 7 + test/toolset-mock/main.cpp | 7 + test/toolset-mock/project-config.jam | 8 + test/toolset-mock/src/Jamroot.jam | 50 +++++ test/toolset-mock/src/MockProgram.py | 260 +++++++++++++++++++++++ test/toolset-mock/src/ar.py | 14 ++ test/toolset-mock/src/gcc-4.8.3-linux.py | 42 ++++ test/toolset-mock/src/mock-program.cpp | 42 ++++ test/toolset-mock/src/project-config.jam | 5 + test/toolset-mock/src/ranlib.py | 14 ++ test/toolset-mock/src/verify.py | 9 + 14 files changed, 573 insertions(+) create mode 100644 test/gcc.py create mode 100644 test/toolset-mock/Jamroot.jam create mode 100644 test/toolset-mock/lib.cpp create mode 100644 test/toolset-mock/main.cpp create mode 100644 test/toolset-mock/project-config.jam create mode 100644 test/toolset-mock/src/Jamroot.jam create mode 100644 test/toolset-mock/src/MockProgram.py create mode 100644 test/toolset-mock/src/ar.py create mode 100644 test/toolset-mock/src/gcc-4.8.3-linux.py create mode 100644 test/toolset-mock/src/mock-program.cpp create mode 100644 test/toolset-mock/src/project-config.jam create mode 100644 test/toolset-mock/src/ranlib.py create mode 100644 test/toolset-mock/src/verify.py diff --git a/test/gcc.py b/test/gcc.py new file mode 100644 index 000000000..f689e056f --- /dev/null +++ b/test/gcc.py @@ -0,0 +1,106 @@ +#!/usr/bin/python +# +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# validates the gcc toolset using a mock of gcc + +import BoostBuild +import os +import re +import sys + +renames = {"debug": "variant=debug", "release": "variant=release"} + +def set_default_target_os(os): + global removed + global default_target_os + default_target_os = os + removed = set() + removed.add("target-os=" + default_target_os) + +def adjust_property(property): + global renames + if property in renames: + return renames[property] + else: + return property + +def adjust_properties(properties): + global removed + return [adjust_property(p) for p in properties if p not in removed] + +def has_property(name, properties): + return name in [re.sub("=.*", "", p) for p in properties] + +def expand_properties(properties): + result = properties[:] + if not has_property("variant", properties): + result += ["variant=debug"] + if not has_property("threading", properties): + result += ["threading=single"] + if not has_property("link", properties): + result += ["link=shared"] + if not has_property("runtime-link", properties): + result += ["runtime-link=shared"] + if not has_property("target-os", properties): + result += ["target-os=" + default_target_os] + return result + +def compute_path(properties): + path = "" + if "variant=release" in properties: + path += "/release" + else: + path += "/debug" + if "threading=multi" in properties: + path += "/threading-multi" + if "link=static" in properties: + path += "/link-static" + if "runtime-link=static" in properties: + path += "/runtime-link-static" + if "target-os=linux" in properties: + path += "/target-os-linux" + return path + +def test_gcc(version, property_sets): + t = BoostBuild.Tester() + + t.set_tree("toolset-mock") + + # Build necessary tools + t.run_build_system(["-sPYTHON_CMD=%s" % sys.executable], subdir="src") + set_default_target_os(t.read("src/bin/target-os.txt").strip()) + + # Fixups required for explicitly setting the toolset + # FIXME: Change BoostBuild.py to support this directly + t.toolset = "gcc-" + version + t.pass_toolset = True + BoostBuild.prepare_prefixes_and_suffixes(t.toolset) + + for properties in property_sets: + properties = adjust_properties(properties) + path = compute_path(properties) + os.environ["B2_PROPERTIES"] = " ".join(expand_properties(properties)) + t.run_build_system(["--user-config="] + properties) + t.expect_addition("bin/gcc-*%s%s/lib.obj" % (version, path)) + if "link=static" not in properties: + t.expect_addition("bin/gcc-*%s%s/l1.dll" % (version, path)) + else: + t.expect_addition("bin/gcc-*%s%s/l1.lib" % (version, path)) + t.expect_addition("bin/gcc-*%s%s/main.obj" % (version, path)) + t.expect_addition("bin/gcc-*%s%s/test.exe" % (version, path)) + t.expect_nothing_more() + t.rm("bin") + + t.cleanup() + +test_gcc("4.8.3", [ + ["target-os=linux"], + ["target-os=linux", "release"], + ["target-os=linux", "threading=multi"], + ["target-os=linux", "link=static"], + ["target-os=linux", "link=static", "runtime-link=static"]]) diff --git a/test/test_all.py b/test/test_all.py index c94d8703a..efb7134a5 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -223,6 +223,7 @@ tests = ["absolute_sources", "explicit", "feature_cxxflags", "free_features_request", + "gcc", "generator_selection", "generators_test", "implicit_dependency", diff --git a/test/toolset-mock/Jamroot.jam b/test/toolset-mock/Jamroot.jam new file mode 100644 index 000000000..fd5f7907b --- /dev/null +++ b/test/toolset-mock/Jamroot.jam @@ -0,0 +1,8 @@ +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +lib l1 : lib.cpp ; +exe test : main.cpp l1 ; diff --git a/test/toolset-mock/lib.cpp b/test/toolset-mock/lib.cpp new file mode 100644 index 000000000..1ba30e32d --- /dev/null +++ b/test/toolset-mock/lib.cpp @@ -0,0 +1,7 @@ +// Copyright (c) 2017 Steven Watanabe +// +// Distributed under the Boost Software License Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +int f() {} diff --git a/test/toolset-mock/main.cpp b/test/toolset-mock/main.cpp new file mode 100644 index 000000000..0fc8b9a75 --- /dev/null +++ b/test/toolset-mock/main.cpp @@ -0,0 +1,7 @@ +// Copyright (c) 2017 Steven Watanabe +// +// Distributed under the Boost Software License Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +int main() {} diff --git a/test/toolset-mock/project-config.jam b/test/toolset-mock/project-config.jam new file mode 100644 index 000000000..fbf86b4fa --- /dev/null +++ b/test/toolset-mock/project-config.jam @@ -0,0 +1,8 @@ +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +path-constant here : . ; +using gcc : 4.8.3 : python $(here)/src/gcc-4.8.3-linux.py : : linux ; diff --git a/test/toolset-mock/src/Jamroot.jam b/test/toolset-mock/src/Jamroot.jam new file mode 100644 index 000000000..51b6f679b --- /dev/null +++ b/test/toolset-mock/src/Jamroot.jam @@ -0,0 +1,50 @@ +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import os ; +import print ; +import regex ; +import feature ; + +.PYTHON = [ os.environ PYTHON_CMD ] ; +path-constant .AR : ar.py ; +path-constant .RANLIB : ranlib.py ; + +rule c-escape ( str ) +{ + return [ regex.replace $(str) \\\\ \\\\ ] ; +} + +rule cfg-header ( target : : properties * ) +{ + local PYTHON = [ c-escape $(.PYTHON) ] ; + local AR = [ c-escape $(.AR) ] ; + local RANLIB = [ c-escape $(.RANLIB) ] ; + print.output $(target) ; + print.text "#define PYTHON_CMD "\"$(PYTHON)\" : true ; + print.text "#define AR_CMD "\"$(AR)\" : true ; + print.text "#define RANLIB_CMD "\"$(RANLIB)\" : true ; +} + +make config.h : : @cfg-header ; + +project + : requirements + config.h + bin # We can only build one variant at a time and we need to have a fixed path + ; + +rule write-target-os ( target : : properties * ) +{ + local target-os = [ feature.defaults ] ; + print.output $(target) ; + print.text $(target-os:G=) : true ; +} + +make target-os.txt : : @write-target-os ; + +exe ar : [ obj ar.obj : mock-program.cpp : PY_SCRIPT=AR_CMD ] ; +exe ranlib : [ obj ranlib.obj : mock-program.cpp : PY_SCRIPT=RANLIB_CMD ] ; diff --git a/test/toolset-mock/src/MockProgram.py b/test/toolset-mock/src/MockProgram.py new file mode 100644 index 000000000..7ca5c1459 --- /dev/null +++ b/test/toolset-mock/src/MockProgram.py @@ -0,0 +1,260 @@ +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import sys +import os +import re + +# Represents a sequence of arguments that must appear +# in a fixed order. +class ordered: + def __init__(self, *args): + self.args = args + def match(self, command_line, pos, outputs): + for p in self.args: + res = try_match(command_line, pos, p, outputs) + if res is None: + return + pos = res + return pos + +# Represents a sequence of arguments that can appear +# in any order. +class unordered: + def __init__(self, *args): + self.args = args + def match(self, command_line, pos, outputs): + unmatched = self.args[:] + while len(unmatched) > 0: + res = try_match_one(command_line, pos, unmatched, outputs) + if res is None: + return + pos = res + return pos + +# Represents a single input file. +# If id is set, then the file must have been created +# by a prior use of output_file. +# If source is set, then the file must be that source file. +class input_file: + def __init__(self, id=None, source=None): + assert((id is None) ^ (source is None)) + self.id = id + self.source = source + def check(self, path): + if path.startswith("-"): + return + if self.id is not None: + try: + with open(path, "r") as f: + data = f.read() + if data == make_file_contents(self.id): + return True + else: + return + except: + return + elif self.source is not None: + if self.source == path: + return True + else: + return + assert(False) + def match(self, command_line, pos, outputs): + if self.check(command_line[pos]): + return pos + 1 + +# Matches an output file. +# If the full pattern is matched, The +# file will be created. +class output_file: + def __init__(self, id): + self.id = id + def match(self, command_line, pos, outputs): + if command_line[pos].startswith("-"): + return + outputs.append((command_line[pos], self.id)) + return pos + 1 + +# Matches the directory containing an input_file +class target_path(object): + def __init__(self, id): + self.tester = input_file(id=id) + def match(self, command_line, pos, outputs): + arg = command_line[pos] + if arg.startswith("-"): + return + try: + for path in os.listdir(arg): + if self.tester.check(os.path.join(arg, path)): + return pos + 1 + except: + return + +# Matches a single argument, which is composed of a prefix and a path +# for example arguments of the form -ofilename. +class arg(object): + def __init__(self, prefix, a): + # The prefix should be a string, a should be target_path or input_file. + self.prefix = prefix + self.a = a + def match(self, command_line, pos, outputs): + s = command_line[pos] + if s.startswith(self.prefix) and try_match([s[len(self.prefix):]], 0, self.a, outputs) == 1: + return pos + 1 + +# Given a file id, returns a string that will be +# written to the file to allow it to be recognized. +def make_file_contents(id): + return id + +# Matches a single pattern from a list. +# If it succeeds, the matching pattern +# is removed from the list. +# Returns the index after the end of the match +def try_match_one(command_line, pos, patterns, outputs): + for p in pattern: + tmp = outputs[:] + res = try_match(command_line, pos, p, tmp) + if res is not None: + outputs[:] = tmp + pattern.remove(p) + return res + +# returns the end of the match if any +def try_match(command_line, pos, pattern, outputs): + if pos == len(command_line): + return + elif type(pattern) is str: + if pattern == command_line[pos]: + return pos + 1 + else: + return pattern.match(command_line, pos, outputs) + +known_patterns = [] +program_name = None + +# Registers a command +# The arguments should be a sequence of: +# str, ordered, unordered, arg, input_file, output_file, target_path +# kwarg: stdout is text that will be printed on success. +def command(*args, **kwargs): + global known_patterns + global program_name + stdout = kwargs.get("stdout", None) + pattern = ordered(*args) + known_patterns += [(pattern, stdout)] + if program_name is None: + program_name = args[0] + else: + assert(program_name == args[0]) + +# Use this to filter the recognized commands, based on the properties +# passed to b2. +def allow_properties(*args): + try: + return all(a in os.environ["B2_PROPERTIES"].split(" ") for a in args) + except KeyError: + return True + +# Use this in the stdout argument of command to print the command +# for running another script. +def script(name): + return os.path.join(os.path.dirname(__file__), "bin", re.sub('\.py$', '', name)) + +def match(command_line): + for (p, stdout) in known_patterns: + outputs = [] + if try_match(command_line, 0, p, outputs) == len(command_line): + return (stdout, outputs) + +# Every mock program should call this after setting up all the commands. +def main(): + command_line = [program_name] + sys.argv[1:] + result = match(command_line) + if result is not None: + (stdout, outputs) = result + if stdout is not None: + print stdout + for (file,id) in outputs: + with open(file, "w") as f: + f.write(make_file_contents(id)) + exit(0) + else: + print command_line + exit(1) + +# file should be the name of a file in the same directory +# as this. Must be called after verify_setup +def verify_file(filename): + global known_files + if filename not in known_files: + known_files.add(filename) + srcdir = os.path.dirname(__file__) + execfile(os.path.join(srcdir, filename), {}) + +def verify_setup(): + """Override the behavior of most module components + in order to detect whether they are being used correctly.""" + global main + global allow_properties + global output_file + global input_file + global target_path + global script + global command + global verify_errors + global output_ids + global input_ids + global known_files + def allow_properties(*args): + return True + def main(): + pass + def output_file(id): + global output_ids + global verify_error + if id in output_ids: + verify_error("duplicate output_file: %s" % id) + output_ids.add(id) + def input_file(id=None, source=None): + if id is not None: + input_ids.add(id) + def target_path(id): + input_ids.add(id) + def script(filename): + verify_file(filename) + def command(*args, **kwargs): + pass + verify_errors = [] + output_ids = set() + input_ids = set() + known_files = set() + +def verify_error(message): + global verify_errors + verify_errors += [message] + +def verify_finalize(): + for id in input_ids: + if not id in output_ids: + verify_error("Input file does not exist: %s" % id) + for error in verify_errors: + print "error: %s" % error + if len(verify_errors) != 0: + return 1 + else: + return 0 + +def verify(): + srcdir = os.path.dirname(__file__) + if srcdir == '': + srcdir = '.' + verify_setup() + for f in os.listdir(srcdir): + if re.match(r"gcc-.*\.py", f): + verify_file(f) + exit(verify_finalize()) diff --git a/test/toolset-mock/src/ar.py b/test/toolset-mock/src/ar.py new file mode 100644 index 000000000..fd3be5322 --- /dev/null +++ b/test/toolset-mock/src/ar.py @@ -0,0 +1,14 @@ +#!/usr/bin/python +# +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +from MockProgram import * + +command('ar', 'rc', output_file('bin/gcc-gnu-4.8.3/debug/link-static/libl1.a'), input_file('bin/gcc-gnu-4.8.3/debug/link-static/lib.o')) +command('ar', 'rc', output_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/libl1.a'), input_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/lib.o')) + +main() diff --git a/test/toolset-mock/src/gcc-4.8.3-linux.py b/test/toolset-mock/src/gcc-4.8.3-linux.py new file mode 100644 index 000000000..a14eded1b --- /dev/null +++ b/test/toolset-mock/src/gcc-4.8.3-linux.py @@ -0,0 +1,42 @@ +#!/usr/bin/python +# +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +from MockProgram import * + +command('g++', '-print-prog-name=ar', stdout=script('ar.py')) +command('g++', '-print-prog-name=ranlib', stdout=script('ranlib.py')) + +if allow_properties("variant=debug", "link=shared", "threading=single", "runtime-link=shared"): + command("g++", "-O0", "-fno-inline", "-Wall", "-g", "-fPIC", "-c", "-o", output_file("bin/gcc-gnu-4.8.3/debug/lib.o"), input_file(source="lib.cpp")) + command("g++", "-o", output_file("bin/gcc-gnu-4.8.3/debug/libl1.so"), "-Wl,-h", "-Wl,libl1.so", "-shared", "-Wl,--start-group", input_file("bin/gcc-gnu-4.8.3/debug/lib.o"), "-Wl,-Bstatic", "-Wl,-Bdynamic", "-Wl,--end-group", "-g", "-fPIC") + command("g++", "-O0", "-fno-inline", "-Wall", "-g", "-fPIC", "-c", "-o", output_file("bin/gcc-gnu-4.8.3/debug/main.o"), input_file(source="main.cpp")) + command("g++", "-Wl,-rpath", arg("-Wl,", target_path("bin/gcc-gnu-4.8.3/debug/libl1.so")), "-Wl,-rpath-link", arg("-Wl,", target_path("bin/gcc-gnu-4.8.3/debug/libl1.so")), "-o", output_file("bin/gcc-gnu-4.8.3/debug/test"), "-Wl,--start-group", input_file("bin/gcc-gnu-4.8.3/debug/main.o"), input_file("bin/gcc-gnu-4.8.3/debug/libl1.so"), "-Wl,-Bstatic", "-Wl,-Bdynamic", "-Wl,--end-group", "-g", "-fPIC") + +if allow_properties("variant=release", "link=shared", "threading=single", "runtime-link=shared"): + command('g++', '-O3', '-finline-functions', '-Wno-inline', '-Wall', '-fPIC', '-DNDEBUG', '-c', '-o', output_file('bin/gcc-gnu-4.8.3/release/lib.o'), input_file(source='lib.cpp')) + command('g++', '-o', output_file('bin/gcc-gnu-4.8.3/release/libl1.so'), '-Wl,-h', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/gcc-gnu-4.8.3/release/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-fPIC') + command('g++', '-O3', '-finline-functions', '-Wno-inline', '-Wall', '-fPIC', '-DNDEBUG', '-c', '-o', output_file('bin/gcc-gnu-4.8.3/release/main.o'), input_file(source='main.cpp')) + command('g++', '-Wl,-rpath', arg('-Wl,', target_path('bin/gcc-gnu-4.8.3/release/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/gcc-gnu-4.8.3/release/libl1.so')), '-o', output_file('bin/gcc-gnu-4.8.3/release/test'), '-Wl,--start-group', input_file('bin/gcc-gnu-4.8.3/release/main.o'), input_file('bin/gcc-gnu-4.8.3/release/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-fPIC') + +if allow_properties("variant=debug", "link=shared", "threading=multi", "runtime-link=shared"): + command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-pthread', '-fPIC', '-c', '-o', output_file('bin/gcc-gnu-4.8.3/debug/threading-multi/lib.o'), input_file(source='lib.cpp')) + command('g++', '-o', output_file('bin/gcc-gnu-4.8.3/debug/threading-multi/libl1.so'), '-Wl,-h', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/gcc-gnu-4.8.3/debug/threading-multi/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-lrt', '-Wl,--end-group', '-g', '-pthread', '-fPIC') + command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-pthread', '-fPIC', '-c', '-o', output_file('bin/gcc-gnu-4.8.3/debug/threading-multi/main.o'), input_file(source='main.cpp')) + command('g++', '-Wl,-rpath', arg('-Wl,', target_path('bin/gcc-gnu-4.8.3/debug/threading-multi/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/gcc-gnu-4.8.3/debug/threading-multi/libl1.so')), '-o', output_file('bin/gcc-gnu-4.8.3/debug/threading-multi/test'), '-Wl,--start-group', input_file('bin/gcc-gnu-4.8.3/debug/threading-multi/main.o'), input_file('bin/gcc-gnu-4.8.3/debug/threading-multi/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-lrt', '-Wl,--end-group', '-g', '-pthread', '-fPIC') + +if allow_properties("variant=debug", "link=static", "threading=single", "runtime-link=shared"): + command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/gcc-gnu-4.8.3/debug/link-static/lib.o'), input_file(source='lib.cpp')) + command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/gcc-gnu-4.8.3/debug/link-static/main.o'), input_file(source='main.cpp')) + command('g++', '-o', output_file('bin/gcc-gnu-4.8.3/debug/link-static/test'), '-Wl,--start-group', input_file('bin/gcc-gnu-4.8.3/debug/link-static/main.o'), input_file('bin/gcc-gnu-4.8.3/debug/link-static/libl1.a'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-g') + +if allow_properties("variant=debug", "link=static", "threading=single", "runtime-link=static"): + command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/lib.o'), input_file(source='lib.cpp')) + command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/main.o'), input_file(source='main.cpp')) + command('g++', '-o', output_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/test'), '-Wl,--start-group', input_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/main.o'), input_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/libl1.a'), '-Wl,--end-group', '-g', '-static') + +main() diff --git a/test/toolset-mock/src/mock-program.cpp b/test/toolset-mock/src/mock-program.cpp new file mode 100644 index 000000000..109e27503 --- /dev/null +++ b/test/toolset-mock/src/mock-program.cpp @@ -0,0 +1,42 @@ +// mock-program.cpp +// +// Copyright (c) 2017 Steven Watanabe +// +// Distributed under the Boost Software License Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// This program does nothing except to exec a python script + +#include +#include +#include +#include "config.h" + +#if defined(_WIN32) + #include + #define execv _execv +#else + #include +#endif + +#ifndef PY_SCRIPT +#error PY_SCRIPT must be defined to the absolute path to the script to run +#endif + +#ifndef PYTHON_CMD +#error PYTHON_CMD must be defined to the absolute path to the python interpreter +#endif + +int main(int argc, char ** argv) +{ + std::vector args; + char python_cmd[] = PYTHON_CMD; + char script[] = PY_SCRIPT; + args.push_back(python_cmd); + args.push_back(script); + args.insert(args.end(), argv + 1, argv + argc); + args.push_back(NULL); + execv(python_cmd, args.data()); + perror("exec"); +} diff --git a/test/toolset-mock/src/project-config.jam b/test/toolset-mock/src/project-config.jam new file mode 100644 index 000000000..73dcf42df --- /dev/null +++ b/test/toolset-mock/src/project-config.jam @@ -0,0 +1,5 @@ +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) diff --git a/test/toolset-mock/src/ranlib.py b/test/toolset-mock/src/ranlib.py new file mode 100644 index 000000000..42d1721fc --- /dev/null +++ b/test/toolset-mock/src/ranlib.py @@ -0,0 +1,14 @@ +#!/usr/bin/python +# +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +from MockProgram import * + +command('ranlib', input_file('bin/gcc-gnu-4.8.3/debug/link-static/libl1.a')) +command('ranlib', input_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/libl1.a')) + +main() diff --git a/test/toolset-mock/src/verify.py b/test/toolset-mock/src/verify.py new file mode 100644 index 000000000..6e5e0ea7b --- /dev/null +++ b/test/toolset-mock/src/verify.py @@ -0,0 +1,9 @@ +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +from MockProgram import * + +verify() From 89b0e49d99b9032eaee1f5360db930dfe0398429 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 26 Dec 2017 09:50:33 -0700 Subject: [PATCH 38/72] Adjust expected suffixes to work on OSX and windows for gcc.py. --- test/BoostBuild.py | 32 ++++++++++++++++++++++---------- test/gcc.py | 13 +++++++------ 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/test/BoostBuild.py b/test/BoostBuild.py index 934451e72..a0455c364 100644 --- a/test/BoostBuild.py +++ b/test/BoostBuild.py @@ -92,13 +92,19 @@ def get_toolset(): cygwin = hasattr(os, "uname") and os.uname()[0].lower().startswith("cygwin") windows = cygwin or os.environ.get("OS", "").lower().startswith("windows") +if cygwin: + default_os = "cygwin" +elif windows: + default_os = "windows" +elif hasattr(os, "uname"): + default_os = os.uname()[0].lower() -def prepare_prefixes_and_suffixes(toolset): - prepare_suffix_map(toolset) - prepare_library_prefix(toolset) +def prepare_prefixes_and_suffixes(toolset, target_os=default_os): + prepare_suffix_map(toolset, target_os) + prepare_library_prefix(toolset, target_os) -def prepare_suffix_map(toolset): +def prepare_suffix_map(toolset, target_os=default_os): """ Set up suffix translation performed by the Boost Build testing framework to accomodate different toolsets generating targets of the same type using @@ -107,11 +113,11 @@ def prepare_suffix_map(toolset): """ global suffixes suffixes = {} - if windows: + if target_os in ["windows", "cygwin"]: if toolset == "gcc": suffixes[".lib"] = ".a" # mingw static libs use suffix ".a". suffixes[".obj"] = ".o" - if cygwin: + if target_os == "cygwin": suffixes[".implib"] = ".lib.a" else: suffixes[".implib"] = ".lib" @@ -122,11 +128,11 @@ def prepare_suffix_map(toolset): suffixes[".obj"] = ".o" suffixes[".implib"] = ".no_implib_files_on_this_platform" - if hasattr(os, "uname") and os.uname()[0] == "Darwin": + if target_os == "darwin": suffixes[".dll"] = ".dylib" -def prepare_library_prefix(toolset): +def prepare_library_prefix(toolset, target_os=default_os): """ Setup whether Boost Build is expected to automatically prepend prefixes to its built library targets. @@ -136,9 +142,9 @@ def prepare_library_prefix(toolset): lib_prefix = "lib" global dll_prefix - if cygwin: + if target_os == "cygwin": dll_prefix = "cyg" - elif windows and toolset != "gcc": + elif target_os == "windows" and toolset != "gcc": dll_prefix = None else: dll_prefix = "lib" @@ -320,6 +326,12 @@ class Tester(TestCmd.TestCmd): # this case. pass + def set_toolset(self, toolset, target_os=default_os): + self.toolset = toolset + self.pass_toolset = True + prepare_prefixes_and_suffixes(toolset, target_os) + + # # Methods that change the working directory's content. # diff --git a/test/gcc.py b/test/gcc.py index f689e056f..7314fbb84 100644 --- a/test/gcc.py +++ b/test/gcc.py @@ -36,6 +36,12 @@ def adjust_properties(properties): def has_property(name, properties): return name in [re.sub("=.*", "", p) for p in properties] +def get_target_os(properties): + for m in [re.match("(.*)=(.*)", p) for p in properties]: + if m and m.group(1) == "target-os": + return m.group(2) + return default_target_os + def expand_properties(properties): result = properties[:] if not has_property("variant", properties): @@ -75,13 +81,8 @@ def test_gcc(version, property_sets): t.run_build_system(["-sPYTHON_CMD=%s" % sys.executable], subdir="src") set_default_target_os(t.read("src/bin/target-os.txt").strip()) - # Fixups required for explicitly setting the toolset - # FIXME: Change BoostBuild.py to support this directly - t.toolset = "gcc-" + version - t.pass_toolset = True - BoostBuild.prepare_prefixes_and_suffixes(t.toolset) - for properties in property_sets: + t.set_toolset("gcc-" + version, get_target_os(properties)) properties = adjust_properties(properties) path = compute_path(properties) os.environ["B2_PROPERTIES"] = " ".join(expand_properties(properties)) From b339e8df4b658b07fec4e5d6537071fd9ab9b706 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 26 Dec 2017 10:38:14 -0700 Subject: [PATCH 39/72] Fix property order. --- test/gcc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/gcc.py b/test/gcc.py index 7314fbb84..f28d35f6a 100644 --- a/test/gcc.py +++ b/test/gcc.py @@ -62,14 +62,14 @@ def compute_path(properties): path += "/release" else: path += "/debug" - if "threading=multi" in properties: - path += "/threading-multi" if "link=static" in properties: path += "/link-static" if "runtime-link=static" in properties: path += "/runtime-link-static" if "target-os=linux" in properties: path += "/target-os-linux" + if "threading=multi" in properties: + path += "/threading-multi" return path def test_gcc(version, property_sets): From 0c2f6ba03fe1372789aab027bba2ac8b5df09a0a Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 26 Dec 2017 10:51:30 -0700 Subject: [PATCH 40/72] Finally kill flavor as a gcc subfeature. Adjust check for cygwin. --- src/tools/common.jam | 4 ++-- src/tools/gcc.jam | 8 ++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/tools/common.jam b/src/tools/common.jam index 6a92d55c2..10059ea01 100644 --- a/src/tools/common.jam +++ b/src/tools/common.jam @@ -925,9 +925,9 @@ local rule toolset-tag ( name : type ? : property-set ) case edg* : tag += edg ; case gcc* : { - switch [ $(property-set).get ] + switch [ $(property-set).get ] { - case *mingw* : tag += mgw ; + case *windows* : tag += mgw ; case * : tag += gcc ; } } diff --git a/src/tools/gcc.jam b/src/tools/gcc.jam index e3b1b9524..ccf973985 100644 --- a/src/tools/gcc.jam +++ b/src/tools/gcc.jam @@ -37,7 +37,6 @@ if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ] feature.extend toolset : gcc ; -# feature.subfeature toolset gcc : flavor : : optional ; toolset.inherit-generators gcc : unix : unix.link unix.link.dll ; toolset.inherit-flags gcc : unix ; @@ -189,14 +188,11 @@ rule init ( version ? : command * : options * : requirement * ) switch $(machine:L) { case *mingw* : flavor ?= mingw ; + case *cygwin* : flavor ?= cygwin ; } } local condition ; - if $(flavor) - { - condition = flavor $(flavor) ; - } condition = [ common.check-init-parameters gcc $(requirement) : version $(version) : $(condition) ] ; @@ -285,7 +281,7 @@ rule .get-prog-name ( command-string : tool : flavor ? ) local prog-name = [ NORMALIZE_PATH [ MATCH "(.*)[\n]+" : [ SHELL "$(command-string) -print-prog-name=$(tool)" ] ] ] ; - if $(flavor) != vxworks && $(flavor) != mingw && [ os.name ] = NT + if $(flavor) = cygwin && [ os.name ] = NT { prog-name = [ cygwin.cygwin-to-windows-path $(prog-name) ] ; } From fa78d4fed7b6d43b2202e389ddba2cc9be98c89f Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 26 Dec 2017 13:25:40 -0700 Subject: [PATCH 41/72] Don't pass -d0, except for the tests that actually require it. Suppress global -d arguments for tests that check stdout or set -d explicitly. All tests now pass in verbose mode. --- test/BoostBuild.py | 9 +++++---- test/alias.py | 4 +--- test/core_action_output.py | 2 +- test/core_arguments.py | 2 +- test/core_bindrule.py | 2 +- test/core_d12.py | 2 +- test/core_import_module.py | 4 ++-- test/core_jamshell.py | 2 +- test/core_multifile_actions.py | 2 +- test/core_nt_cmd_line.py | 6 +++--- test/core_option_d2.py | 2 +- test/core_option_n.py | 2 +- test/core_parallel_actions.py | 2 +- test/core_parallel_multifile_actions_1.py | 2 +- test/core_parallel_multifile_actions_2.py | 2 +- test/core_update_now.py | 14 +++++++------- test/dependency_test.py | 4 ++-- test/generators_test.py | 4 ++-- test/message.py | 2 +- test/path_features.py | 4 ++-- test/rebuilds.py | 2 +- test/test_rc.py | 2 +- 22 files changed, 38 insertions(+), 39 deletions(-) diff --git a/test/BoostBuild.py b/test/BoostBuild.py index a0455c364..9f66c39d7 100644 --- a/test/BoostBuild.py +++ b/test/BoostBuild.py @@ -215,7 +215,7 @@ class Tester(TestCmd.TestCmd): def __init__(self, arguments=None, executable="bjam", match=TestCmd.match_exact, boost_build_path=None, translate_suffixes=True, pass_toolset=True, use_test_config=True, - ignore_toolset_requirements=False, workdir="", pass_d0=True, + ignore_toolset_requirements=False, workdir="", pass_d0=False, **keywords): assert arguments.__class__ is not str @@ -295,7 +295,8 @@ class Tester(TestCmd.TestCmd): verbosity = [] if "--verbose" in sys.argv: keywords["verbose"] = True - verbosity = ["-d+2"] + verbosity = ["-d2"] + self.verbosity = verbosity if boost_build_path is None: boost_build_path = self.original_workdir + "/.." @@ -306,8 +307,6 @@ class Tester(TestCmd.TestCmd): else: program_list.append(os.path.join(jam_build_dir, executable)) program_list.append('-sBOOST_BUILD_PATH="' + boost_build_path + '"') - if verbosity: - program_list += verbosity if arguments: program_list += arguments @@ -457,6 +456,8 @@ class Tester(TestCmd.TestCmd): kw["program"] += self.program if extra_args: kw["program"] += extra_args + if stdout is None and not any(a.startswith("-d") for a in kw["program"]): + kw["program"] += self.verbosity if pass_toolset: kw["program"].append("toolset=" + self.toolset) if use_test_config: diff --git a/test/alias.py b/test/alias.py index 53371f4e6..132e4c390 100644 --- a/test/alias.py +++ b/test/alias.py @@ -99,9 +99,7 @@ int main() {} # ############################################################################### -# We do not pass the '-d0' option to Boost Build here to get more detailed -# information in case of failure. -t = BoostBuild.Tester(pass_d0=False, use_test_config=False) +t = BoostBuild.Tester(use_test_config=False) test_alias_rule(t) test_alias_source_usage_requirements(t) diff --git a/test/core_action_output.py b/test/core_action_output.py index b26f0e0bd..d2734d00e 100755 --- a/test/core_action_output.py +++ b/test/core_action_output.py @@ -9,7 +9,7 @@ import BoostBuild -t = BoostBuild.Tester(["-d1"], pass_d0=False, pass_toolset=False) +t = BoostBuild.Tester(["-d1"], pass_toolset=False) t.write("file.jam", """\ prefix = "echo \\"" ; diff --git a/test/core_arguments.py b/test/core_arguments.py index a6e886ff6..7f1278214 100755 --- a/test/core_arguments.py +++ b/test/core_arguments.py @@ -30,7 +30,7 @@ def test_varargs(t, *args, **kwargs): test(t, "varargs", *args, **kwargs) -t = BoostBuild.Tester(pass_toolset=0, pass_d0=False) +t = BoostBuild.Tester(pass_toolset=0) t.write("echo_args.jam", """\ NOCARE all ; diff --git a/test/core_bindrule.py b/test/core_bindrule.py index 6ae4ab34c..5a8faca1e 100755 --- a/test/core_bindrule.py +++ b/test/core_bindrule.py @@ -8,7 +8,7 @@ import BoostBuild import os -t = BoostBuild.Tester(pass_toolset=0, pass_d0=False) +t = BoostBuild.Tester(["-d1"], pass_toolset=0) t.write("subdir1/file-to-bind", "# This file intentionally left blank") diff --git a/test/core_d12.py b/test/core_d12.py index 5488973d2..370fc4bf1 100644 --- a/test/core_d12.py +++ b/test/core_d12.py @@ -9,7 +9,7 @@ import BoostBuild -t = BoostBuild.Tester(["-ffile.jam"], pass_d0=False, pass_toolset=0) +t = BoostBuild.Tester(["-ffile.jam"], pass_toolset=0) t.write("file.jam", """\ actions a { } diff --git a/test/core_import_module.py b/test/core_import_module.py index c5bbd3e63..5903dcd64 100644 --- a/test/core_import_module.py +++ b/test/core_import_module.py @@ -67,8 +67,7 @@ module c IMPORT_MODULE c : ; c.test ; -actions do-nothing { } -do-nothing all ; +EXIT : 0 ; """) t.run_build_system(["-fcode"], stdout="""\ @@ -77,6 +76,7 @@ R2 L1 A.L1 CTEST + """) t.cleanup() diff --git a/test/core_jamshell.py b/test/core_jamshell.py index 0344a5792..5b14213c3 100644 --- a/test/core_jamshell.py +++ b/test/core_jamshell.py @@ -7,7 +7,7 @@ import BoostBuild import sys -t = BoostBuild.Tester(pass_toolset=False, pass_d0=False) +t = BoostBuild.Tester(pass_toolset=False) t.write("file.jam", """ actions run { diff --git a/test/core_multifile_actions.py b/test/core_multifile_actions.py index 50bfe8339..a9c7f4790 100755 --- a/test/core_multifile_actions.py +++ b/test/core_multifile_actions.py @@ -20,7 +20,7 @@ import BoostBuild -t = BoostBuild.Tester(pass_toolset=0, pass_d0=False) +t = BoostBuild.Tester(["-d1"], pass_toolset=0) t.write("file.jam", """ actions update diff --git a/test/core_nt_cmd_line.py b/test/core_nt_cmd_line.py index 579242d24..064f86826 100755 --- a/test/core_nt_cmd_line.py +++ b/test/core_nt_cmd_line.py @@ -49,7 +49,7 @@ def test_raw_empty(): # get an extra "\r" added in front of it on output. whitespace_out = whitespace_in.replace("\r\n", "\n").replace("\n", "\r\n") - t = BoostBuild.Tester(["-d2", "-d+4"], pass_d0=False, pass_toolset=0, + t = BoostBuild.Tester(["-d2", "-d+4"], pass_toolset=0, use_test_config=False) t.write("file.jam", """\ actions do_empty {%s} @@ -67,7 +67,7 @@ do_empty all ; def test_raw_nt(n=None, error=False): - t = BoostBuild.Tester(["-d1", "-d+4"], pass_d0=False, pass_toolset=0, + t = BoostBuild.Tester(["-d1", "-d+4"], pass_toolset=0, use_test_config=False) cmd_prefix = "%s -c \"print('XXX: " % executable @@ -135,7 +135,7 @@ do_echo all ; def test_raw_to_shell_fallback_nt(): - t = BoostBuild.Tester(["-d1", "-d+4"], pass_d0=False, pass_toolset=0, + t = BoostBuild.Tester(["-d1", "-d+4"], pass_toolset=0, use_test_config=False) cmd_prefix = '%s -c print(' % executable diff --git a/test/core_option_d2.py b/test/core_option_d2.py index bf809aa85..8e6b05a45 100755 --- a/test/core_option_d2.py +++ b/test/core_option_d2.py @@ -7,7 +7,7 @@ import BoostBuild -t = BoostBuild.Tester(pass_toolset=0, pass_d0=False) +t = BoostBuild.Tester(pass_toolset=0) t.write("file.jam", """\ actions .a. diff --git a/test/core_option_n.py b/test/core_option_n.py index 4dab3bf99..af3ee0c3e 100755 --- a/test/core_option_n.py +++ b/test/core_option_n.py @@ -7,7 +7,7 @@ import BoostBuild -t = BoostBuild.Tester(pass_toolset=0, pass_d0=False) +t = BoostBuild.Tester(pass_toolset=0) t.write("file.jam", """\ actions .a. diff --git a/test/core_parallel_actions.py b/test/core_parallel_actions.py index 0d44149b7..4f1627c20 100755 --- a/test/core_parallel_actions.py +++ b/test/core_parallel_actions.py @@ -7,7 +7,7 @@ import BoostBuild -t = BoostBuild.Tester(pass_toolset=0, pass_d0=False) +t = BoostBuild.Tester(["-d1"], pass_toolset=0) t.write("sleep.bat", """\ ::@timeout /T %1 /NOBREAK >nul diff --git a/test/core_parallel_multifile_actions_1.py b/test/core_parallel_multifile_actions_1.py index 8d9448e0c..4b800a788 100755 --- a/test/core_parallel_multifile_actions_1.py +++ b/test/core_parallel_multifile_actions_1.py @@ -17,7 +17,7 @@ import BoostBuild -t = BoostBuild.Tester(pass_toolset=0, pass_d0=False) +t = BoostBuild.Tester(["-d1"], pass_toolset=0) t.write("sleep.bat", """\ ::@timeout /T %1 /NOBREAK >nul diff --git a/test/core_parallel_multifile_actions_2.py b/test/core_parallel_multifile_actions_2.py index ea4034af0..c49e92380 100755 --- a/test/core_parallel_multifile_actions_2.py +++ b/test/core_parallel_multifile_actions_2.py @@ -20,7 +20,7 @@ import BoostBuild -t = BoostBuild.Tester(pass_toolset=0, pass_d0=False) +t = BoostBuild.Tester(pass_toolset=0) t.write("sleep.bat", """\ ::@timeout /T %1 /NOBREAK >nul diff --git a/test/core_update_now.py b/test/core_update_now.py index 819309a73..5535c3189 100755 --- a/test/core_update_now.py +++ b/test/core_update_now.py @@ -9,7 +9,7 @@ import os def basic(): - t = BoostBuild.Tester(pass_toolset=0, pass_d0=False) + t = BoostBuild.Tester(pass_toolset=0) t.write("file.jam", """\ actions do-print @@ -39,7 +39,7 @@ updating target1 def ignore_minus_n(): - t = BoostBuild.Tester(pass_toolset=0, pass_d0=False) + t = BoostBuild.Tester(pass_toolset=0) t.write("file.jam", """\ actions do-print @@ -72,7 +72,7 @@ updating target1 def failed_target(): - t = BoostBuild.Tester(pass_toolset=0, pass_d0=False) + t = BoostBuild.Tester(pass_toolset=0) t.write("file.jam", """\ actions fail @@ -120,7 +120,7 @@ do-print target2 def missing_target(): - t = BoostBuild.Tester(pass_toolset=0, pass_d0=False) + t = BoostBuild.Tester(pass_toolset=0) t.write("file.jam", """\ actions do-print @@ -155,7 +155,7 @@ def build_once(): effect. """ - t = BoostBuild.Tester(pass_toolset=0, pass_d0=False) + t = BoostBuild.Tester(pass_toolset=0) t.write("file.jam", """\ actions do-print @@ -199,7 +199,7 @@ def return_status(): Make sure that UPDATE_NOW returns a failure status if the target failed in a previous call to UPDATE_NOW """ - t = BoostBuild.Tester(pass_toolset=0, pass_d0=False) + t = BoostBuild.Tester(pass_toolset=0) t.write("file.jam", """\ actions fail @@ -237,7 +237,7 @@ update2: def save_restore(): """Tests that ignore-minus-n and ignore-minus-q are local to the call to UPDATE_NOW""" - t = BoostBuild.Tester(pass_toolset=0, pass_d0=False) + t = BoostBuild.Tester(pass_toolset=0) t.write("actions.jam", """\ rule fail diff --git a/test/dependency_test.py b/test/dependency_test.py index a495affff..852955775 100644 --- a/test/dependency_test.py +++ b/test/dependency_test.py @@ -10,7 +10,7 @@ import BoostBuild def test_basic(): - t = BoostBuild.Tester(["-d3", "-d+12"], pass_d0=False, use_test_config=False) + t = BoostBuild.Tester(["-d3", "-d+12"], use_test_config=False) t.write("a.cpp", """ #include @@ -211,7 +211,7 @@ def test_scanned_includes_with_absolute_paths(): considered when scanning dependencies. """ - t = BoostBuild.Tester(["-d3", "-d+12"], pass_d0=False) + t = BoostBuild.Tester(["-d3", "-d+12"]) t.write("jamroot.jam", """\ path-constant TOP : . ; diff --git a/test/generators_test.py b/test/generators_test.py index d666d46c2..7d0997404 100644 --- a/test/generators_test.py +++ b/test/generators_test.py @@ -12,7 +12,7 @@ import re def test_basic(): - t = BoostBuild.Tester(pass_d0=False) + t = BoostBuild.Tester() __write_appender(t, "appender.jam") t.write("a.cpp", "") t.write("b.cxx", "") @@ -285,7 +285,7 @@ appender.register ccc-to-ddd composing : CCC : DDD ; ddd _xxx : _xxx._a ; """ - t = BoostBuild.Tester(pass_d0=False) + t = BoostBuild.Tester() __write_appender(t, "appender.jam") t.write("_xxx._a", "") diff --git a/test/message.py b/test/message.py index 5b4f7da81..30edced4d 100755 --- a/test/message.py +++ b/test/message.py @@ -10,7 +10,7 @@ import BoostBuild # Create a temporary working directory. -t = BoostBuild.Tester(use_test_config=False) +t = BoostBuild.Tester(["-d0"], use_test_config=False) t.write("Jamroot.jam", """ project diff --git a/test/path_features.py b/test/path_features.py index f8a3f7caa..b43b86d4c 100644 --- a/test/path_features.py +++ b/test/path_features.py @@ -96,7 +96,7 @@ int main() { return OK; } def test_paths_set_by_indirect_conditionals(): - t = BoostBuild.Tester(pass_d0=False, use_test_config=False) + t = BoostBuild.Tester(use_test_config=False) header = "child_dir/folder_to_include/some_header.h" @@ -139,7 +139,7 @@ int main() {} t.expect_touch(expected_x2) t.touch(header) - t.run_build_system(["..", "-d2"], subdir="child_dir/folder_to_include") + t.run_build_system([".."], subdir="child_dir/folder_to_include") t.expect_touch(expected_x1) t.expect_touch(expected_x2) diff --git a/test/rebuilds.py b/test/rebuilds.py index 89ad4d84f..8242e3ec0 100644 --- a/test/rebuilds.py +++ b/test/rebuilds.py @@ -21,7 +21,7 @@ def wait_for_bar(t): t.wait_for_time_change("bar", touch=False) -t = BoostBuild.Tester(["-ffile.jam", "-d+3", "-d+12", "-d+13"], pass_d0=False, +t = BoostBuild.Tester(["-ffile.jam", "-d+3", "-d+12", "-d+13"], pass_toolset=0) t.write("file.jam", """\ diff --git a/test/test_rc.py b/test/test_rc.py index 1ffac15b0..89976fe9a 100755 --- a/test/test_rc.py +++ b/test/test_rc.py @@ -34,7 +34,7 @@ def included_resource_newer_than_rc_script(): # affected by any local (mis)configuration.. t = BoostBuild.Tester(["-d4", "--debug-configuration", "--ignore-site-config", "--user-config=", "toolset=%s" % toolsetName], - pass_d0=False, pass_toolset=False, use_test_config=False, + pass_toolset=False, use_test_config=False, translate_suffixes=False) # Prepare a dummy toolset so we do not get errors in case the default one From a84c6d4c0cf806750929dd0e73c59cd68375c8ae Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 26 Dec 2017 16:31:37 -0700 Subject: [PATCH 42/72] Add gcc/target-os=darwin test. --- test/TestToolset.py | 100 ++++++++++++++++++++++ test/gcc.py | 100 ++-------------------- test/toolset-mock/project-config.jam | 1 + test/toolset-mock/src/ar.py | 2 + test/toolset-mock/src/gcc-4.2.1-darwin.py | 37 ++++++++ test/toolset-mock/src/ranlib.py | 2 + 6 files changed, 151 insertions(+), 91 deletions(-) create mode 100644 test/TestToolset.py create mode 100644 test/toolset-mock/src/gcc-4.2.1-darwin.py diff --git a/test/TestToolset.py b/test/TestToolset.py new file mode 100644 index 000000000..c03d3f960 --- /dev/null +++ b/test/TestToolset.py @@ -0,0 +1,100 @@ +#!/usr/bin/python +# +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# validates a toolset using a mock of the compiler + +import BoostBuild +import os +import re +import sys + +renames = {"debug": "variant=debug", "release": "variant=release"} + +def set_default_target_os(os): + global removed + global default_target_os + default_target_os = os + removed = set() + removed.add("target-os=" + default_target_os) + +def adjust_property(property): + global renames + if property in renames: + return renames[property] + else: + return property + +def adjust_properties(properties): + global removed + return [adjust_property(p) for p in properties if p not in removed] + +def has_property(name, properties): + return name in [re.sub("=.*", "", p) for p in properties] + +def get_target_os(properties): + for m in [re.match("(.*)=(.*)", p) for p in properties]: + if m and m.group(1) == "target-os": + return m.group(2) + return default_target_os + +def expand_properties(properties): + result = properties[:] + if not has_property("variant", properties): + result += ["variant=debug"] + if not has_property("threading", properties): + result += ["threading=single"] + if not has_property("link", properties): + result += ["link=shared"] + if not has_property("runtime-link", properties): + result += ["runtime-link=shared"] + if not has_property("target-os", properties): + result += ["target-os=" + default_target_os] + return result + +def compute_path(properties): + path = "" + if "variant=release" in properties: + path += "/release" + else: + path += "/debug" + if "link=static" in properties: + path += "/link-static" + if "runtime-link=static" in properties: + path += "/runtime-link-static" + if get_target_os(properties) != default_target_os: + path += "/target-os-" + get_target_os(properties) + if "threading=multi" in properties: + path += "/threading-multi" + return path + +def test_toolset(toolset, version, property_sets): + t = BoostBuild.Tester() + + t.set_tree("toolset-mock") + + # Build necessary tools + t.run_build_system(["-sPYTHON_CMD=%s" % sys.executable], subdir="src") + set_default_target_os(t.read("src/bin/target-os.txt").strip()) + + for properties in property_sets: + t.set_toolset(toolset + "-" + version, get_target_os(properties)) + properties = adjust_properties(properties) + path = toolset + "-*" + version + compute_path(properties) + os.environ["B2_PROPERTIES"] = " ".join(expand_properties(properties)) + t.run_build_system(["--user-config="] + properties) + t.expect_addition("bin/%s/lib.obj" % (path)) + if "link=static" not in properties: + t.expect_addition("bin/%s/l1.dll" % (path)) + else: + t.expect_addition("bin/%s/l1.lib" % (path)) + t.expect_addition("bin/%s/main.obj" % (path)) + t.expect_addition("bin/%s/test.exe" % (path)) + t.expect_nothing_more() + t.rm("bin") + + t.cleanup() diff --git a/test/gcc.py b/test/gcc.py index f28d35f6a..9007de3e8 100644 --- a/test/gcc.py +++ b/test/gcc.py @@ -8,100 +8,18 @@ # validates the gcc toolset using a mock of gcc -import BoostBuild -import os -import re -import sys +from TestToolset import test_toolset -renames = {"debug": "variant=debug", "release": "variant=release"} - -def set_default_target_os(os): - global removed - global default_target_os - default_target_os = os - removed = set() - removed.add("target-os=" + default_target_os) - -def adjust_property(property): - global renames - if property in renames: - return renames[property] - else: - return property - -def adjust_properties(properties): - global removed - return [adjust_property(p) for p in properties if p not in removed] - -def has_property(name, properties): - return name in [re.sub("=.*", "", p) for p in properties] - -def get_target_os(properties): - for m in [re.match("(.*)=(.*)", p) for p in properties]: - if m and m.group(1) == "target-os": - return m.group(2) - return default_target_os - -def expand_properties(properties): - result = properties[:] - if not has_property("variant", properties): - result += ["variant=debug"] - if not has_property("threading", properties): - result += ["threading=single"] - if not has_property("link", properties): - result += ["link=shared"] - if not has_property("runtime-link", properties): - result += ["runtime-link=shared"] - if not has_property("target-os", properties): - result += ["target-os=" + default_target_os] - return result - -def compute_path(properties): - path = "" - if "variant=release" in properties: - path += "/release" - else: - path += "/debug" - if "link=static" in properties: - path += "/link-static" - if "runtime-link=static" in properties: - path += "/runtime-link-static" - if "target-os=linux" in properties: - path += "/target-os-linux" - if "threading=multi" in properties: - path += "/threading-multi" - return path - -def test_gcc(version, property_sets): - t = BoostBuild.Tester() - - t.set_tree("toolset-mock") - - # Build necessary tools - t.run_build_system(["-sPYTHON_CMD=%s" % sys.executable], subdir="src") - set_default_target_os(t.read("src/bin/target-os.txt").strip()) - - for properties in property_sets: - t.set_toolset("gcc-" + version, get_target_os(properties)) - properties = adjust_properties(properties) - path = compute_path(properties) - os.environ["B2_PROPERTIES"] = " ".join(expand_properties(properties)) - t.run_build_system(["--user-config="] + properties) - t.expect_addition("bin/gcc-*%s%s/lib.obj" % (version, path)) - if "link=static" not in properties: - t.expect_addition("bin/gcc-*%s%s/l1.dll" % (version, path)) - else: - t.expect_addition("bin/gcc-*%s%s/l1.lib" % (version, path)) - t.expect_addition("bin/gcc-*%s%s/main.obj" % (version, path)) - t.expect_addition("bin/gcc-*%s%s/test.exe" % (version, path)) - t.expect_nothing_more() - t.rm("bin") - - t.cleanup() - -test_gcc("4.8.3", [ +test_toolset("gcc", "4.8.3", [ ["target-os=linux"], ["target-os=linux", "release"], ["target-os=linux", "threading=multi"], ["target-os=linux", "link=static"], ["target-os=linux", "link=static", "runtime-link=static"]]) + +test_toolset("gcc", "4.2.1", [ + ["target-os=darwin"], + ["target-os=darwin", "release"], + ["target-os=darwin", "threading=multi"], + ["target-os=darwin", "link=static"], + ["target-os=darwin", "link=static", "runtime-link=static"]]) diff --git a/test/toolset-mock/project-config.jam b/test/toolset-mock/project-config.jam index fbf86b4fa..77aa09481 100644 --- a/test/toolset-mock/project-config.jam +++ b/test/toolset-mock/project-config.jam @@ -6,3 +6,4 @@ path-constant here : . ; using gcc : 4.8.3 : python $(here)/src/gcc-4.8.3-linux.py : : linux ; +using gcc : 4.2.1 : python $(here)/src/gcc-4.2.1-darwin.py : : darwin ; diff --git a/test/toolset-mock/src/ar.py b/test/toolset-mock/src/ar.py index fd3be5322..dd5467301 100644 --- a/test/toolset-mock/src/ar.py +++ b/test/toolset-mock/src/ar.py @@ -10,5 +10,7 @@ from MockProgram import * command('ar', 'rc', output_file('bin/gcc-gnu-4.8.3/debug/link-static/libl1.a'), input_file('bin/gcc-gnu-4.8.3/debug/link-static/lib.o')) command('ar', 'rc', output_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/libl1.a'), input_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/lib.o')) +command('ar', 'rc', output_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-darwin/libl1.a'), input_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-darwin/lib.o')) +command('ar', 'rc', output_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), input_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/lib.o')) main() diff --git a/test/toolset-mock/src/gcc-4.2.1-darwin.py b/test/toolset-mock/src/gcc-4.2.1-darwin.py new file mode 100644 index 000000000..ec88af680 --- /dev/null +++ b/test/toolset-mock/src/gcc-4.2.1-darwin.py @@ -0,0 +1,37 @@ +#!/usr/bin/python +# +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +from MockProgram import * + +command('g++', '-print-prog-name=ar', stdout=script('ar.py')) +command('g++', '-print-prog-name=ranlib', stdout=script('ranlib.py')) + +# all builds are multi-threaded for darwin +if allow_properties("variant=debug", "link=shared", "runtime-link=shared"): + command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-fPIC', '-c', '-o', output_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('g++', '-o', output_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/libl1.dylib'), '-shared', input_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/lib.o'), '-g', '-fPIC') + command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-fPIC', '-c', '-o', output_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('g++', '-Wl,-rpath', arg('-Wl,', target_path('bin/gcc-darwin-4.2.1/debug/target-os-darwin/libl1.dylib')), '-o', output_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/test'), input_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/main.o'), input_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/libl1.dylib'), '-g', '-fPIC') + +if allow_properties("variant=release", "link=shared", "runtime-link=shared"): + command('g++', '-O3', '-finline-functions', '-Wno-inline', '-Wall', '-fPIC', '-DNDEBUG', '-c', '-o', output_file('bin/gcc-darwin-4.2.1/release/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('g++', '-o', output_file('bin/gcc-darwin-4.2.1/release/target-os-darwin/libl1.dylib'), '-shared', input_file('bin/gcc-darwin-4.2.1/release/target-os-darwin/lib.o'), '-fPIC') + command('g++', '-O3', '-finline-functions', '-Wno-inline', '-Wall', '-fPIC', '-DNDEBUG', '-c', '-o', output_file('bin/gcc-darwin-4.2.1/release/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('g++', '-Wl,-rpath', arg('-Wl,', target_path('bin/gcc-darwin-4.2.1/release/target-os-darwin/libl1.dylib')), '-o', output_file('bin/gcc-darwin-4.2.1/release/target-os-darwin/test'), input_file('bin/gcc-darwin-4.2.1/release/target-os-darwin/main.o'), input_file('bin/gcc-darwin-4.2.1/release/target-os-darwin/libl1.dylib'), '-fPIC') + +if allow_properties("variant=debug", "link=static", "runtime-link=shared"): + command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('g++', '-o', output_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-darwin/test'), input_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-darwin/main.o'), input_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-darwin/libl1.a'), '-g') + +if allow_properties("variant=debug", "link=static", "runtime-link=static"): + command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('g++', '-o', output_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/test'), input_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), '-g', '-static') + +main() diff --git a/test/toolset-mock/src/ranlib.py b/test/toolset-mock/src/ranlib.py index 42d1721fc..53011503d 100644 --- a/test/toolset-mock/src/ranlib.py +++ b/test/toolset-mock/src/ranlib.py @@ -10,5 +10,7 @@ from MockProgram import * command('ranlib', input_file('bin/gcc-gnu-4.8.3/debug/link-static/libl1.a')) command('ranlib', input_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/libl1.a')) +command('ranlib', input_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-darwin/libl1.a')) +command('ranlib', input_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/libl1.a')) main() From 53cf891d8aa2a9cf84340ce9af176fbef339193f Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 26 Dec 2017 21:06:44 -0700 Subject: [PATCH 43/72] Add test for the darwin toolset. --- test/darwin.py | 18 ++++++++++++++ test/toolset-mock/project-config.jam | 7 ++++++ test/toolset-mock/src/Jamroot.jam | 13 ++++++---- test/toolset-mock/src/MockProgram.py | 6 ++--- test/toolset-mock/src/darwin-4.2.1.py | 36 +++++++++++++++++++++++++++ test/toolset-mock/src/libtool.py | 14 +++++++++++ 6 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 test/darwin.py create mode 100644 test/toolset-mock/src/darwin-4.2.1.py create mode 100644 test/toolset-mock/src/libtool.py diff --git a/test/darwin.py b/test/darwin.py new file mode 100644 index 000000000..9f1d43d5f --- /dev/null +++ b/test/darwin.py @@ -0,0 +1,18 @@ +#!/usr/bin/python +# +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# validates the darwin toolset using a mock of gcc + +from TestToolset import test_toolset + +test_toolset("darwin", "4.2.1", [ + ["target-os=darwin"], + ["target-os=darwin", "release"], + ["target-os=darwin", "threading=multi"], + ["target-os=darwin", "link=static"], + ["target-os=darwin", "link=static", "runtime-link=static"]]) diff --git a/test/toolset-mock/project-config.jam b/test/toolset-mock/project-config.jam index 77aa09481..f21a062ee 100644 --- a/test/toolset-mock/project-config.jam +++ b/test/toolset-mock/project-config.jam @@ -4,6 +4,13 @@ # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) +import modules ; + path-constant here : . ; + using gcc : 4.8.3 : python $(here)/src/gcc-4.8.3-linux.py : : linux ; using gcc : 4.2.1 : python $(here)/src/gcc-4.2.1-darwin.py : : darwin ; + +# hard-code this to make the test work on other platforms +modules.poke darwin : .host-osx-version : 10.11.0 ; +using darwin : 4.2.1 : python $(here)/src/darwin-4.2.1.py : $(here)/src/bin/libtool : darwin ; diff --git a/test/toolset-mock/src/Jamroot.jam b/test/toolset-mock/src/Jamroot.jam index 51b6f679b..96b78ab54 100644 --- a/test/toolset-mock/src/Jamroot.jam +++ b/test/toolset-mock/src/Jamroot.jam @@ -12,6 +12,7 @@ import feature ; .PYTHON = [ os.environ PYTHON_CMD ] ; path-constant .AR : ar.py ; path-constant .RANLIB : ranlib.py ; +path-constant .LIBTOOL : libtool.py ; rule c-escape ( str ) { @@ -23,19 +24,20 @@ rule cfg-header ( target : : properties * ) local PYTHON = [ c-escape $(.PYTHON) ] ; local AR = [ c-escape $(.AR) ] ; local RANLIB = [ c-escape $(.RANLIB) ] ; + local LIBTOOL = [ c-escape $(.LIBTOOL) ] ; print.output $(target) ; print.text "#define PYTHON_CMD "\"$(PYTHON)\" : true ; print.text "#define AR_CMD "\"$(AR)\" : true ; print.text "#define RANLIB_CMD "\"$(RANLIB)\" : true ; + print.text "#define LIBTOOL_CMD "\"$(LIBTOOL)\" : true ; } +# We can only build one variant at a time and we need to have a fixed path +project : requirements bin ; + make config.h : : @cfg-header ; -project - : requirements - config.h - bin # We can only build one variant at a time and we need to have a fixed path - ; +project : requirements config.h ; rule write-target-os ( target : : properties * ) { @@ -48,3 +50,4 @@ make target-os.txt : : @write-target-os ; exe ar : [ obj ar.obj : mock-program.cpp : PY_SCRIPT=AR_CMD ] ; exe ranlib : [ obj ranlib.obj : mock-program.cpp : PY_SCRIPT=RANLIB_CMD ] ; +exe libtool : [ obj libtool.obj : mock-program.cpp : PY_SCRIPT=LIBTOOL_CMD ] ; \ No newline at end of file diff --git a/test/toolset-mock/src/MockProgram.py b/test/toolset-mock/src/MockProgram.py index 7ca5c1459..90e9631d8 100644 --- a/test/toolset-mock/src/MockProgram.py +++ b/test/toolset-mock/src/MockProgram.py @@ -25,7 +25,7 @@ class ordered: # in any order. class unordered: def __init__(self, *args): - self.args = args + self.args = list(args) def match(self, command_line, pos, outputs): unmatched = self.args[:] while len(unmatched) > 0: @@ -116,12 +116,12 @@ def make_file_contents(id): # is removed from the list. # Returns the index after the end of the match def try_match_one(command_line, pos, patterns, outputs): - for p in pattern: + for p in patterns: tmp = outputs[:] res = try_match(command_line, pos, p, tmp) if res is not None: outputs[:] = tmp - pattern.remove(p) + patterns.remove(p) return res # returns the end of the match if any diff --git a/test/toolset-mock/src/darwin-4.2.1.py b/test/toolset-mock/src/darwin-4.2.1.py new file mode 100644 index 000000000..2371b2119 --- /dev/null +++ b/test/toolset-mock/src/darwin-4.2.1.py @@ -0,0 +1,36 @@ +#!/usr/bin/python +# +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +from MockProgram import * + +command('g++', '-dumpversion', stdout='4.2.1') + +# all builds are multi-threaded for darwin +if allow_properties("variant=debug", "link=shared", "runtime-link=shared"): + command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-dynamic', '-gdwarf-2', '-fexceptions', '-fPIC', '-c', '-o', output_file('bin/darwin-4.2.1/debug/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('g++', '-dynamiclib', '-Wl,-single_module', '-install_name', 'libl1.dylib', '-o', output_file('bin/darwin-4.2.1/debug/target-os-darwin/libl1.dylib'), input_file('bin/darwin-4.2.1/debug/target-os-darwin/lib.o'), '-headerpad_max_install_names', '-g', '-fPIC') + command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-dynamic', '-gdwarf-2', '-fexceptions', '-fPIC', '-c', '-o', output_file('bin/darwin-4.2.1/debug/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('g++', '-o', output_file('bin/darwin-4.2.1/debug/target-os-darwin/test'), input_file('bin/darwin-4.2.1/debug/target-os-darwin/main.o'), input_file('bin/darwin-4.2.1/debug/target-os-darwin/libl1.dylib'), '-g', '-fPIC') + +if allow_properties("variant=release", "link=shared", "runtime-link=shared"): + command('g++', unordered('-O3', '-Wno-inline', '-Wall', '-dynamic', '-gdwarf-2', '-fexceptions', '-fPIC'), '-DNDEBUG', '-c', '-o', output_file('bin/darwin-4.2.1/release/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('g++', '-dynamiclib', '-Wl,-single_module', '-install_name', 'libl1.dylib', '-o', output_file('bin/darwin-4.2.1/release/target-os-darwin/libl1.dylib'), input_file('bin/darwin-4.2.1/release/target-os-darwin/lib.o'), '-headerpad_max_install_names', '-Wl,-dead_strip', '-no_dead_strip_inits_and_terms', '-fPIC') + command('g++', unordered('-O3', '-Wno-inline', '-Wall', '-dynamic', '-gdwarf-2', '-fexceptions', '-fPIC'), '-DNDEBUG', '-c', '-o', output_file('bin/darwin-4.2.1/release/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('g++', '-o', output_file('bin/darwin-4.2.1/release/target-os-darwin/test'), input_file('bin/darwin-4.2.1/release/target-os-darwin/main.o'), input_file('bin/darwin-4.2.1/release/target-os-darwin/libl1.dylib'), '-Wl,-dead_strip', '-no_dead_strip_inits_and_terms', '-fPIC') + +if allow_properties("variant=debug", "link=static", "runtime-link=shared"): + command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-gdwarf-2', '-fexceptions', '-c', '-o', output_file('bin/darwin-4.2.1/debug/link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-gdwarf-2', '-fexceptions', '-c', '-o', output_file('bin/darwin-4.2.1/debug/link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('g++', '-o', output_file('bin/darwin-4.2.1/debug/link-static/target-os-darwin/test'), input_file('bin/darwin-4.2.1/debug/link-static/target-os-darwin/main.o'), input_file('bin/darwin-4.2.1/debug/link-static/target-os-darwin/libl1.a'), '-g') + +if allow_properties("variant=debug", "link=static", "runtime-link=static"): + command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-gdwarf-2', '-fexceptions', '-c', '-o', output_file('bin/darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-gdwarf-2', '-fexceptions', '-c', '-o', output_file('bin/darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('g++', '-o', output_file('bin/darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/test'), input_file('bin/darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file('bin/darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), '-g', '-nodefaultlibs', '-shared-libgcc', '-lstdc++-static', '-lgcc_eh', '-lgcc', '-lSystem', '-static') + +main() diff --git a/test/toolset-mock/src/libtool.py b/test/toolset-mock/src/libtool.py new file mode 100644 index 000000000..9f58dc96d --- /dev/null +++ b/test/toolset-mock/src/libtool.py @@ -0,0 +1,14 @@ +#!/usr/bin/python +# +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +from MockProgram import * + +command('libtool', '-static', '-o', output_file('bin/darwin-4.2.1/debug/link-static/target-os-darwin/libl1.a'), input_file('bin/darwin-4.2.1/debug/link-static/target-os-darwin/lib.o')) +command('libtool', '-static', '-o', output_file('bin/darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), input_file('bin/darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/lib.o')) + +main() From 6ffd6b9c7a7cd1a0ec4b5d22874af29a3b70c8f7 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Wed, 27 Dec 2017 13:30:23 -0700 Subject: [PATCH 44/72] Add test for clang-darwin. --- test/TestToolset.py | 16 ++++++-- test/clang-darwin.py | 19 +++++++++ test/darwin.py | 7 +++- test/test_all.py | 2 + test/toolset-mock/project-config.jam | 11 +++++- test/toolset-mock/src/Jamroot.jam | 6 ++- test/toolset-mock/src/ar.py | 2 + test/toolset-mock/src/clang-3.9.0-darwin.py | 43 +++++++++++++++++++++ test/toolset-mock/src/ranlib.py | 2 + test/toolset-mock/src/strip.py | 13 +++++++ 10 files changed, 114 insertions(+), 7 deletions(-) create mode 100644 test/clang-darwin.py create mode 100644 test/toolset-mock/src/clang-3.9.0-darwin.py create mode 100644 test/toolset-mock/src/strip.py diff --git a/test/TestToolset.py b/test/TestToolset.py index c03d3f960..88a847d3d 100644 --- a/test/TestToolset.py +++ b/test/TestToolset.py @@ -36,11 +36,13 @@ def adjust_properties(properties): def has_property(name, properties): return name in [re.sub("=.*", "", p) for p in properties] -def get_target_os(properties): +def get_property(name, properties): for m in [re.match("(.*)=(.*)", p) for p in properties]: - if m and m.group(1) == "target-os": + if m and m.group(1) == name: return m.group(2) - return default_target_os + +def get_target_os(properties): + return get_property("target-os", properties) or default_target_os def expand_properties(properties): result = properties[:] @@ -52,6 +54,8 @@ def expand_properties(properties): result += ["link=shared"] if not has_property("runtime-link", properties): result += ["runtime-link=shared"] + if not has_property("strip", properties): + result += ["strip=off"] if not has_property("target-os", properties): result += ["target-os=" + default_target_os] return result @@ -62,10 +66,16 @@ def compute_path(properties): path += "/release" else: path += "/debug" + if has_property("address-model", properties): + path += "/address-model-" + get_property("address-model", properties) + if has_property("architecture", properties): + path += "/architecture-" + get_property("architecture", properties) if "link=static" in properties: path += "/link-static" if "runtime-link=static" in properties: path += "/runtime-link-static" + if "strip=on" in properties: + path += "/strip-on" if get_target_os(properties) != default_target_os: path += "/target-os-" + get_target_os(properties) if "threading=multi" in properties: diff --git a/test/clang-darwin.py b/test/clang-darwin.py new file mode 100644 index 000000000..e3bb0265f --- /dev/null +++ b/test/clang-darwin.py @@ -0,0 +1,19 @@ +#!/usr/bin/python +# +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# validates the clang-darwin toolset using a mock of clang + +from TestToolset import test_toolset + +test_toolset("clang-darwin", "3.9.0", [ + ["target-os=darwin"], + ["target-os=darwin", "release", "strip=on"], + ["target-os=darwin", "threading=multi"], + ["target-os=darwin", "link=static"], + ["target-os=darwin", "link=static", "runtime-link=static"], + ["target-os=darwin", "architecture=x86", "address-model=32"]]) diff --git a/test/darwin.py b/test/darwin.py index 9f1d43d5f..58ecc8d2b 100644 --- a/test/darwin.py +++ b/test/darwin.py @@ -12,7 +12,10 @@ from TestToolset import test_toolset test_toolset("darwin", "4.2.1", [ ["target-os=darwin"], - ["target-os=darwin", "release"], + ["target-os=darwin", "release", "strip=on"], ["target-os=darwin", "threading=multi"], ["target-os=darwin", "link=static"], - ["target-os=darwin", "link=static", "runtime-link=static"]]) + ["target-os=darwin", "link=static", "runtime-link=static"], +# Address-model handling is quite broken +# ["target-os=darwin", "architecture=x86", "address-model=32"] +]) diff --git a/test/test_all.py b/test/test_all.py index efb7134a5..4df8d3cab 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -175,6 +175,7 @@ tests = ["absolute_sources", "bzip2", "c_file", "chain", + "clang-darwin", "clean", "composite", "conditionals", @@ -203,6 +204,7 @@ tests = ["absolute_sources", "core_update_now", "core_variables_in_actions", "custom_generator", + "darwin", "debugger", "debugger-mi", "default_build", diff --git a/test/toolset-mock/project-config.jam b/test/toolset-mock/project-config.jam index f21a062ee..27e4b7fbe 100644 --- a/test/toolset-mock/project-config.jam +++ b/test/toolset-mock/project-config.jam @@ -13,4 +13,13 @@ using gcc : 4.2.1 : python $(here)/src/gcc-4.2.1-darwin.py : : darwin # hard-code this to make the test work on other platforms modules.poke darwin : .host-osx-version : 10.11.0 ; -using darwin : 4.2.1 : python $(here)/src/darwin-4.2.1.py : $(here)/src/bin/libtool : darwin ; +using darwin : 4.2.1 : python $(here)/src/darwin-4.2.1.py + : $(here)/src/bin/libtool + $(here)/src/bin/strip + : darwin + ; + +using clang-darwin : 3.9.0 : python $(here)/src/clang-3.9.0-darwin.py + : $(here)/src/bin/ar + $(here)/src/bin/ranlib + ; diff --git a/test/toolset-mock/src/Jamroot.jam b/test/toolset-mock/src/Jamroot.jam index 96b78ab54..901afdbf4 100644 --- a/test/toolset-mock/src/Jamroot.jam +++ b/test/toolset-mock/src/Jamroot.jam @@ -13,6 +13,7 @@ import feature ; path-constant .AR : ar.py ; path-constant .RANLIB : ranlib.py ; path-constant .LIBTOOL : libtool.py ; +path-constant .STRIP : strip.py ; rule c-escape ( str ) { @@ -25,11 +26,13 @@ rule cfg-header ( target : : properties * ) local AR = [ c-escape $(.AR) ] ; local RANLIB = [ c-escape $(.RANLIB) ] ; local LIBTOOL = [ c-escape $(.LIBTOOL) ] ; + local STRIP = [ c-escape $(.STRIP) ] ; print.output $(target) ; print.text "#define PYTHON_CMD "\"$(PYTHON)\" : true ; print.text "#define AR_CMD "\"$(AR)\" : true ; print.text "#define RANLIB_CMD "\"$(RANLIB)\" : true ; print.text "#define LIBTOOL_CMD "\"$(LIBTOOL)\" : true ; + print.text "#define STRIP_CMD "\"$(STRIP)\" : true ; } # We can only build one variant at a time and we need to have a fixed path @@ -50,4 +53,5 @@ make target-os.txt : : @write-target-os ; exe ar : [ obj ar.obj : mock-program.cpp : PY_SCRIPT=AR_CMD ] ; exe ranlib : [ obj ranlib.obj : mock-program.cpp : PY_SCRIPT=RANLIB_CMD ] ; -exe libtool : [ obj libtool.obj : mock-program.cpp : PY_SCRIPT=LIBTOOL_CMD ] ; \ No newline at end of file +exe libtool : [ obj libtool.obj : mock-program.cpp : PY_SCRIPT=LIBTOOL_CMD ] ; +exe strip : [ obj strip.obj : mock-program.cpp : PY_SCRIPT=STRIP_CMD ] ; diff --git a/test/toolset-mock/src/ar.py b/test/toolset-mock/src/ar.py index dd5467301..dba8bf207 100644 --- a/test/toolset-mock/src/ar.py +++ b/test/toolset-mock/src/ar.py @@ -12,5 +12,7 @@ command('ar', 'rc', output_file('bin/gcc-gnu-4.8.3/debug/link-static/libl1.a'), command('ar', 'rc', output_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/libl1.a'), input_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/lib.o')) command('ar', 'rc', output_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-darwin/libl1.a'), input_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-darwin/lib.o')) command('ar', 'rc', output_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), input_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/lib.o')) +command('ar', 'rc', output_file('bin/clang-darwin-3.9.0/debug/link-static/target-os-darwin/libl1.a'), input_file('bin/clang-darwin-3.9.0/debug/link-static/target-os-darwin/lib.o')) +command('ar', 'rc', output_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), input_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/lib.o')) main() diff --git a/test/toolset-mock/src/clang-3.9.0-darwin.py b/test/toolset-mock/src/clang-3.9.0-darwin.py new file mode 100644 index 000000000..c5db106ff --- /dev/null +++ b/test/toolset-mock/src/clang-3.9.0-darwin.py @@ -0,0 +1,43 @@ +#!/usr/bin/python +# +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +from MockProgram import * + +command('clang++', '-print-prog-name=ar', stdout=script('ar.py')) +command('clang++', '-print-prog-name=ranlib', stdout=script('ranlib.py')) + +# all builds are multi-threaded for darwin +if allow_properties("variant=debug", "link=shared", "runtime-link=shared"): + command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-fPIC', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', '@rpath/libl1.dylib', input_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/lib.o'), '-g', '-fPIC') + command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-fPIC', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/test'), input_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/main.o'), input_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/libl1.dylib'), '-g', '-fPIC') + +if allow_properties("variant=release", "link=shared", "runtime-link=shared"): + command('clang++', '-x', 'c++', unordered('-O3', '-Wno-inline', '-Wall', '-fPIC'), '-DNDEBUG', '-c', '-o', output_file('bin/clang-darwin-3.9.0/release/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/release/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', '@rpath/libl1.dylib', input_file('bin/clang-darwin-3.9.0/release/target-os-darwin/lib.o'), '-fPIC') + command('clang++', '-x', 'c++', unordered('-O3', '-Wno-inline', '-Wall', '-fPIC'), '-DNDEBUG', '-c', '-o', output_file('bin/clang-darwin-3.9.0/release/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/release/target-os-darwin/test'), input_file('bin/clang-darwin-3.9.0/release/target-os-darwin/main.o'), input_file('bin/clang-darwin-3.9.0/release/target-os-darwin/libl1.dylib'), '-fPIC') + +if allow_properties("variant=debug", "link=static", "runtime-link=shared"): + command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/link-static/target-os-darwin/test'), input_file('bin/clang-darwin-3.9.0/debug/link-static/target-os-darwin/main.o'), input_file('bin/clang-darwin-3.9.0/debug/link-static/target-os-darwin/libl1.a'), '-g') + +if allow_properties("variant=debug", "link=static", "runtime-link=static"): + command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/test'), input_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), '-g', '-static') + +if allow_properties("variant=debug", "link=shared", "runtime-link=shared", "architecture=x86", "address-model=32"): + command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-march=i686', '-fPIC', '-m32', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', '@rpath/libl1.dylib', input_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/lib.o'), '-g', '-march=i686', '-fPIC', '-m32') + command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-march=i686', '-fPIC', '-m32', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/test'), input_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/main.o'), input_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/libl1.dylib'), '-g', '-march=i686', '-fPIC', '-m32') + +main() diff --git a/test/toolset-mock/src/ranlib.py b/test/toolset-mock/src/ranlib.py index 53011503d..1cf40c458 100644 --- a/test/toolset-mock/src/ranlib.py +++ b/test/toolset-mock/src/ranlib.py @@ -12,5 +12,7 @@ command('ranlib', input_file('bin/gcc-gnu-4.8.3/debug/link-static/libl1.a')) command('ranlib', input_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/libl1.a')) command('ranlib', input_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-darwin/libl1.a')) command('ranlib', input_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/libl1.a')) +command('ranlib', input_file('bin/clang-darwin-3.9.0/debug/link-static/target-os-darwin/libl1.a')) +command('ranlib', input_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/libl1.a')) main() diff --git a/test/toolset-mock/src/strip.py b/test/toolset-mock/src/strip.py new file mode 100644 index 000000000..6245588bf --- /dev/null +++ b/test/toolset-mock/src/strip.py @@ -0,0 +1,13 @@ +#!/usr/bin/python +# +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +from MockProgram import * + +command('strip', '-S', '-x', input_file('bin/darwin-4.2.1/release/target-os-darwin/test')) + +main() From dda019c9d941be38dd95b318387e7450748f9e95 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Thu, 28 Dec 2017 15:40:00 -0700 Subject: [PATCH 45/72] Tests for intel-darwin. --- test/toolset-mock/project-config.jam | 5 +++ test/toolset-mock/src/MockProgram.py | 2 +- test/toolset-mock/src/ar.py | 2 + test/toolset-mock/src/clang-3.9.0-darwin.py | 8 ++-- test/toolset-mock/src/darwin-4.2.1.py | 2 + test/toolset-mock/src/intel-darwin-10.2.py | 43 +++++++++++++++++++++ test/toolset-mock/src/ranlib.py | 2 + test/toolset_intel_darwin.py | 19 +++++++++ 8 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 test/toolset-mock/src/intel-darwin-10.2.py create mode 100644 test/toolset_intel_darwin.py diff --git a/test/toolset-mock/project-config.jam b/test/toolset-mock/project-config.jam index 27e4b7fbe..6c004434c 100644 --- a/test/toolset-mock/project-config.jam +++ b/test/toolset-mock/project-config.jam @@ -23,3 +23,8 @@ using clang-darwin : 3.9.0 : python $(here)/src/clang-3.9.0-darwin.py : $(here)/src/bin/ar $(here)/src/bin/ranlib ; + +using intel-darwin : 10.2 : python $(here)/src/intel-darwin-10.2.py + : $(here)/src/bin/ar + $(here)/src/bin/ranlib + ; diff --git a/test/toolset-mock/src/MockProgram.py b/test/toolset-mock/src/MockProgram.py index 90e9631d8..2e40c6ce4 100644 --- a/test/toolset-mock/src/MockProgram.py +++ b/test/toolset-mock/src/MockProgram.py @@ -255,6 +255,6 @@ def verify(): srcdir = '.' verify_setup() for f in os.listdir(srcdir): - if re.match(r"gcc-.*\.py", f): + if re.match(r"(gcc|clang|darwin)-.*\.py", f): verify_file(f) exit(verify_finalize()) diff --git a/test/toolset-mock/src/ar.py b/test/toolset-mock/src/ar.py index dba8bf207..8a969479f 100644 --- a/test/toolset-mock/src/ar.py +++ b/test/toolset-mock/src/ar.py @@ -14,5 +14,7 @@ command('ar', 'rc', output_file('bin/gcc-darwin-4.2.1/debug/link-static/target-o command('ar', 'rc', output_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), input_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/lib.o')) command('ar', 'rc', output_file('bin/clang-darwin-3.9.0/debug/link-static/target-os-darwin/libl1.a'), input_file('bin/clang-darwin-3.9.0/debug/link-static/target-os-darwin/lib.o')) command('ar', 'rc', output_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), input_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/lib.o')) +command('ar', 'rc', output_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/libl1.a'), input_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/lib.o')) +command('ar', 'rc', output_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), input_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/lib.o')) main() diff --git a/test/toolset-mock/src/clang-3.9.0-darwin.py b/test/toolset-mock/src/clang-3.9.0-darwin.py index c5db106ff..15a2bfc8c 100644 --- a/test/toolset-mock/src/clang-3.9.0-darwin.py +++ b/test/toolset-mock/src/clang-3.9.0-darwin.py @@ -35,9 +35,9 @@ if allow_properties("variant=debug", "link=static", "runtime-link=static"): command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/test'), input_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), '-g', '-static') if allow_properties("variant=debug", "link=shared", "runtime-link=shared", "architecture=x86", "address-model=32"): - command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-march=i686', '-fPIC', '-m32', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/lib.o'), input_file(source='lib.cpp')) - command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', '@rpath/libl1.dylib', input_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/lib.o'), '-g', '-march=i686', '-fPIC', '-m32') - command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-march=i686', '-fPIC', '-m32', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/main.o'), input_file(source='main.cpp')) - command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/test'), input_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/main.o'), input_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/libl1.dylib'), '-g', '-march=i686', '-fPIC', '-m32') + command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-march=i686', '-fPIC', '-m32', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', '@rpath/libl1.dylib', input_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/lib.o'), '-g', '-march=i686', '-fPIC', '-m32') + command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-march=i686', '-fPIC', '-m32', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/test'), input_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/main.o'), input_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/libl1.dylib'), '-g', '-march=i686', '-fPIC', '-m32') main() diff --git a/test/toolset-mock/src/darwin-4.2.1.py b/test/toolset-mock/src/darwin-4.2.1.py index 2371b2119..a29fff9d1 100644 --- a/test/toolset-mock/src/darwin-4.2.1.py +++ b/test/toolset-mock/src/darwin-4.2.1.py @@ -8,6 +8,8 @@ from MockProgram import * +script("libtool.py") + command('g++', '-dumpversion', stdout='4.2.1') # all builds are multi-threaded for darwin diff --git a/test/toolset-mock/src/intel-darwin-10.2.py b/test/toolset-mock/src/intel-darwin-10.2.py new file mode 100644 index 000000000..5638cf55e --- /dev/null +++ b/test/toolset-mock/src/intel-darwin-10.2.py @@ -0,0 +1,43 @@ +#!/usr/bin/python +# +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +from MockProgram import * + +command('icc', '-print-prog-name=ar', stdout=script('ar.py')) +command('icc', '-print-prog-name=ranlib', stdout=script('ranlib.py')) + +# all builds are multi-threaded for darwin +if allow_properties("variant=debug", "link=shared", "runtime-link=shared"): + command('icc', '-xc++', unordered('-O0', '-inline-level=0', '-w1', '-g', '-vec-report0', '-fPIC'), '-c', '-o', output_file('bin/intel-darwin-10.2/debug/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('icc', '-o', output_file('bin/intel-darwin-10.2/debug/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', 'libl1.dylib', input_file('bin/intel-darwin-10.2/debug/target-os-darwin/lib.o'), '-g', '-shared-intel', '-lstdc++', '-lpthread', '-fPIC') + command('icc', '-xc++', unordered('-O0', '-inline-level=0', '-w1', '-g', '-vec-report0', '-fPIC'), '-c', '-o', output_file('bin/intel-darwin-10.2/debug/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('icc', '-o', output_file('bin/intel-darwin-10.2/debug/target-os-darwin/test'), input_file('bin/intel-darwin-10.2/debug/target-os-darwin/main.o'), input_file('bin/intel-darwin-10.2/debug/target-os-darwin/libl1.dylib'), '-g', '-shared-intel', '-lstdc++', '-lpthread', '-fPIC') + +if allow_properties("variant=release", "link=shared", "runtime-link=shared"): + command('icc', '-xc++', unordered('-O3', '-inline-level=2', '-w1', '-vec-report0', '-fPIC'), '-DNDEBUG', '-c', '-o', output_file('bin/intel-darwin-10.2/release/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('icc', '-o', output_file('bin/intel-darwin-10.2/release/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', 'libl1.dylib', input_file('bin/intel-darwin-10.2/release/target-os-darwin/lib.o'), '-shared-intel', '-lstdc++', '-lpthread', '-fPIC') + command('icc', '-xc++', unordered('-O3', '-inline-level=2', '-w1', '-vec-report0', '-fPIC'), '-DNDEBUG', '-c', '-o', output_file('bin/intel-darwin-10.2/release/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('icc', '-o', output_file('bin/intel-darwin-10.2/release/target-os-darwin/test'), input_file('bin/intel-darwin-10.2/release/target-os-darwin/main.o'), input_file('bin/intel-darwin-10.2/release/target-os-darwin/libl1.dylib'), '-shared-intel', '-lstdc++', '-lpthread', '-fPIC') + +if allow_properties("variant=debug", "link=static", "runtime-link=shared"): + command('icc', '-xc++', unordered('-O0', '-inline-level=0', '-w1', '-g', '-vec-report0'), '-c', '-o', output_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('icc', '-xc++', unordered('-O0', '-inline-level=0', '-w1', '-g', '-vec-report0'), '-c', '-o', output_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('icc', '-o', output_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/test'), input_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/main.o'), input_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/libl1.a'), '-g', '-shared-intel', '-lstdc++', '-lpthread') + +if allow_properties("variant=debug", "link=static", "runtime-link=static"): + command('icc', '-xc++', unordered('-O0', '-inline-level=0', '-w1', '-g', '-vec-report0'), '-c', '-o', output_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('icc', '-xc++', unordered('-O0', '-inline-level=0', '-w1', '-g', '-vec-report0'), '-c', '-o', output_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('icc', '-o', output_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/test'), input_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), '-g', '-static', '-static-intel', '-lstdc++', '-lpthread', '-static') + +if allow_properties("variant=debug", "link=shared", "runtime-link=shared", "architecture=x86", "address-model=32"): + command('icc', '-xc++', unordered('-O0', '-inline-level=0', '-w1', '-g', '-vec-report0'), '-march=i686', '-fPIC', '-m32', '-c', '-o', output_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('icc', '-o', output_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', 'libl1.dylib', input_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/lib.o'), '-g', '-shared-intel', '-lstdc++', '-lpthread', '-march=i686', '-fPIC', '-m32') + command('icc', '-xc++', unordered('-O0', '-inline-level=0', '-w1', '-g', '-vec-report0'), '-march=i686', '-fPIC', '-m32', '-c', '-o', output_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('icc', '-o', output_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/test'), input_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/main.o'), input_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/libl1.dylib'), '-g', '-shared-intel', '-lstdc++', '-lpthread', '-march=i686', '-fPIC', '-m32') + +main() diff --git a/test/toolset-mock/src/ranlib.py b/test/toolset-mock/src/ranlib.py index 1cf40c458..a274d5ff7 100644 --- a/test/toolset-mock/src/ranlib.py +++ b/test/toolset-mock/src/ranlib.py @@ -14,5 +14,7 @@ command('ranlib', input_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-d command('ranlib', input_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/libl1.a')) command('ranlib', input_file('bin/clang-darwin-3.9.0/debug/link-static/target-os-darwin/libl1.a')) command('ranlib', input_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/libl1.a')) +command('ranlib', '-cs', input_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/libl1.a')) +command('ranlib', '-cs', input_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/libl1.a')) main() diff --git a/test/toolset_intel_darwin.py b/test/toolset_intel_darwin.py new file mode 100644 index 000000000..db0444900 --- /dev/null +++ b/test/toolset_intel_darwin.py @@ -0,0 +1,19 @@ +#!/usr/bin/python +# +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# validates the intel-darwin toolset using a mock of icc + +from TestToolset import test_toolset + +test_toolset("intel-darwin", "10.2", [ + ["target-os=darwin"], + ["target-os=darwin", "release", "strip=on"], + ["target-os=darwin", "threading=multi"], + ["target-os=darwin", "link=static"], + ["target-os=darwin", "link=static", "runtime-link=static"], + ["target-os=darwin", "architecture=x86", "address-model=32"]]) From 205146c15f804e036f2b2863ce370d7801a990e2 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Fri, 29 Dec 2017 12:32:58 -0700 Subject: [PATCH 46/72] Tests for clang-linux. --- test/TestToolset.py | 2 +- test/toolset-mock/project-config.jam | 5 +++ test/toolset-mock/src/MockProgram.py | 2 +- test/toolset-mock/src/ar.py | 2 + test/toolset-mock/src/clang-linux-3.9.0.py | 48 ++++++++++++++++++++++ test/toolset-mock/src/ranlib.py | 2 + test/toolset_clang_linux.py | 19 +++++++++ 7 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 test/toolset-mock/src/clang-linux-3.9.0.py create mode 100644 test/toolset_clang_linux.py diff --git a/test/TestToolset.py b/test/TestToolset.py index 88a847d3d..ca6e96956 100644 --- a/test/TestToolset.py +++ b/test/TestToolset.py @@ -94,7 +94,7 @@ def test_toolset(toolset, version, property_sets): for properties in property_sets: t.set_toolset(toolset + "-" + version, get_target_os(properties)) properties = adjust_properties(properties) - path = toolset + "-*" + version + compute_path(properties) + path = toolset.split("-")[0] + "-*" + version + compute_path(properties) os.environ["B2_PROPERTIES"] = " ".join(expand_properties(properties)) t.run_build_system(["--user-config="] + properties) t.expect_addition("bin/%s/lib.obj" % (path)) diff --git a/test/toolset-mock/project-config.jam b/test/toolset-mock/project-config.jam index 6c004434c..10291b71c 100644 --- a/test/toolset-mock/project-config.jam +++ b/test/toolset-mock/project-config.jam @@ -24,6 +24,11 @@ using clang-darwin : 3.9.0 : python $(here)/src/clang-3.9.0-darwin.py $(here)/src/bin/ranlib ; +using clang-linux : 3.9.0 : python $(here)/src/clang-linux-3.9.0.py + : $(here)/src/bin/ar + $(here)/src/bin/ranlib + ; + using intel-darwin : 10.2 : python $(here)/src/intel-darwin-10.2.py : $(here)/src/bin/ar $(here)/src/bin/ranlib diff --git a/test/toolset-mock/src/MockProgram.py b/test/toolset-mock/src/MockProgram.py index 2e40c6ce4..ce4723e1e 100644 --- a/test/toolset-mock/src/MockProgram.py +++ b/test/toolset-mock/src/MockProgram.py @@ -255,6 +255,6 @@ def verify(): srcdir = '.' verify_setup() for f in os.listdir(srcdir): - if re.match(r"(gcc|clang|darwin)-.*\.py", f): + if re.match(r"(gcc|clang|darwin|intel)-.*\.py", f): verify_file(f) exit(verify_finalize()) diff --git a/test/toolset-mock/src/ar.py b/test/toolset-mock/src/ar.py index 8a969479f..2e73c3410 100644 --- a/test/toolset-mock/src/ar.py +++ b/test/toolset-mock/src/ar.py @@ -16,5 +16,7 @@ command('ar', 'rc', output_file('bin/clang-darwin-3.9.0/debug/link-static/target command('ar', 'rc', output_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), input_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/lib.o')) command('ar', 'rc', output_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/libl1.a'), input_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/lib.o')) command('ar', 'rc', output_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), input_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/lib.o')) +command('ar', 'rc', output_file('bin/clang-linux-3.9.0/debug/link-static/libl1.a'), input_file('bin/clang-linux-3.9.0/debug/link-static/lib.o')) +command('ar', 'rc', output_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/libl1.a'), input_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/lib.o')) main() diff --git a/test/toolset-mock/src/clang-linux-3.9.0.py b/test/toolset-mock/src/clang-linux-3.9.0.py new file mode 100644 index 000000000..988dbdb3d --- /dev/null +++ b/test/toolset-mock/src/clang-linux-3.9.0.py @@ -0,0 +1,48 @@ +#!/usr/bin/python +# +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +from MockProgram import * + +command('clang++', '-print-prog-name=ar', stdout=script('ar.py')) +command('clang++', '-print-prog-name=ranlib', stdout=script('ranlib.py')) + +if allow_properties('variant=debug', 'link=shared', 'threading=single', 'runtime-link=shared'): + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-fPIC', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/lib.o'), input_file(source='lib.cpp')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/libl1.so'), '-Wl,-soname', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-g', '-fPIC') + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-fPIC', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/main.o'), input_file(source='main.cpp')) + command('clang++', '-Wl,-R', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/libl1.so')), '-o', output_file('bin/clang-linux-3.9.0/debug/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/main.o'), input_file('bin/clang-linux-3.9.0/debug/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-g', '-fPIC') + +if allow_properties('variant=release', 'link=shared', 'threading=single', 'runtime-link=shared', 'strip=on'): + command('clang++', unordered(ordered('-x', 'c++'), '-O3', '-Wno-inline', '-Wall', '-fPIC', '-DNDEBUG', '-c'), '-o', output_file('bin/clang-linux-3.9.0/release/lib.o'), input_file(source='lib.cpp')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/release/libl1.so'), '-Wl,-soname', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/release/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-fPIC', '-Wl,--strip-all') + command('clang++', unordered(ordered('-x', 'c++'), '-O3', '-Wno-inline', '-Wall', '-fPIC', '-DNDEBUG', '-c'), '-o', output_file('bin/clang-linux-3.9.0/release/main.o'), input_file(source='main.cpp')) + command('clang++', '-Wl,-R', arg('-Wl,', target_path('bin/clang-linux-3.9.0/release/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/clang-linux-3.9.0/release/libl1.so')), '-o', output_file('bin/clang-linux-3.9.0/release/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/release/main.o'), input_file('bin/clang-linux-3.9.0/release/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-fPIC', '-Wl,--strip-all') + +if allow_properties('variant=debug', 'link=shared', 'threading=multi', 'runtime-link=shared'): + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-pthread', '-fPIC', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/threading-multi/lib.o'), input_file(source='lib.cpp')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/threading-multi/libl1.so'), '-Wl,-soname', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/threading-multi/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-lrt', '-Wl,--end-group', '-g', '-pthread', '-fPIC') + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-pthread', '-fPIC', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/threading-multi/main.o'), input_file(source='main.cpp')) + command('clang++', '-Wl,-R', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/threading-multi/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/threading-multi/libl1.so')), '-o', output_file('bin/clang-linux-3.9.0/debug/threading-multi/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/threading-multi/main.o'), input_file('bin/clang-linux-3.9.0/debug/threading-multi/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-lrt', '-Wl,--end-group', '-g', '-pthread', '-fPIC') + +if allow_properties('variant=debug', 'link=static', 'threading=single', 'runtime-link=shared'): + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/lib.o'), input_file(source='lib.cpp')) + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/main.o'), input_file(source='main.cpp')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/link-static/main.o'), input_file('bin/clang-linux-3.9.0/debug/link-static/libl1.a'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-g') + +if allow_properties('variant=debug', 'link=static', 'threading=single', 'runtime-link=static'): + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/lib.o'), input_file(source='lib.cpp')) + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/main.o'), input_file(source='main.cpp')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/main.o'), input_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/libl1.a'), '-Wl,--end-group', '-g', '-static') + +if allow_properties('variant=debug', 'link=shared', 'threading=single', 'runtime-link=shared', 'architecture=x86', 'address-model=32'): + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-march=i686', '-m32', '-fPIC', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/lib.o'), input_file(source='lib.cpp')) + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/libl1.so'), '-Wl,-soname', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-g', '-march=i686', '-fPIC', '-m32') + command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-march=i686', '-m32', '-fPIC', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/main.o'), input_file(source='main.cpp')) + command('clang++', '-Wl,-R', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/libl1.so')), '-o', output_file('bin/clang-linux-3.9.0/debug/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/main.o'), input_file('bin/clang-linux-3.9.0/debug/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-g', '-march=i686', '-fPIC', '-m32') + +main() diff --git a/test/toolset-mock/src/ranlib.py b/test/toolset-mock/src/ranlib.py index a274d5ff7..4abe21ed0 100644 --- a/test/toolset-mock/src/ranlib.py +++ b/test/toolset-mock/src/ranlib.py @@ -16,5 +16,7 @@ command('ranlib', input_file('bin/clang-darwin-3.9.0/debug/link-static/target-os command('ranlib', input_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/libl1.a')) command('ranlib', '-cs', input_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/libl1.a')) command('ranlib', '-cs', input_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/libl1.a')) +command('ranlib', input_file('bin/clang-linux-3.9.0/debug/link-static/libl1.a')) +command('ranlib', input_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/libl1.a')) main() diff --git a/test/toolset_clang_linux.py b/test/toolset_clang_linux.py new file mode 100644 index 000000000..2fbf84b6d --- /dev/null +++ b/test/toolset_clang_linux.py @@ -0,0 +1,19 @@ +#!/usr/bin/python +# +# Copyright 2017 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# validates the clang_linux toolset using a mock of clang + +from TestToolset import test_toolset + +test_toolset("clang-linux", "3.9.0", [ + ["target-os=linux"], + ["target-os=linux", "release", "strip=on"], + ["target-os=linux", "threading=multi"], + ["target-os=linux", "link=static"], + ["target-os=linux", "link=static", "runtime-link=static"], + ["target-os=linux", "architecture=x86", "address-model=32"]]) From 44598b21071edd7d11fdeb69010323f3d4c90308 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 30 Dec 2017 10:53:03 -0700 Subject: [PATCH 47/72] Clean up test names. --- test/test_all.py | 7 +++++-- test/{clang-darwin.py => toolset_clang_darwin.py} | 0 test/{darwin.py => toolset_darwin.py} | 0 test/{gcc.py => toolset_gcc.py} | 0 4 files changed, 5 insertions(+), 2 deletions(-) rename test/{clang-darwin.py => toolset_clang_darwin.py} (100%) rename test/{darwin.py => toolset_darwin.py} (100%) rename test/{gcc.py => toolset_gcc.py} (100%) diff --git a/test/test_all.py b/test/test_all.py index 4df8d3cab..905a7289c 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -204,7 +204,6 @@ tests = ["absolute_sources", "core_update_now", "core_variables_in_actions", "custom_generator", - "darwin", "debugger", "debugger-mi", "default_build", @@ -225,7 +224,6 @@ tests = ["absolute_sources", "explicit", "feature_cxxflags", "free_features_request", - "gcc", "generator_selection", "generators_test", "implicit_dependency", @@ -280,6 +278,11 @@ tests = ["absolute_sources", "test_rc", "testing_support", "timedata", + "toolset_clang_darwin", + "toolset_clang_linux", + "toolset_darwin", + "toolset_gcc", + "toolset_intel_darwin", "toolset_requirements", "unit_test", "unused", diff --git a/test/clang-darwin.py b/test/toolset_clang_darwin.py similarity index 100% rename from test/clang-darwin.py rename to test/toolset_clang_darwin.py diff --git a/test/darwin.py b/test/toolset_darwin.py similarity index 100% rename from test/darwin.py rename to test/toolset_darwin.py diff --git a/test/gcc.py b/test/toolset_gcc.py similarity index 100% rename from test/gcc.py rename to test/toolset_gcc.py From 61989801cab6a8f92969fcb82340a1e299e14e5e Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 30 Dec 2017 10:58:14 -0700 Subject: [PATCH 48/72] Unduplicate options. Allow ranlib and ar to be set, to make mocking easier. Fix condition for setting linker-type. --- src/tools/clang-darwin.jam | 26 +++++--------------------- src/tools/clang-linux.jam | 22 +--------------------- src/tools/gcc.jam | 1 + src/tools/intel-darwin.jam | 13 +++++++++++-- 4 files changed, 18 insertions(+), 44 deletions(-) diff --git a/src/tools/clang-darwin.jam b/src/tools/clang-darwin.jam index 9d0197362..e1f6c14ed 100644 --- a/src/tools/clang-darwin.jam +++ b/src/tools/clang-darwin.jam @@ -33,8 +33,7 @@ generators.register-c-compiler clang-darwin.compile.mm : OBJECTIVE_CPP : OBJ : < toolset.inherit-rules clang-darwin : gcc ; toolset.inherit-flags clang-darwin : gcc - : off on full space - off all on + : full x86/32 x86/64 ; @@ -79,42 +78,27 @@ rule init ( version ? : command * : options * ) SPACE = " " ; -toolset.flags clang-darwin.compile OPTIONS ; -toolset.flags clang-darwin.compile.c++ OPTIONS ; toolset.flags clang-darwin.compile.m OPTIONS ; toolset.flags clang-darwin.compile.mm OPTIONS ; toolset.flags clang-darwin.compile.mm OPTIONS ; -# toolset.flags clang-darwin.compile INCLUDES ; # Declare flags and action for compilation. -toolset.flags clang-darwin.compile OPTIONS off : -O0 ; -toolset.flags clang-darwin.compile OPTIONS speed : -O3 ; -toolset.flags clang-darwin.compile OPTIONS space : -Os ; # For clang, 'on' and 'full' are identical -toolset.flags clang-darwin.compile OPTIONS off : -fno-inline ; -toolset.flags clang-darwin.compile OPTIONS on : -Wno-inline ; toolset.flags clang-darwin.compile OPTIONS full : -Wno-inline ; -toolset.flags clang-darwin.compile OPTIONS off : -w ; -toolset.flags clang-darwin.compile OPTIONS on : -Wall ; -toolset.flags clang-darwin.compile OPTIONS all : -Wall -pedantic ; -toolset.flags clang-darwin.compile OPTIONS on : -Werror ; - -toolset.flags clang-darwin.compile OPTIONS on : -g ; -toolset.flags clang-darwin.compile OPTIONS on : -pg ; -toolset.flags clang-darwin.compile OPTIONS off : -fno-rtti ; - +# SJW 12/2017: Support for is widely inconsistant. +# shouldn't this be handled by the common gcc? toolset.flags clang-darwin.compile OPTIONS ; actions compile.c { - "$(CONFIG_COMMAND)" -x c $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" + "$(CONFIG_COMMAND)" -x c $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" } actions compile.c++ { - "$(CONFIG_COMMAND)" -x c++ $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" + "$(CONFIG_COMMAND)" -x c++ $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" } actions compile.m diff --git a/src/tools/clang-linux.jam b/src/tools/clang-linux.jam index b1c2ad95b..8b58ea857 100644 --- a/src/tools/clang-linux.jam +++ b/src/tools/clang-linux.jam @@ -36,9 +36,7 @@ type.set-generated-target-suffix PCH toolset.inherit-rules clang-linux : gcc ; toolset.inherit-flags clang-linux : gcc - : off on full - space speed - off all on ; + : full ; if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ] { .debug-configuration = true ; @@ -75,28 +73,10 @@ rule init ( version ? : command * : options * ) { ############################################################################### # Flags -toolset.flags clang-linux.compile OPTIONS ; -toolset.flags clang-linux.compile.c++ OPTIONS ; - -toolset.flags clang-linux.compile OPTIONS off : ; -toolset.flags clang-linux.compile OPTIONS speed : -O3 ; -toolset.flags clang-linux.compile OPTIONS space : -Os ; - # note: clang silently ignores some of these inlining options -toolset.flags clang-linux.compile OPTIONS off : -fno-inline ; # For clang, 'on' and 'full' are identical. -toolset.flags clang-linux.compile OPTIONS on : -Wno-inline ; toolset.flags clang-linux.compile OPTIONS full : -Wno-inline ; -toolset.flags clang-linux.compile OPTIONS off : -w ; -toolset.flags clang-linux.compile OPTIONS on : -Wall ; -toolset.flags clang-linux.compile OPTIONS all : -Wall -pedantic ; -toolset.flags clang-linux.compile OPTIONS on : -Werror ; - -toolset.flags clang-linux.compile OPTIONS on : -g ; -toolset.flags clang-linux.compile OPTIONS on : -pg ; -toolset.flags clang-linux.compile OPTIONS off : -fno-rtti ; - ############################################################################### # C and C++ compilation diff --git a/src/tools/gcc.jam b/src/tools/gcc.jam index ccf973985..c0ae6895d 100644 --- a/src/tools/gcc.jam +++ b/src/tools/gcc.jam @@ -933,6 +933,7 @@ rule init-link-flags ( toolset subtool condition ) feature.subfeature toolset $(toolset) : linker-type : gnu aix darwin hpux osf sun : propagated link-incompatible ; } + condition = [ regex.replace $(condition) "/" "," ] ; ## The specification to add the linker-type is per toolset "instance". toolset.add-requirements $(condition),aix:aix diff --git a/src/tools/intel-darwin.jam b/src/tools/intel-darwin.jam index 228793eb4..02f25d1bc 100644 --- a/src/tools/intel-darwin.jam +++ b/src/tools/intel-darwin.jam @@ -55,7 +55,7 @@ rule init ( version ? : command * : options * ) common.handle-options intel-darwin : $(condition) : $(command) : $(options) ; - gcc.init-link-flags intel-darwin darwin $(condition) ; + gcc.init-link-flags intel darwin $(condition) ; # handle # local library-path = [ feature.get-values : $(options) ] ; @@ -118,6 +118,14 @@ rule init ( version ? : command * : options * ) if $(major) = "9" || ( $(major) = "10" && ( $(minor) = "0" || $(minor) = "1" ) ) { flags intel-darwin.compile DEFINES $(condition) : __WINT_TYPE__=int : unchecked ; } + + # - Ranlib. + local ranlib = [ feature.get-values : $(options) ] ; + toolset.flags intel-darwin.archive .RANLIB $(condition) : $(ranlib[1]) ; + + # - Archive builder. + local archiver = [ feature.get-values : $(options) ] ; + toolset.flags intel-darwin.archive .AR $(condition) : $(archiver[1]) ; } SPACE = " " ; @@ -168,6 +176,7 @@ flags intel-darwin ARFLAGS ; # logic in intel-linux, but that's hardly worth the trouble # as on Linux, 'ar' is always available. .AR = ar ; +.RANLIB = ranlib ; rule archive ( targets * : sources * : properties * ) { @@ -201,7 +210,7 @@ rule archive ( targets * : sources * : properties * ) actions piecemeal archive { "$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)" - "ranlib" -cs "$(<)" + "$(.RANLIB)" -cs "$(<)" } flags intel-darwin.link USER_OPTIONS ; From bf5db0d505d6196b8bb3c59ccbcae668f1483df6 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 30 Dec 2017 12:19:47 -0700 Subject: [PATCH 49/72] Remove old test name. --- test/test_all.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test_all.py b/test/test_all.py index 905a7289c..78aba01d0 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -175,7 +175,6 @@ tests = ["absolute_sources", "bzip2", "c_file", "chain", - "clang-darwin", "clean", "composite", "conditionals", From 12decb3ce680031b915f69902795eec47224fc7d Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Mon, 1 Jan 2018 12:51:43 -0700 Subject: [PATCH 50/72] Rewrite gcc to use toolset.flags again. --- src/tools/clang-darwin.jam | 3 +- src/tools/clang-linux.jam | 10 +- src/tools/clang-vxworks.jam | 2 - src/tools/clang.jam | 33 + src/tools/darwin.jam | 3 - src/tools/gcc.jam | 736 +++++++------------- src/tools/intel-darwin.jam | 2 - src/tools/intel-linux.jam | 2 - src/tools/intel-vxworks.jam | 2 - src/tools/pgi.jam | 2 - src/util/sequence.jam | 36 + test/TestToolset.py | 2 + test/toolset-mock/src/clang-3.9.0-darwin.py | 34 +- test/toolset-mock/src/clang-linux-3.9.0.py | 18 +- test/toolset-mock/src/darwin-4.2.1.py | 22 +- test/toolset-mock/src/gcc-4.2.1-darwin.py | 22 +- test/toolset-mock/src/gcc-4.8.3-linux.py | 38 +- test/toolset-mock/src/intel-darwin-10.2.py | 20 +- test/toolset_clang_darwin.py | 3 +- test/toolset_gcc.py | 3 +- 20 files changed, 416 insertions(+), 577 deletions(-) diff --git a/src/tools/clang-darwin.jam b/src/tools/clang-darwin.jam index e1f6c14ed..74a323a16 100644 --- a/src/tools/clang-darwin.jam +++ b/src/tools/clang-darwin.jam @@ -64,8 +64,7 @@ rule init ( version ? : command * : options * ) : version $(version) ] ; common.handle-options clang-darwin : $(condition) : $(command) : $(options) ; - - gcc.init-link-flags clang darwin $(condition) ; + clang.init-cxxstd-flags clang-darwin : $(condition) : $(version) ; # - Ranlib. local ranlib = [ feature.get-values : $(options) ] ; diff --git a/src/tools/clang-linux.jam b/src/tools/clang-linux.jam index 8b58ea857..53c5749e5 100644 --- a/src/tools/clang-linux.jam +++ b/src/tools/clang-linux.jam @@ -36,7 +36,9 @@ type.set-generated-target-suffix PCH toolset.inherit-rules clang-linux : gcc ; toolset.inherit-flags clang-linux : gcc - : full ; + : full + multi/windows + ; if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ] { .debug-configuration = true ; @@ -58,8 +60,7 @@ rule init ( version ? : command * : options * ) { : version $(version) ] ; common.handle-options clang-linux : $(condition) : $(command) : $(options) ; - - gcc.init-link-flags clang linux $(condition) ; + clang.init-cxxstd-flags clang-linux : $(condition) : $(version) ; # - Ranlib. local ranlib = [ feature.get-values : $(options) ] ; @@ -77,6 +78,9 @@ rule init ( version ? : command * : options * ) { # For clang, 'on' and 'full' are identical. toolset.flags clang-linux.compile OPTIONS full : -Wno-inline ; +toolset.flags clang-linux.compile OPTIONS multi/windows : -pthread ; +toolset.flags clang-linux.link OPTIONS multi/windows : -pthread ; + ############################################################################### # C and C++ compilation diff --git a/src/tools/clang-vxworks.jam b/src/tools/clang-vxworks.jam index 203a3a320..b104aa7e8 100644 --- a/src/tools/clang-vxworks.jam +++ b/src/tools/clang-vxworks.jam @@ -69,8 +69,6 @@ rule init ( version ? : command * : options * ) common.handle-options clang-vxworks : $(condition) : $(command) : $(options) ; - gcc.init-link-flags clang-vxworks vxworks $(condition) ; - toolset.flags clang-vxworks.link .LD : $(linker) ; } diff --git a/src/tools/clang.jam b/src/tools/clang.jam index 2d89f3807..26c95202a 100644 --- a/src/tools/clang.jam +++ b/src/tools/clang.jam @@ -8,6 +8,9 @@ import feature ; import os ; import toolset ; +import sequence ; +import regex ; +import set ; feature.extend toolset : clang ; feature.subfeature toolset clang : platform : : propagated link-incompatible ; @@ -25,3 +28,33 @@ rule init ( * : * ) $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ; } } + + +local rule cxxstd-flags ( toolset : condition * : options * ) +{ + toolset.flags $(toolset).compile.c++ OPTIONS $(condition) : $(options) : unchecked ; + toolset.flags $(toolset).link OPTIONS $(condition) : $(options) : unchecked ; +} + +local rule version-ge ( lhs : rhs ) +{ + lhs = [ regex.split $(lhs) "[.]" ] ; + rhs = [ regex.split $(rhs) "[.]" ] ; + return [ sequence.compare $(rhs) : $(lhs) : numbers.less ] ; +} + +# Version specific flags +rule init-cxxstd-flags ( toolset : condition * : version ) +{ + local cxxstd = [ feature.values ] ; + local dialects = [ feature.values ] ; + dialects = [ set.difference $(dialects) : gnu iso ] ; + local std ; + if [ version-ge $(version) : 3.5 ] { std = 1z ; } + else if [ version-ge $(version) : 3.4 ] { std = 14 ; } + else if [ version-ge $(version) : 3.3 ] { std = 11 ; } + else { std = 03 ; } + cxxstd-flags $(toolset) : $(condition)/latest/iso : -std=c++$(std) ; + cxxstd-flags $(toolset) : $(condition)/latest/gnu : -std=gnu++$(std) ; + cxxstd-flags $(toolset) : $(condition)/latest/$(dialects) : -std=c++$(std) ; +} diff --git a/src/tools/darwin.jam b/src/tools/darwin.jam index 1760a1986..3369ac973 100644 --- a/src/tools/darwin.jam +++ b/src/tools/darwin.jam @@ -156,9 +156,6 @@ rule init ( version ? : command * : options * : requirement * ) flags darwin.compile OPTIONS $(condition)/full : -Wno-inline ; } - # - Set the link flags common with the GCC toolset. - gcc.init-link-flags darwin darwin $(condition) ; - # - The symbol strip program. local strip ; if in $(options) diff --git a/src/tools/gcc.jam b/src/tools/gcc.jam index c0ae6895d..6ba56967e 100644 --- a/src/tools/gcc.jam +++ b/src/tools/gcc.jam @@ -22,6 +22,7 @@ import property ; import property-set ; import rc ; import regex ; +import sequence ; import set ; import toolset ; import type ; @@ -198,8 +199,6 @@ rule init ( version ? : command * : options * : requirement * ) common.handle-options gcc : $(condition) : $(command) : $(options) ; - init-link-flags gcc "" $(condition) ; - # If gcc is installed in a non-standard location, we would need to add # LD_LIBRARY_PATH when running programs created with it (for unit-test/run # rules). @@ -264,6 +263,8 @@ rule init ( version ? : command * : options * : requirement * ) rc.configure $(rc) : $(condition) : $(rc-type) ; toolset.flags gcc VERSION $(condition) : [ regex.split $(version) "[.]" ] ; + + init-cxxstd-flags $(condition) : $(version) ; } if [ os.name ] = NT @@ -292,259 +293,127 @@ rule .get-prog-name ( command-string : tool : flavor ? ) ### Functions that set options on the targets. ### -rule set-fpic-options ( targets * : sources * : properties * ) +local all-os = [ feature.values ] ; + +local rule compile-link-flags ( * ) { - local link = [ feature.get-values link : $(properties) ] ; - if $(link) = shared + toolset.flags gcc.compile OPTIONS $(1) : $(2) ; + toolset.flags gcc.link OPTIONS $(1) : $(2) ; +} + +{ + # This logic will add -fPIC for all compilations: + # + # lib a : a.cpp b ; + # obj b : b.cpp ; + # exe c : c.cpp a d ; + # obj d : d.cpp ; + # + # This all is fine, except that 'd' will be compiled with -fPIC even + # though it is not needed, as 'd' is used only in exe. However, it is + # hard to detect where a target is going to be used. Alternatively, we + # can set -fPIC only when main target type is LIB but than 'b' would be + # compiled without -fPIC which would lead to link errors on x86-64. So, + # compile everything with -fPIC. + # + # Yet another alternative would be to create a propagated + # feature and set it when building shared libraries, but that would be + # hard to implement and would increase the target path length even more. + + # On Windows, fPIC is the default, and specifying -fPIC explicitly leads + # to a warning. + local non-windows = [ set.difference $(all-os) : cygwin windows ] ; + compile-link-flags shared/$(non-windows) : -fPIC ; +} + +{ + # Handle address-model + compile-link-flags aix/32 : -maix32 ; + compile-link-flags aix/64 : -maix64 ; + + compile-link-flags hpux/32 : -milp32 ; + compile-link-flags hpux/64 : -mlp64 ; + + local generic-os = [ set.difference $(all-os) : aix hpux ] ; + local arch = power sparc x86 ; + compile-link-flags $(generic-os)/$(arch)/32 : -m32 ; + compile-link-flags $(generic-os)/$(arch)/64 : -m64 ; +} + +{ + # Handle threading + local rule threading-flags ( * ) { - local target-os = [ feature.get-values target-os : $(properties) ] ; - - # This logic will add -fPIC for all compilations: - # - # lib a : a.cpp b ; - # obj b : b.cpp ; - # exe c : c.cpp a d ; - # obj d : d.cpp ; - # - # This all is fine, except that 'd' will be compiled with -fPIC even - # though it is not needed, as 'd' is used only in exe. However, it is - # hard to detect where a target is going to be used. Alternatively, we - # can set -fPIC only when main target type is LIB but than 'b' would be - # compiled without -fPIC which would lead to link errors on x86-64. So, - # compile everything with -fPIC. - # - # Yet another alternative would be to create a propagated - # feature and set it when building shared libraries, but that would be - # hard to implement and would increase the target path length even more. - - # On Windows, fPIC is the default, and specifying -fPIC explicitly leads - # to a warning. - if ! $(target-os) in cygwin windows + compile-link-flags multi/$(1) : $(2) ; + if $(3) { - OPTIONS on $(targets) += -fPIC ; + toolset.flags gcc.link FINDLIBS-SA multi/$(1) : $(3) ; + } + } + + threading-flags windows : -mthreads ; + threading-flags cygwin : -mthreads ; + threading-flags solaris : -pthreads : rt ; + + local bsd = [ MATCH ^(.*bsd)$ : $(all-os) ] ; + threading-flags $(bsd) : -pthread ; + + local no-threading = android beos haiku sgi darwin vxworks ; + local threading-generic-os = [ set.difference $(all-os) : $(no-threading) $(bsd) windows cygwin solaris ] ; + threading-flags $(threading-generic-os) : -pthread : rt ; +} + +{ + local rule cxxstd-flags ( * ) + { + toolset.flags gcc.compile.c++ OPTIONS $(1) : $(2) ; + toolset.flags gcc.link OPTIONS $(1) : $(2) ; + } + + local cxxstd = [ feature.values ] ; + local dialects = [ feature.values ] ; + .cxxstd-dialects = [ set.difference $(dialects) : gnu iso ] ; + # C++ latest needs to be set up on a per-toolset basis + for local std in [ set.difference $(cxxstd) : latest ] + { + cxxstd-flags $(std)/iso : -std=c++$(std) ; + cxxstd-flags $(std)/gnu : -std=gnu++$(std) ; + # If we see this it's probably a mistake, but + # toolset.flags has no way to set up diagnostics. + cxxstd-flags $(std)/$(.cxxstd-dialects) : -std=c++$(std) ; + } + + local rule version-ge ( lhs : rhs ) + { + lhs = [ regex.split $(lhs) "[.]" ] ; + rhs = [ regex.split $(rhs) "[.]" ] ; + return [ sequence.compare $(rhs) : $(lhs) : numbers.less ] ; + } + # Version specific flags + local rule init-cxxstd-flags ( condition * : version ) + { + local std ; + if [ version-ge $(version) : 8.0 ] { std = 2a ; } + else if [ version-ge $(version) : 5.1 ] { std = 1z ; } + else if [ version-ge $(version) : 4.8 ] { std = 1y ; } + else if [ version-ge $(version) : 4.7 ] { std = 11 ; } + else if [ version-ge $(version) : 3.3 ] { std = 98 ; } + if $(std) + { + cxxstd-flags $(condition)/latest/iso : -std=c++$(std) ; + cxxstd-flags $(condition)/latest/gnu : -std=gnu++$(std) ; + cxxstd-flags $(condition)/latest/$(.cxxstd-dialects) : -std=c++$(std) ; } } } -rule set-address-model-options ( targets * : sources * : properties * ) -{ - local model = [ feature.get-values address-model : $(properties) ] ; - if $(model) - { - local option ; - local target-os = [ feature.get-values target-os : $(properties) ] ; - if $(target-os) = aix - { - if $(model) = 32 - { - option = -maix32 ; - } - else - { - option = -maix64 ; - } - } - else if $(target-os) = hpux - { - if $(model) = 32 - { - option = -milp32 ; - } - else - { - option = -mlp64 ; - } - } - else - { - local arch = [ feature.get-values architecture : $(properties) ] ; - if $(arch) = power || $(arch) = sparc || $(arch) = x86 - { - if $(model) = 32 - { - option = -m32 ; - } - else if $(model) = 64 - { - option = -m64 ; - } - } - # For darwin, the model can be 32_64. darwin.jam will handle that - # on its own. - } - OPTIONS on $(targets) += $(option) ; - } -} +generators.register-c-compiler gcc.compile.c++.preprocess : CPP : PREPROCESSED_CPP : gcc ; +generators.register-c-compiler gcc.compile.c.preprocess : C : PREPROCESSED_C : gcc ; +generators.register-c-compiler gcc.compile.c++ : CPP : OBJ : gcc ; +generators.register-c-compiler gcc.compile.c : C : OBJ : gcc ; +generators.register-c-compiler gcc.compile.asm : ASM : OBJ : gcc ; -rule set-threading-options ( targets * : sources * : properties * ) -{ - local threading = [ feature.get-values threading : $(properties) ] ; - if $(threading) = multi - { - local target-os = [ feature.get-values target-os : $(properties) ] ; - local host-os = [ feature.get-values host-os : $(properties) ] ; - local toolset = [ feature.get-values toolset : $(properties) ] ; - local option ; - local libs ; - - if $(toolset) = clang && $(target-os) = windows - { - option = -pthread ; - } - - switch $(target-os) - { - case android : # No threading options, everything is in already. - case windows : option ?= -mthreads ; - case cygwin : option ?= -mthreads ; - case solaris : option ?= -pthreads ; libs = rt ; - case beos : # No threading options. - case haiku : # No threading options. - case *bsd : option ?= -pthread ; # There is no -lrt on BSD. - case sgi : # gcc on IRIX does not support multi-threading. - case darwin : # No threading options. - case vxworks : # No threading options. - case * : option ?= -pthread ; libs = rt ; - } - if $(option) - { - OPTIONS on $(targets) += $(option) ; - } - if $(libs) - { - FINDLIBS-SA on $(targets) += $(libs) ; - } - } -} - -local rule zero-pad ( numbers * ) -{ - local result ; - for local n in $(numbers) - { - switch $(n) - { - case ???? : result += $(n) ; - case ??? : result += 0$(n) ; - case ?? : result += 00$(n) ; - case ? : result += 000$(n) ; - } - } - return $(result) ; -} - -rule set-cxxstd-options ( targets * : sources * : properties * : action ) -{ - local *targets = [ $(action).targets ] ; - local *sources = [ $(action).sources ] ; - local target-type = [ $(*targets[1]).type ] ; - local source-type = [ $(*sources[1]).type ] ; - local toolset = [ feature.get-values toolset : $(properties) ] ; - local version = [ zero-pad [ on $(targets[1]) return $(VERSION) ] ] ; - version = $(version[1]).$(version[2]) ; - local cxxstd = [ feature.get-values cxxstd : $(properties) ] ; - local cxxstd-dialect = [ feature.get-values cxxstd-dialect : $(properties) ] ; - cxxstd-dialect ?= iso ; - switch $(cxxstd-dialect) - { - case gnu : cxxstd-dialect = gnu++ ; - case iso : cxxstd-dialect = c++ ; - case * : - errors.warning Unknown cxxstd-dialect $(cxxstd-dialect:E=?) .. using - ISO dialect instead. ; - cxxstd-dialect = c++ ; - } - local option ; - if $(cxxstd) = latest - { - if $(toolset) = gcc - { - if $(version) >= 0008.0000 { option = 2a ; } - else if $(version) >= 0005.0001 { option = 1z ; } - else if $(version) >= 0004.0008 { option = 1y ; } - else if $(version) >= 0004.0007 { option = 11 ; } - else if $(version) >= 0003.0003 { option = 98 ; } - } - if $(toolset) = clang - { - if $(version) >= 0003.0005 { option = 1z ; } - if $(version) >= 0003.0004 { option = 14 ; } - if $(version) >= 0003.0003 { option = 11 ; } - option ?= 03 ; - } - } - else - { - option = $(cxxstd) ; - } - if $(source-type) in CPP || $(target-type) in CPP_PCH EXE SHARED_LIB - { - OPTIONS on $(targets) += -std=$(cxxstd-dialect)$(option) ; - } -} - -### -### Compiling generators and actions. -### - -class gcc-c-compiling-generator : C-compiling-generator -{ - rule action-class ( ) - { - return gcc-c-compile-action ; - } -} - -class gcc-c-compile-action : compile-action -{ - import gcc ; - - rule execute ( action-name targets + : sources * : properties * ) - { - gcc.set-threading-options $(targets) : $(sources) : $(properties) ; - gcc.set-fpic-options $(targets) : $(sources) : $(properties) ; - gcc.set-address-model-options $(targets) : $(sources) : $(properties) ; - gcc.set-cxxstd-options $(targets) : $(sources) : $(properties) : $(__name__) ; - compile-action.execute $(action-name) $(targets) : $(sources) : $(properties) ; - } -} - -local rule register-gcc-c-compiler ( id : source-types + : target-types + : requirements * - : optional-properties * ) -{ - generators.register [ new gcc-c-compiling-generator $(id) : $(source-types) : - $(target-types) : $(requirements) : $(optional-properties) ] ; -} - -register-gcc-c-compiler gcc.compile.c++.preprocess : CPP : PREPROCESSED_CPP : gcc ; -register-gcc-c-compiler gcc.compile.c.preprocess : C : PREPROCESSED_C : gcc ; -register-gcc-c-compiler gcc.compile.c++ : CPP : OBJ : gcc ; -register-gcc-c-compiler gcc.compile.c : C : OBJ : gcc ; -register-gcc-c-compiler gcc.compile.asm : ASM : OBJ : gcc ; - -class gcc-fortran-compiling-generator : fortran-compiling-generator -{ - rule action-class ( ) - { - return gcc-fortran-compile-action ; - } -} - -class gcc-fortran-compile-action : compile-action -{ - import gcc ; - - rule execute ( action-name targets + : sources * : properties * ) - { - gcc.set-threading-options $(targets) : $(sources) : $(properties) ; - gcc.set-fpic-options $(targets) : $(sources) : $(properties) ; - gcc.set-address-model-options $(targets) : $(sources) : $(properties) ; - gcc.set-cxxstd-options $(targets) : $(sources) : $(properties) : $(__name__) ; - compile-action.execute $(action-name) $(targets) : $(sources) : $(properties) ; - } -} - -generators.register [ new gcc-fortran-compiling-generator +generators.register [ new fortran-compiling-generator gcc.compile.fortran : FORTRAN FORTRAN90 : OBJ : gcc ] ; rule compile.c++.preprocess ( targets * : sources * : properties * ) @@ -695,25 +564,6 @@ class gcc-pch-generator : pch-generator return [ generator.generated-targets $(sources) : $(property-set) : $(project) $(name) ] ; } - - rule action-class ( ) - { - return gcc-pch-compile-action ; - } -} - -class gcc-pch-compile-action : compile-action -{ - import gcc ; - - rule execute ( action-name targets + : sources * : properties * ) - { - gcc.set-threading-options $(targets) : $(sources) : $(properties) ; - gcc.set-fpic-options $(targets) : $(sources) : $(properties) ; - gcc.set-address-model-options $(targets) : $(sources) : $(properties) ; - gcc.set-cxxstd-options $(targets) : $(sources) : $(properties) : $(__name__) ; - compile-action.execute $(action-name) $(targets) : $(sources) : $(properties) ; - } } # Note: the 'H' source type will catch both '.h' header and '.hpp' header. The @@ -835,26 +685,6 @@ class gcc-linking-generator : unix-linking-generator $(property-set) : $(sources) ] ; } } - - rule action-class ( ) - { - return gcc-link-action ; - } -} - -class gcc-link-action : action -{ - import gcc ; - - rule execute ( action-name targets + : sources * : properties * ) - { - gcc.set-threading-options $(targets) : $(sources) : $(properties) ; - gcc.set-fpic-options $(targets) : $(sources) : $(properties) ; - gcc.set-address-model-options $(targets) : $(sources) : $(properties) ; - gcc.set-cxxstd-options $(targets) : $(sources) : $(properties) : $(__name__) ; - gcc.set-link-options $(action-name) $(targets) : $(sources) : $(properties) ; - action.execute $(action-name) $(targets) : $(sources) : $(properties) ; - } } # The set of permissible input types is different on mingw. So, define two sets @@ -923,231 +753,163 @@ toolset.flags gcc.link LIBRARIES ; toolset.flags gcc.link.dll .IMPLIB-COMMAND windows : "-Wl,--out-implib," ; toolset.flags gcc.link.dll .IMPLIB-COMMAND cygwin : "-Wl,--out-implib," ; -# Now, the vendor specific flags. -# The parameter linker can be either aix, darwin, gnu, hpux, osf or sun. -rule init-link-flags ( toolset subtool condition ) +# target specific link flags { - ## Need to define the linker-type feature once for each toolset module. - if ! [ feature.valid ] - { - feature.subfeature toolset $(toolset) : linker-type : - gnu aix darwin hpux osf sun : propagated link-incompatible ; - } - condition = [ regex.replace $(condition) "/" "," ] ; - ## The specification to add the linker-type is per toolset "instance". - toolset.add-requirements - $(condition),aix:aix - $(condition),darwin:darwin - $(condition),hpux:hpux - $(condition),osf:osf - $(condition),solaris:sun - ; -} + # aix -rule set-link-options ( action-name targets + : sources * : properties * ) -{ - local toolset = [ feature.get-values : $(properties) ] ; - local linker-type = [ feature.get-values : $(properties) ] ; - local target-os = [ feature.get-values : $(properties) ] ; + # On AIX we *have* to use the native linker. + # + # Using -brtl, the AIX linker will look for libraries with both the .a + # and .so extensions, such as libfoo.a and libfoo.so. Without -brtl, the + # AIX linker looks only for libfoo.a. Note that libfoo.a is an archived + # file that may contain shared objects and is different from static libs + # as on Linux. + # + # The -bnoipath strips the prepending (relative) path of libraries from + # the loader section in the target library or executable. Hence, during + # load-time LIBPATH (identical to LD_LIBRARY_PATH) or a hard-coded + # -blibpath (*similar* to -lrpath/-lrpath-link) is searched. Without + # this option, the prepending (relative) path + library name is + # hard-coded in the loader section, causing *only* this path to be + # searched during load-time. Note that the AIX linker does not have an + # -soname equivalent, this is as close as it gets. + # + # The -bbigtoc option instrcuts the linker to create a TOC bigger than 64k. + # This is neccesary for some submodules such as math, but it does make running + # the tests a tad slower. + # + # The above options are definately for AIX 5.x, and most likely also for + # AIX 4.x and AIX 6.x. For details about the AIX linker see: + # http://download.boulder.ibm.com/ibmdl/pub/software/dw/aix/es-aix_ll.pdf + # + toolset.flags gcc.link OPTIONS aix : -Wl,-brtl -Wl,-bnoipath -Wl,-bbigtoc ; - switch $(linker-type:G=) - { - case aix : + # See note [1] + toolset.flags gcc.link OPTIONS aix/static : -static ; - # On AIX we *have* to use the native linker. - # - # Using -brtl, the AIX linker will look for libraries with both the .a - # and .so extensions, such as libfoo.a and libfoo.so. Without -brtl, the - # AIX linker looks only for libfoo.a. Note that libfoo.a is an archived - # file that may contain shared objects and is different from static libs - # as on Linux. - # - # The -bnoipath strips the prepending (relative) path of libraries from - # the loader section in the target library or executable. Hence, during - # load-time LIBPATH (identical to LD_LIBRARY_PATH) or a hard-coded - # -blibpath (*similar* to -lrpath/-lrpath-link) is searched. Without - # this option, the prepending (relative) path + library name is - # hard-coded in the loader section, causing *only* this path to be - # searched during load-time. Note that the AIX linker does not have an - # -soname equivalent, this is as close as it gets. - # - # The -bbigtoc option instrcuts the linker to create a TOC bigger than 64k. - # This is neccesary for some submodules such as math, but it does make running - # the tests a tad slower. - # - # The above options are definately for AIX 5.x, and most likely also for - # AIX 4.x and AIX 6.x. For details about the AIX linker see: - # http://download.boulder.ibm.com/ibmdl/pub/software/dw/aix/es-aix_ll.pdf - # + # darwin - OPTIONS on $(targets) += -Wl,-brtl -Wl,-bnoipath -Wl,-bbigtoc ; + # On Darwin, the -s option to ld does not work unless we pass -static, + # and passing -static unconditionally is a bad idea. So, do not pass -s + # at all and darwin.jam will use a separate 'strip' invocation. + toolset.flags gcc.link RPATH darwin : ; + # This does not support -R. + toolset.flags gcc.link RPATH_OPTION darwin : -rpath ; + # -rpath-link is not supported at all. - # See note [1] - if static in $(properties) - { - OPTIONS on $(targets) += -static ; - } - - case darwin : - - # On Darwin, the -s option to ld does not work unless we pass -static, - # and passing -static unconditionally is a bad idea. So, do not pass -s - # at all and darwin.jam will use a separate 'strip' invocation. - RPATH on $(targets) += - [ feature.get-values : $(properties) ] ; - # This does not support -R. - RPATH_OPTION on $(targets) += -rpath ; - # -rpath-link is not supported at all. - - # See note [1] - if static in $(properties) - { - OPTIONS on $(targets) += -static ; - } + # See note [1] + toolset.flags gcc.link OPTIONS darwin/static : -static ; - case vxworks : - # On VxWorks we want to reflect what ever special flags have been set in the - # environment for the CPU we are targeting in the cross build - toolset.flags $(toolset).link OPTIONS $(condition)/on : -Wl,--strip-all : unchecked ; - toolset.flags $(toolset).link OPTIONS $(condition)/static : [ os.environ LDFLAGS_STATIC ] : unchecked ; - toolset.flags $(toolset).link.dll OPTIONS $(condition) : [ os.environ LDFLAGS_SO ] : unchecked ; - toolset.flags $(toolset).link OPTIONS $(condition)/shared : [ os.environ LDFLAGS_DYNAMIC ] : unchecked ; + # vxworks + # On VxWorks we want to reflect what ever special flags have been set in the + # environment for the CPU we are targeting in the cross build + toolset.flags gcc.link OPTIONS vxworks/on : -Wl,--strip-all ; + toolset.flags gcc.link OPTIONS vxworks/static : [ os.environ LDFLAGS_STATIC ] ; + toolset.flags gcc.link.dll OPTIONS vxworks : [ os.environ LDFLAGS_SO ] ; + toolset.flags gcc.link OPTIONS vxworks/shared : [ os.environ LDFLAGS_DYNAMIC ] ; - case gnu : + # default - # Strip the binary when no debugging is needed. We use --strip-all flag - # as opposed to -s since icc (intel's compiler) is generally - # option-compatible with and inherits from the gcc toolset, but does not - # support -s. - if on in $(properties) - { - OPTIONS on $(targets) += -Wl,--strip-all ; - } - RPATH on $(targets) += - [ feature.get-values : $(properties) ] ; - RPATH_OPTION on $(targets) += -rpath ; - RPATH_LINK on $(targets) += - [ feature.get-values : $(properties) ] ; - START-GROUP on $(targets) += -Wl,--start-group ; - END-GROUP on $(targets) += -Wl,--end-group ; + local generic-os = [ set.difference $(all-os) : aix darwin vxworks solaris osf hpux ] ; + # Strip the binary when no debugging is needed. We use --strip-all flag + # as opposed to -s since icc (intel's compiler) is generally + # option-compatible with and inherits from the gcc toolset, but does not + # support -s. + toolset.flags gcc.link OPTIONS $(generic-os)/on : + -Wl,--strip-all ; + toolset.flags gcc.link RPATH $(generic-os) : ; + toolset.flags gcc.link RPATH_OPTION $(generic-os) : -rpath ; + toolset.flags gcc.link RPATH_LINK $(generic-os) : ; + toolset.flags gcc.link START-GROUP $(generic-os) : + -Wl,--start-group ; + toolset.flags gcc.link END-GROUP $(generic-os) : -Wl,--end-group ; - # gnu ld has the ability to change the search behaviour for libraries - # referenced by the -l switch. These modifiers are -Bstatic and - # -Bdynamic and change search for -l switches that follow them. The - # following list shows the tried variants. Search stops at the first - # variant that has a match. - # - # *nix: -Bstatic -lxxx - # libxxx.a - # - # *nix: -Bdynamic -lxxx - # libxxx.so - # libxxx.a - # - # windows (mingw, cygwin) -Bstatic -lxxx - # libxxx.a - # xxx.lib - # - # windows (mingw, cygwin) -Bdynamic -lxxx - # libxxx.dll.a - # xxx.dll.a - # libxxx.a - # xxx.lib - # cygxxx.dll (*) - # libxxx.dll - # xxx.dll - # libxxx.a - # - # (*) This is for cygwin - # Please note that -Bstatic and -Bdynamic are not a guarantee that a - # static or dynamic lib indeed gets linked in. The switches only change - # search patterns! + # gnu ld has the ability to change the search behaviour for libraries + # referenced by the -l switch. These modifiers are -Bstatic and + # -Bdynamic and change search for -l switches that follow them. The + # following list shows the tried variants. Search stops at the first + # variant that has a match. + # + # *nix: -Bstatic -lxxx + # libxxx.a + # + # *nix: -Bdynamic -lxxx + # libxxx.so + # libxxx.a + # + # windows (mingw, cygwin) -Bstatic -lxxx + # libxxx.a + # xxx.lib + # + # windows (mingw, cygwin) -Bdynamic -lxxx + # libxxx.dll.a + # xxx.dll.a + # libxxx.a + # xxx.lib + # cygxxx.dll (*) + # libxxx.dll + # xxx.dll + # libxxx.a + # + # (*) This is for cygwin + # Please note that -Bstatic and -Bdynamic are not a guarantee that a + # static or dynamic lib indeed gets linked in. The switches only change + # search patterns! - # On *nix mixing shared libs with static runtime is not a good idea. - if shared in $(properties) - { - FINDLIBS-ST-PFX on $(targets) += -Wl,-Bstatic ; - FINDLIBS-SA-PFX on $(targets) += -Wl,-Bdynamic ; - } + # On *nix mixing shared libs with static runtime is not a good idea. + toolset.flags gcc.link FINDLIBS-ST-PFX $(generic-os)/shared : -Wl,-Bstatic ; + toolset.flags gcc.link FINDLIBS-SA-PFX $(generic-os)/shared : -Wl,-Bdynamic ; - # On windows allow mixing of static and dynamic libs with static - # runtime is not a good idea. - if static in $(properties) && windows in $(properties) - { - FINDLIBS-ST-PFX on $(targets) += -Wl,-Bstatic ; - FINDLIBS-SA-PFX on $(targets) += -Wl,-Bdynamic ; - OPTIONS on $(targets) += -Wl,-Bstatic ; - } + # On windows allow mixing of static and dynamic libs with static + # runtime is not a good idea. + toolset.flags gcc.link FINDLIBS-ST-PFX windows/static : -Wl,-Bstatic ; + toolset.flags gcc.link FINDLIBS-SA-PFX windows/static : -Wl,-Bdynamic ; + toolset.flags gcc.link OPTIONS windows/static : -Wl,-Bstatic ; - HAVE_SONAME on $(targets) += "" ; - SONAME_OPTION on $(targets) += -h ; + toolset.flags gcc.link HAVE_SONAME $(generic-os) : "" ; + toolset.flags gcc.link SONAME_OPTION $(generic-os) : -h ; - # See note [1] - if static in $(properties) - { - OPTIONS on $(targets) += -static ; - } + # See note [1] + toolset.flags gcc.link OPTIONS $(generic-os)/static : -static ; - case hpux : + # hpux - if on in $(properties) - { - OPTIONS on $(targets) += -Wl,-s ; - } - if shared in $(properties) - { - OPTIONS on $(targets) += -fPIC ; - } + toolset.flags gcc.link OPTIONS hpux/on : -Wl,-s ; - HAVE_SONAME on $(targets) += "" ; - SONAME_OPTION on $(targets) += +h ; + toolset.flags gcc.link HAVE_SONAME hpux : "" ; + toolset.flags gcc.link SONAME_OPTION hpux : +h ; - case osf : + # osf - # No --strip-all, just -s. - OPTIONS - osf/$(condition)/on - : -Wl,-s - : unchecked ; - RPATH on $(targets) += [ feature.get-values ] ; - # This does not support -R. - RPATH_OPTION on $(targets) += -rpath ; - # -rpath-link is not supported at all. + # No --strip-all, just -s. + toolset.flags gcc.link OPTIONS osf/on : -Wl,-s ; + toolset.flags gcc.link RPATH osf : ; + # This does not support -R. + toolset.flags gcc.link RPATH_OPTION osf : -rpath ; + # -rpath-link is not supported at all. - # See note [1] - if static in $(properties) - { - OPTIONS on $(targets) += -static ; - } + # See note [1] + toolset.flags gcc.link OPTIONS osf/static : -static ; - case sun : + # sun - if on in $(properties) - { - OPTIONS on $(targets) += -Wl,-s ; - } - RPATH on $(targets) += [ feature.get-values ] ; - # Solaris linker does not have a separate -rpath-link, but allows using - # -L for the same purpose. - LINKPATH on $(targets) += [ feature.get-values ] ; + toolset.flags gcc.link OPTIONS solaris/on : -Wl,-s ; - # This permits shared libraries with non-PIC code on Solaris. - # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the - # following is not needed. Whether -fPIC should be hardcoded, is a - # separate question. - # AH, 2004/10/16: it is still necessary because some tests link against - # static libraries that were compiled without PIC. - if shared in $(properties) - { - OPTIONS on $(targets) += -mimpure-text ; - } + toolset.flags gcc.link RPATH solaris : ; + # Solaris linker does not have a separate -rpath-link, but allows using + # -L for the same purpose. + toolset.flags gcc.link LINKPATH solaris : ; - # See note [1] - if static in $(properties) - { - OPTIONS on $(targets) += -static ; - } - } + # This permits shared libraries with non-PIC code on Solaris. + # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the + # following is not needed. Whether -fPIC should be hardcoded, is a + # separate question. + # AH, 2004/10/16: it is still necessary because some tests link against + # static libraries that were compiled without PIC. + toolset.flags gcc.link OPTIONS solaris : -mimpure-text ; + + # See note [1] + toolset.flags gcc.link OPTIONS solaris/static : -static ; # [1] # For static we made sure there are no dynamic libraries in the diff --git a/src/tools/intel-darwin.jam b/src/tools/intel-darwin.jam index 02f25d1bc..096224a6f 100644 --- a/src/tools/intel-darwin.jam +++ b/src/tools/intel-darwin.jam @@ -55,8 +55,6 @@ rule init ( version ? : command * : options * ) common.handle-options intel-darwin : $(condition) : $(command) : $(options) ; - gcc.init-link-flags intel darwin $(condition) ; - # handle # local library-path = [ feature.get-values : $(options) ] ; # flags intel-darwin.link USER_OPTIONS $(condition) : [ feature.get-values : $(options) ] ; diff --git a/src/tools/intel-linux.jam b/src/tools/intel-linux.jam index c743e52d2..a8b23459f 100644 --- a/src/tools/intel-linux.jam +++ b/src/tools/intel-linux.jam @@ -96,8 +96,6 @@ rule init ( version ? : command * : options * ) : $(command) : $(default_path) ] ; common.handle-options intel-linux : $(condition) : $(command) : $(options) ; - - gcc.init-link-flags intel-linux gnu $(condition) ; local root = [ feature.get-values : $(options) ] ; local bin ; diff --git a/src/tools/intel-vxworks.jam b/src/tools/intel-vxworks.jam index 8d9a3e3a0..4026ba734 100644 --- a/src/tools/intel-vxworks.jam +++ b/src/tools/intel-vxworks.jam @@ -54,8 +54,6 @@ rule init ( version ? : command * : options * ) common.handle-options intel-vxworks : $(condition) : $(command) : $(options) ; - gcc.init-link-flags intel-vxworks vxworks $(condition) ; - # handle # local library-path = [ feature.get-values : $(options) ] ; # flags intel-vxworks.link USER_OPTIONS $(condition) : [ feature.get-values : $(options) ] ; diff --git a/src/tools/pgi.jam b/src/tools/pgi.jam index 0ea025e7a..8b13d451b 100644 --- a/src/tools/pgi.jam +++ b/src/tools/pgi.jam @@ -40,8 +40,6 @@ rule init ( version ? : command * : options * ) # set link flags flags pgi.link FINDLIBS-ST : [ feature.get-values : $(options) ] : unchecked ; - - gcc.init-link-flags pgi gnu $(condition) ; } # Declare generators diff --git a/src/util/sequence.jam b/src/util/sequence.jam index 97ddfe153..ddfd069c7 100644 --- a/src/util/sequence.jam +++ b/src/util/sequence.jam @@ -156,6 +156,42 @@ rule merge ( s1 * : s2 * : ordered * ) return $(result__) ; } +# Compares two sequences lexicagraphically +# +rule compare ( s1 * : s2 * : ordered * ) +{ + if ! $(ordered) + { + if $(s1) < $(s2) + { + return true ; + } + } + else + { + while true + { + if ! $(s2[1])-is-defined + { + return ; + } + else if ! $(s1[1])-is-defined + { + return true ; + } + else if [ $(ordered) $(s1[1]) $(s2[1]) ] + { + return true ; + } + else if [ $(ordered) $(s2[1]) $(s1[1]) ] + { + return ; + } + s1 = $(s1[2-]) ; + s2 = $(s2[2-]) ; + } + } +} # Join the elements of s into one long string. If joint is supplied, it is used # as a separator. diff --git a/test/TestToolset.py b/test/TestToolset.py index ca6e96956..98bc7c82b 100644 --- a/test/TestToolset.py +++ b/test/TestToolset.py @@ -70,6 +70,8 @@ def compute_path(properties): path += "/address-model-" + get_property("address-model", properties) if has_property("architecture", properties): path += "/architecture-" + get_property("architecture", properties) + if "cxxstd=latest" in properties: + path += "/cxxstd-latest-iso" if "link=static" in properties: path += "/link-static" if "runtime-link=static" in properties: diff --git a/test/toolset-mock/src/clang-3.9.0-darwin.py b/test/toolset-mock/src/clang-3.9.0-darwin.py index 15a2bfc8c..d21aad8fa 100644 --- a/test/toolset-mock/src/clang-3.9.0-darwin.py +++ b/test/toolset-mock/src/clang-3.9.0-darwin.py @@ -13,10 +13,10 @@ command('clang++', '-print-prog-name=ranlib', stdout=script('ranlib.py')) # all builds are multi-threaded for darwin if allow_properties("variant=debug", "link=shared", "runtime-link=shared"): - command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-fPIC', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/lib.o'), input_file(source='lib.cpp')) - command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', '@rpath/libl1.dylib', input_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/lib.o'), '-g', '-fPIC') - command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-fPIC', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/main.o'), input_file(source='main.cpp')) - command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/test'), input_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/main.o'), input_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/libl1.dylib'), '-g', '-fPIC') + command('clang++', '-x', 'c++', unordered('-O0', '-fno-inline', '-Wall', '-g', '-fPIC'), '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', '@rpath/libl1.dylib', input_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/lib.o'), unordered('-g', '-fPIC')) + command('clang++', '-x', 'c++', unordered('-O0', '-fno-inline', '-Wall', '-g', '-fPIC'), '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/test'), input_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/main.o'), input_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/libl1.dylib'), unordered('-g', '-fPIC')) if allow_properties("variant=release", "link=shared", "runtime-link=shared"): command('clang++', '-x', 'c++', unordered('-O3', '-Wno-inline', '-Wall', '-fPIC'), '-DNDEBUG', '-c', '-o', output_file('bin/clang-darwin-3.9.0/release/target-os-darwin/lib.o'), input_file(source='lib.cpp')) @@ -25,19 +25,25 @@ if allow_properties("variant=release", "link=shared", "runtime-link=shared"): command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/release/target-os-darwin/test'), input_file('bin/clang-darwin-3.9.0/release/target-os-darwin/main.o'), input_file('bin/clang-darwin-3.9.0/release/target-os-darwin/libl1.dylib'), '-fPIC') if allow_properties("variant=debug", "link=static", "runtime-link=shared"): - command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) - command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('clang++', '-x', 'c++', unordered('-O0', '-fno-inline', '-Wall', '-g'), '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('clang++', '-x', 'c++', unordered('-O0', '-fno-inline', '-Wall', '-g'), '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/link-static/target-os-darwin/test'), input_file('bin/clang-darwin-3.9.0/debug/link-static/target-os-darwin/main.o'), input_file('bin/clang-darwin-3.9.0/debug/link-static/target-os-darwin/libl1.a'), '-g') if allow_properties("variant=debug", "link=static", "runtime-link=static"): - command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) - command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) - command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/test'), input_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), '-g', '-static') + command('clang++', '-x', 'c++', unordered('-O0', '-fno-inline', '-Wall', '-g'), '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('clang++', '-x', 'c++', unordered('-O0', '-fno-inline', '-Wall', '-g'), '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/test'), input_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file('bin/clang-darwin-3.9.0/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), unordered('-g', '-static')) if allow_properties("variant=debug", "link=shared", "runtime-link=shared", "architecture=x86", "address-model=32"): - command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-march=i686', '-fPIC', '-m32', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/lib.o'), input_file(source='lib.cpp')) - command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', '@rpath/libl1.dylib', input_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/lib.o'), '-g', '-march=i686', '-fPIC', '-m32') - command('clang++', '-x', 'c++', '-O0', '-fno-inline', '-Wall', '-g', '-march=i686', '-fPIC', '-m32', '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/main.o'), input_file(source='main.cpp')) - command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/test'), input_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/main.o'), input_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/libl1.dylib'), '-g', '-march=i686', '-fPIC', '-m32') - + command('clang++', '-x', 'c++', unordered('-O0', '-fno-inline', '-Wall', '-g', '-march=i686', '-fPIC', '-m32'), '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', '@rpath/libl1.dylib', input_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/lib.o'), unordered('-g', '-march=i686', '-fPIC', '-m32')) + command('clang++', '-x', 'c++', unordered('-O0', '-fno-inline', '-Wall', '-g', '-march=i686', '-fPIC', '-m32'), '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/test'), input_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/main.o'), input_file('bin/clang-darwin-3.9.0/debug/x86/target-os-darwin/libl1.dylib'), unordered('-g', '-march=i686', '-fPIC', '-m32')) + +if allow_properties("variant=debug", "link=shared", "runtime-link=shared", "cxxstd=latest"): + command('clang++', '-x', 'c++', unordered('-O0', '-fno-inline', '-Wall', '-g', '-fPIC', '-std=c++1z'), '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', '@rpath/libl1.dylib', input_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/lib.o'), unordered('-g', '-fPIC', '-std=c++1z')) + command('clang++', '-x', 'c++', unordered('-O0', '-fno-inline', '-Wall', '-g', '-fPIC', '-std=c++1z'), '-c', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('clang++', '-o', output_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/test'), input_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/main.o'), input_file('bin/clang-darwin-3.9.0/debug/target-os-darwin/libl1.dylib'), unordered('-g', '-fPIC', '-std=c++1z')) + main() diff --git a/test/toolset-mock/src/clang-linux-3.9.0.py b/test/toolset-mock/src/clang-linux-3.9.0.py index 988dbdb3d..242d25624 100644 --- a/test/toolset-mock/src/clang-linux-3.9.0.py +++ b/test/toolset-mock/src/clang-linux-3.9.0.py @@ -13,21 +13,21 @@ command('clang++', '-print-prog-name=ranlib', stdout=script('ranlib.py')) if allow_properties('variant=debug', 'link=shared', 'threading=single', 'runtime-link=shared'): command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-fPIC', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/lib.o'), input_file(source='lib.cpp')) - command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/libl1.so'), '-Wl,-soname', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-g', '-fPIC') + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/libl1.so'), '-Wl,-soname', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-g', '-fPIC')) command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-fPIC', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/main.o'), input_file(source='main.cpp')) - command('clang++', '-Wl,-R', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/libl1.so')), '-o', output_file('bin/clang-linux-3.9.0/debug/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/main.o'), input_file('bin/clang-linux-3.9.0/debug/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-g', '-fPIC') + command('clang++', '-Wl,-R', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/libl1.so')), '-o', output_file('bin/clang-linux-3.9.0/debug/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/main.o'), input_file('bin/clang-linux-3.9.0/debug/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-g', '-fPIC')) if allow_properties('variant=release', 'link=shared', 'threading=single', 'runtime-link=shared', 'strip=on'): command('clang++', unordered(ordered('-x', 'c++'), '-O3', '-Wno-inline', '-Wall', '-fPIC', '-DNDEBUG', '-c'), '-o', output_file('bin/clang-linux-3.9.0/release/lib.o'), input_file(source='lib.cpp')) - command('clang++', '-o', output_file('bin/clang-linux-3.9.0/release/libl1.so'), '-Wl,-soname', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/release/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-fPIC', '-Wl,--strip-all') + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/release/libl1.so'), '-Wl,-soname', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/release/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-fPIC', '-Wl,--strip-all')) command('clang++', unordered(ordered('-x', 'c++'), '-O3', '-Wno-inline', '-Wall', '-fPIC', '-DNDEBUG', '-c'), '-o', output_file('bin/clang-linux-3.9.0/release/main.o'), input_file(source='main.cpp')) - command('clang++', '-Wl,-R', arg('-Wl,', target_path('bin/clang-linux-3.9.0/release/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/clang-linux-3.9.0/release/libl1.so')), '-o', output_file('bin/clang-linux-3.9.0/release/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/release/main.o'), input_file('bin/clang-linux-3.9.0/release/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-fPIC', '-Wl,--strip-all') + command('clang++', '-Wl,-R', arg('-Wl,', target_path('bin/clang-linux-3.9.0/release/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/clang-linux-3.9.0/release/libl1.so')), '-o', output_file('bin/clang-linux-3.9.0/release/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/release/main.o'), input_file('bin/clang-linux-3.9.0/release/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-fPIC', '-Wl,--strip-all')) if allow_properties('variant=debug', 'link=shared', 'threading=multi', 'runtime-link=shared'): command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-pthread', '-fPIC', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/threading-multi/lib.o'), input_file(source='lib.cpp')) - command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/threading-multi/libl1.so'), '-Wl,-soname', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/threading-multi/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-lrt', '-Wl,--end-group', '-g', '-pthread', '-fPIC') + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/threading-multi/libl1.so'), '-Wl,-soname', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/threading-multi/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-lrt', '-Wl,--end-group', unordered('-g', '-pthread', '-fPIC')) command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-pthread', '-fPIC', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/threading-multi/main.o'), input_file(source='main.cpp')) - command('clang++', '-Wl,-R', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/threading-multi/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/threading-multi/libl1.so')), '-o', output_file('bin/clang-linux-3.9.0/debug/threading-multi/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/threading-multi/main.o'), input_file('bin/clang-linux-3.9.0/debug/threading-multi/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-lrt', '-Wl,--end-group', '-g', '-pthread', '-fPIC') + command('clang++', '-Wl,-R', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/threading-multi/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/threading-multi/libl1.so')), '-o', output_file('bin/clang-linux-3.9.0/debug/threading-multi/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/threading-multi/main.o'), input_file('bin/clang-linux-3.9.0/debug/threading-multi/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-lrt', '-Wl,--end-group', unordered('-g', '-pthread', '-fPIC')) if allow_properties('variant=debug', 'link=static', 'threading=single', 'runtime-link=shared'): command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/lib.o'), input_file(source='lib.cpp')) @@ -37,12 +37,12 @@ if allow_properties('variant=debug', 'link=static', 'threading=single', 'runtime if allow_properties('variant=debug', 'link=static', 'threading=single', 'runtime-link=static'): command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/lib.o'), input_file(source='lib.cpp')) command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/main.o'), input_file(source='main.cpp')) - command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/main.o'), input_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/libl1.a'), '-Wl,--end-group', '-g', '-static') + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/main.o'), input_file('bin/clang-linux-3.9.0/debug/link-static/runtime-link-static/libl1.a'), '-Wl,--end-group', unordered('-g', '-static')) if allow_properties('variant=debug', 'link=shared', 'threading=single', 'runtime-link=shared', 'architecture=x86', 'address-model=32'): command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-march=i686', '-m32', '-fPIC', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/lib.o'), input_file(source='lib.cpp')) - command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/libl1.so'), '-Wl,-soname', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-g', '-march=i686', '-fPIC', '-m32') + command('clang++', '-o', output_file('bin/clang-linux-3.9.0/debug/libl1.so'), '-Wl,-soname', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-g', '-march=i686', '-fPIC', '-m32')) command('clang++', unordered(ordered('-x', 'c++'), '-O0', '-fno-inline', '-Wall', '-g', '-march=i686', '-m32', '-fPIC', '-c'), '-o', output_file('bin/clang-linux-3.9.0/debug/main.o'), input_file(source='main.cpp')) - command('clang++', '-Wl,-R', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/libl1.so')), '-o', output_file('bin/clang-linux-3.9.0/debug/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/main.o'), input_file('bin/clang-linux-3.9.0/debug/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-g', '-march=i686', '-fPIC', '-m32') + command('clang++', '-Wl,-R', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/clang-linux-3.9.0/debug/libl1.so')), '-o', output_file('bin/clang-linux-3.9.0/debug/test'), '-Wl,--start-group', input_file('bin/clang-linux-3.9.0/debug/main.o'), input_file('bin/clang-linux-3.9.0/debug/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', unordered('-g', '-march=i686', '-fPIC', '-m32')) main() diff --git a/test/toolset-mock/src/darwin-4.2.1.py b/test/toolset-mock/src/darwin-4.2.1.py index a29fff9d1..d81359ca5 100644 --- a/test/toolset-mock/src/darwin-4.2.1.py +++ b/test/toolset-mock/src/darwin-4.2.1.py @@ -14,25 +14,25 @@ command('g++', '-dumpversion', stdout='4.2.1') # all builds are multi-threaded for darwin if allow_properties("variant=debug", "link=shared", "runtime-link=shared"): - command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-dynamic', '-gdwarf-2', '-fexceptions', '-fPIC', '-c', '-o', output_file('bin/darwin-4.2.1/debug/target-os-darwin/lib.o'), input_file(source='lib.cpp')) - command('g++', '-dynamiclib', '-Wl,-single_module', '-install_name', 'libl1.dylib', '-o', output_file('bin/darwin-4.2.1/debug/target-os-darwin/libl1.dylib'), input_file('bin/darwin-4.2.1/debug/target-os-darwin/lib.o'), '-headerpad_max_install_names', '-g', '-fPIC') - command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-dynamic', '-gdwarf-2', '-fexceptions', '-fPIC', '-c', '-o', output_file('bin/darwin-4.2.1/debug/target-os-darwin/main.o'), input_file(source='main.cpp')) - command('g++', '-o', output_file('bin/darwin-4.2.1/debug/target-os-darwin/test'), input_file('bin/darwin-4.2.1/debug/target-os-darwin/main.o'), input_file('bin/darwin-4.2.1/debug/target-os-darwin/libl1.dylib'), '-g', '-fPIC') + command('g++', unordered('-O0', '-fno-inline', '-Wall', '-g', '-dynamic', '-gdwarf-2', '-fexceptions', '-fPIC'), '-c', '-o', output_file('bin/darwin-4.2.1/debug/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('g++', '-dynamiclib', '-Wl,-single_module', '-install_name', 'libl1.dylib', '-o', output_file('bin/darwin-4.2.1/debug/target-os-darwin/libl1.dylib'), input_file('bin/darwin-4.2.1/debug/target-os-darwin/lib.o'), '-headerpad_max_install_names', unordered('-g', '-fPIC')) + command('g++', unordered('-O0', '-fno-inline', '-Wall', '-g', '-dynamic', '-gdwarf-2', '-fexceptions', '-fPIC'), '-c', '-o', output_file('bin/darwin-4.2.1/debug/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('g++', '-o', output_file('bin/darwin-4.2.1/debug/target-os-darwin/test'), input_file('bin/darwin-4.2.1/debug/target-os-darwin/main.o'), input_file('bin/darwin-4.2.1/debug/target-os-darwin/libl1.dylib'), unordered('-g', '-fPIC')) if allow_properties("variant=release", "link=shared", "runtime-link=shared"): command('g++', unordered('-O3', '-Wno-inline', '-Wall', '-dynamic', '-gdwarf-2', '-fexceptions', '-fPIC'), '-DNDEBUG', '-c', '-o', output_file('bin/darwin-4.2.1/release/target-os-darwin/lib.o'), input_file(source='lib.cpp')) - command('g++', '-dynamiclib', '-Wl,-single_module', '-install_name', 'libl1.dylib', '-o', output_file('bin/darwin-4.2.1/release/target-os-darwin/libl1.dylib'), input_file('bin/darwin-4.2.1/release/target-os-darwin/lib.o'), '-headerpad_max_install_names', '-Wl,-dead_strip', '-no_dead_strip_inits_and_terms', '-fPIC') + command('g++', '-dynamiclib', '-Wl,-single_module', '-install_name', 'libl1.dylib', '-o', output_file('bin/darwin-4.2.1/release/target-os-darwin/libl1.dylib'), input_file('bin/darwin-4.2.1/release/target-os-darwin/lib.o'), '-headerpad_max_install_names', unordered(ordered('-Wl,-dead_strip', '-no_dead_strip_inits_and_terms'), '-fPIC')) command('g++', unordered('-O3', '-Wno-inline', '-Wall', '-dynamic', '-gdwarf-2', '-fexceptions', '-fPIC'), '-DNDEBUG', '-c', '-o', output_file('bin/darwin-4.2.1/release/target-os-darwin/main.o'), input_file(source='main.cpp')) - command('g++', '-o', output_file('bin/darwin-4.2.1/release/target-os-darwin/test'), input_file('bin/darwin-4.2.1/release/target-os-darwin/main.o'), input_file('bin/darwin-4.2.1/release/target-os-darwin/libl1.dylib'), '-Wl,-dead_strip', '-no_dead_strip_inits_and_terms', '-fPIC') + command('g++', '-o', output_file('bin/darwin-4.2.1/release/target-os-darwin/test'), input_file('bin/darwin-4.2.1/release/target-os-darwin/main.o'), input_file('bin/darwin-4.2.1/release/target-os-darwin/libl1.dylib'), unordered(ordered('-Wl,-dead_strip', '-no_dead_strip_inits_and_terms'), '-fPIC')) if allow_properties("variant=debug", "link=static", "runtime-link=shared"): - command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-gdwarf-2', '-fexceptions', '-c', '-o', output_file('bin/darwin-4.2.1/debug/link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) - command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-gdwarf-2', '-fexceptions', '-c', '-o', output_file('bin/darwin-4.2.1/debug/link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('g++', unordered('-O0', '-fno-inline', '-Wall', '-g', '-gdwarf-2', '-fexceptions'), '-c', '-o', output_file('bin/darwin-4.2.1/debug/link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('g++', unordered('-O0', '-fno-inline', '-Wall', '-g', '-gdwarf-2', '-fexceptions'), '-c', '-o', output_file('bin/darwin-4.2.1/debug/link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) command('g++', '-o', output_file('bin/darwin-4.2.1/debug/link-static/target-os-darwin/test'), input_file('bin/darwin-4.2.1/debug/link-static/target-os-darwin/main.o'), input_file('bin/darwin-4.2.1/debug/link-static/target-os-darwin/libl1.a'), '-g') if allow_properties("variant=debug", "link=static", "runtime-link=static"): - command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-gdwarf-2', '-fexceptions', '-c', '-o', output_file('bin/darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) - command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-gdwarf-2', '-fexceptions', '-c', '-o', output_file('bin/darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) - command('g++', '-o', output_file('bin/darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/test'), input_file('bin/darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file('bin/darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), '-g', '-nodefaultlibs', '-shared-libgcc', '-lstdc++-static', '-lgcc_eh', '-lgcc', '-lSystem', '-static') + command('g++', unordered('-O0', '-fno-inline', '-Wall', '-g', '-gdwarf-2', '-fexceptions'), '-c', '-o', output_file('bin/darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('g++', unordered('-O0', '-fno-inline', '-Wall', '-g', '-gdwarf-2', '-fexceptions'), '-c', '-o', output_file('bin/darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('g++', '-o', output_file('bin/darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/test'), input_file('bin/darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file('bin/darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), unordered('-g', ordered('-nodefaultlibs', '-shared-libgcc', '-lstdc++-static', '-lgcc_eh', '-lgcc', '-lSystem'), '-static')) main() diff --git a/test/toolset-mock/src/gcc-4.2.1-darwin.py b/test/toolset-mock/src/gcc-4.2.1-darwin.py index ec88af680..76058c320 100644 --- a/test/toolset-mock/src/gcc-4.2.1-darwin.py +++ b/test/toolset-mock/src/gcc-4.2.1-darwin.py @@ -13,25 +13,25 @@ command('g++', '-print-prog-name=ranlib', stdout=script('ranlib.py')) # all builds are multi-threaded for darwin if allow_properties("variant=debug", "link=shared", "runtime-link=shared"): - command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-fPIC', '-c', '-o', output_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/lib.o'), input_file(source='lib.cpp')) - command('g++', '-o', output_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/libl1.dylib'), '-shared', input_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/lib.o'), '-g', '-fPIC') - command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-fPIC', '-c', '-o', output_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/main.o'), input_file(source='main.cpp')) - command('g++', '-Wl,-rpath', arg('-Wl,', target_path('bin/gcc-darwin-4.2.1/debug/target-os-darwin/libl1.dylib')), '-o', output_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/test'), input_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/main.o'), input_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/libl1.dylib'), '-g', '-fPIC') + command('g++', unordered('-O0', '-fno-inline', '-Wall', '-g', '-fPIC'), '-c', '-o', output_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('g++', '-o', output_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/libl1.dylib'), '-shared', input_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/lib.o'), unordered('-g', '-fPIC')) + command('g++', unordered('-O0', '-fno-inline', '-Wall', '-g', '-fPIC'), '-c', '-o', output_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('g++', '-Wl,-rpath', arg('-Wl,', target_path('bin/gcc-darwin-4.2.1/debug/target-os-darwin/libl1.dylib')), '-o', output_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/test'), input_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/main.o'), input_file('bin/gcc-darwin-4.2.1/debug/target-os-darwin/libl1.dylib'), unordered('-g', '-fPIC')) if allow_properties("variant=release", "link=shared", "runtime-link=shared"): - command('g++', '-O3', '-finline-functions', '-Wno-inline', '-Wall', '-fPIC', '-DNDEBUG', '-c', '-o', output_file('bin/gcc-darwin-4.2.1/release/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('g++', unordered('-O3', '-finline-functions', '-Wno-inline', '-Wall', '-fPIC', '-DNDEBUG'), '-c', '-o', output_file('bin/gcc-darwin-4.2.1/release/target-os-darwin/lib.o'), input_file(source='lib.cpp')) command('g++', '-o', output_file('bin/gcc-darwin-4.2.1/release/target-os-darwin/libl1.dylib'), '-shared', input_file('bin/gcc-darwin-4.2.1/release/target-os-darwin/lib.o'), '-fPIC') - command('g++', '-O3', '-finline-functions', '-Wno-inline', '-Wall', '-fPIC', '-DNDEBUG', '-c', '-o', output_file('bin/gcc-darwin-4.2.1/release/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('g++', unordered('-O3', '-finline-functions', '-Wno-inline', '-Wall', '-fPIC', '-DNDEBUG'), '-c', '-o', output_file('bin/gcc-darwin-4.2.1/release/target-os-darwin/main.o'), input_file(source='main.cpp')) command('g++', '-Wl,-rpath', arg('-Wl,', target_path('bin/gcc-darwin-4.2.1/release/target-os-darwin/libl1.dylib')), '-o', output_file('bin/gcc-darwin-4.2.1/release/target-os-darwin/test'), input_file('bin/gcc-darwin-4.2.1/release/target-os-darwin/main.o'), input_file('bin/gcc-darwin-4.2.1/release/target-os-darwin/libl1.dylib'), '-fPIC') if allow_properties("variant=debug", "link=static", "runtime-link=shared"): - command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) - command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('g++', unordered('-O0', '-fno-inline', '-Wall', '-g'), '-c', '-o', output_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('g++', unordered('-O0', '-fno-inline', '-Wall', '-g'), '-c', '-o', output_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) command('g++', '-o', output_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-darwin/test'), input_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-darwin/main.o'), input_file('bin/gcc-darwin-4.2.1/debug/link-static/target-os-darwin/libl1.a'), '-g') if allow_properties("variant=debug", "link=static", "runtime-link=static"): - command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) - command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) - command('g++', '-o', output_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/test'), input_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), '-g', '-static') + command('g++', unordered('-O0', '-fno-inline', '-Wall', '-g'), '-c', '-o', output_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('g++', unordered('-O0', '-fno-inline', '-Wall', '-g'), '-c', '-o', output_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('g++', '-o', output_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/test'), input_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file('bin/gcc-darwin-4.2.1/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), unordered('-g', '-static')) main() diff --git a/test/toolset-mock/src/gcc-4.8.3-linux.py b/test/toolset-mock/src/gcc-4.8.3-linux.py index a14eded1b..5604ee5d1 100644 --- a/test/toolset-mock/src/gcc-4.8.3-linux.py +++ b/test/toolset-mock/src/gcc-4.8.3-linux.py @@ -12,31 +12,39 @@ command('g++', '-print-prog-name=ar', stdout=script('ar.py')) command('g++', '-print-prog-name=ranlib', stdout=script('ranlib.py')) if allow_properties("variant=debug", "link=shared", "threading=single", "runtime-link=shared"): - command("g++", "-O0", "-fno-inline", "-Wall", "-g", "-fPIC", "-c", "-o", output_file("bin/gcc-gnu-4.8.3/debug/lib.o"), input_file(source="lib.cpp")) - command("g++", "-o", output_file("bin/gcc-gnu-4.8.3/debug/libl1.so"), "-Wl,-h", "-Wl,libl1.so", "-shared", "-Wl,--start-group", input_file("bin/gcc-gnu-4.8.3/debug/lib.o"), "-Wl,-Bstatic", "-Wl,-Bdynamic", "-Wl,--end-group", "-g", "-fPIC") - command("g++", "-O0", "-fno-inline", "-Wall", "-g", "-fPIC", "-c", "-o", output_file("bin/gcc-gnu-4.8.3/debug/main.o"), input_file(source="main.cpp")) - command("g++", "-Wl,-rpath", arg("-Wl,", target_path("bin/gcc-gnu-4.8.3/debug/libl1.so")), "-Wl,-rpath-link", arg("-Wl,", target_path("bin/gcc-gnu-4.8.3/debug/libl1.so")), "-o", output_file("bin/gcc-gnu-4.8.3/debug/test"), "-Wl,--start-group", input_file("bin/gcc-gnu-4.8.3/debug/main.o"), input_file("bin/gcc-gnu-4.8.3/debug/libl1.so"), "-Wl,-Bstatic", "-Wl,-Bdynamic", "-Wl,--end-group", "-g", "-fPIC") + command("g++", unordered("-O0", "-fno-inline", "-Wall", "-g", "-fPIC"), "-c", "-o", output_file("bin/gcc-gnu-4.8.3/debug/lib.o"), input_file(source="lib.cpp")) + command("g++", "-o", output_file("bin/gcc-gnu-4.8.3/debug/libl1.so"), "-Wl,-h", "-Wl,libl1.so", "-shared", "-Wl,--start-group", input_file("bin/gcc-gnu-4.8.3/debug/lib.o"), "-Wl,-Bstatic", "-Wl,-Bdynamic", "-Wl,--end-group", unordered("-g", "-fPIC")) + command("g++", unordered("-O0", "-fno-inline", "-Wall", "-g", "-fPIC"), "-c", "-o", output_file("bin/gcc-gnu-4.8.3/debug/main.o"), input_file(source="main.cpp")) + command("g++", "-Wl,-rpath", arg("-Wl,", target_path("bin/gcc-gnu-4.8.3/debug/libl1.so")), "-Wl,-rpath-link", arg("-Wl,", target_path("bin/gcc-gnu-4.8.3/debug/libl1.so")), "-o", output_file("bin/gcc-gnu-4.8.3/debug/test"), "-Wl,--start-group", input_file("bin/gcc-gnu-4.8.3/debug/main.o"), input_file("bin/gcc-gnu-4.8.3/debug/libl1.so"), "-Wl,-Bstatic", "-Wl,-Bdynamic", "-Wl,--end-group", unordered("-g", "-fPIC")) if allow_properties("variant=release", "link=shared", "threading=single", "runtime-link=shared"): - command('g++', '-O3', '-finline-functions', '-Wno-inline', '-Wall', '-fPIC', '-DNDEBUG', '-c', '-o', output_file('bin/gcc-gnu-4.8.3/release/lib.o'), input_file(source='lib.cpp')) + command('g++', unordered('-O3', '-finline-functions', '-Wno-inline', '-Wall', '-fPIC', '-DNDEBUG'), '-c', '-o', output_file('bin/gcc-gnu-4.8.3/release/lib.o'), input_file(source='lib.cpp')) command('g++', '-o', output_file('bin/gcc-gnu-4.8.3/release/libl1.so'), '-Wl,-h', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/gcc-gnu-4.8.3/release/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-fPIC') - command('g++', '-O3', '-finline-functions', '-Wno-inline', '-Wall', '-fPIC', '-DNDEBUG', '-c', '-o', output_file('bin/gcc-gnu-4.8.3/release/main.o'), input_file(source='main.cpp')) + command('g++', unordered('-O3', '-finline-functions', '-Wno-inline', '-Wall', '-fPIC', '-DNDEBUG'), '-c', '-o', output_file('bin/gcc-gnu-4.8.3/release/main.o'), input_file(source='main.cpp')) command('g++', '-Wl,-rpath', arg('-Wl,', target_path('bin/gcc-gnu-4.8.3/release/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/gcc-gnu-4.8.3/release/libl1.so')), '-o', output_file('bin/gcc-gnu-4.8.3/release/test'), '-Wl,--start-group', input_file('bin/gcc-gnu-4.8.3/release/main.o'), input_file('bin/gcc-gnu-4.8.3/release/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-fPIC') if allow_properties("variant=debug", "link=shared", "threading=multi", "runtime-link=shared"): - command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-pthread', '-fPIC', '-c', '-o', output_file('bin/gcc-gnu-4.8.3/debug/threading-multi/lib.o'), input_file(source='lib.cpp')) - command('g++', '-o', output_file('bin/gcc-gnu-4.8.3/debug/threading-multi/libl1.so'), '-Wl,-h', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/gcc-gnu-4.8.3/debug/threading-multi/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-lrt', '-Wl,--end-group', '-g', '-pthread', '-fPIC') - command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-pthread', '-fPIC', '-c', '-o', output_file('bin/gcc-gnu-4.8.3/debug/threading-multi/main.o'), input_file(source='main.cpp')) - command('g++', '-Wl,-rpath', arg('-Wl,', target_path('bin/gcc-gnu-4.8.3/debug/threading-multi/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/gcc-gnu-4.8.3/debug/threading-multi/libl1.so')), '-o', output_file('bin/gcc-gnu-4.8.3/debug/threading-multi/test'), '-Wl,--start-group', input_file('bin/gcc-gnu-4.8.3/debug/threading-multi/main.o'), input_file('bin/gcc-gnu-4.8.3/debug/threading-multi/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-lrt', '-Wl,--end-group', '-g', '-pthread', '-fPIC') + command('g++', unordered('-O0', '-fno-inline', '-Wall', '-g', '-pthread', '-fPIC'), '-c', '-o', output_file('bin/gcc-gnu-4.8.3/debug/threading-multi/lib.o'), input_file(source='lib.cpp')) + command('g++', '-o', output_file('bin/gcc-gnu-4.8.3/debug/threading-multi/libl1.so'), '-Wl,-h', '-Wl,libl1.so', '-shared', '-Wl,--start-group', input_file('bin/gcc-gnu-4.8.3/debug/threading-multi/lib.o'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-lrt', '-Wl,--end-group', unordered('-g', '-pthread', '-fPIC')) + command('g++', unordered('-O0', '-fno-inline', '-Wall', '-g', '-pthread', '-fPIC'), '-c', '-o', output_file('bin/gcc-gnu-4.8.3/debug/threading-multi/main.o'), input_file(source='main.cpp')) + command('g++', '-Wl,-rpath', arg('-Wl,', target_path('bin/gcc-gnu-4.8.3/debug/threading-multi/libl1.so')), '-Wl,-rpath-link', arg('-Wl,', target_path('bin/gcc-gnu-4.8.3/debug/threading-multi/libl1.so')), '-o', output_file('bin/gcc-gnu-4.8.3/debug/threading-multi/test'), '-Wl,--start-group', input_file('bin/gcc-gnu-4.8.3/debug/threading-multi/main.o'), input_file('bin/gcc-gnu-4.8.3/debug/threading-multi/libl1.so'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-lrt', '-Wl,--end-group', unordered('-g', '-pthread', '-fPIC')) if allow_properties("variant=debug", "link=static", "threading=single", "runtime-link=shared"): - command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/gcc-gnu-4.8.3/debug/link-static/lib.o'), input_file(source='lib.cpp')) - command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/gcc-gnu-4.8.3/debug/link-static/main.o'), input_file(source='main.cpp')) + command('g++', unordered('-O0', '-fno-inline', '-Wall', '-g'), '-c', '-o', output_file('bin/gcc-gnu-4.8.3/debug/link-static/lib.o'), input_file(source='lib.cpp')) + command('g++', unordered('-O0', '-fno-inline', '-Wall', '-g'), '-c', '-o', output_file('bin/gcc-gnu-4.8.3/debug/link-static/main.o'), input_file(source='main.cpp')) command('g++', '-o', output_file('bin/gcc-gnu-4.8.3/debug/link-static/test'), '-Wl,--start-group', input_file('bin/gcc-gnu-4.8.3/debug/link-static/main.o'), input_file('bin/gcc-gnu-4.8.3/debug/link-static/libl1.a'), '-Wl,-Bstatic', '-Wl,-Bdynamic', '-Wl,--end-group', '-g') if allow_properties("variant=debug", "link=static", "threading=single", "runtime-link=static"): - command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/lib.o'), input_file(source='lib.cpp')) - command('g++', '-O0', '-fno-inline', '-Wall', '-g', '-c', '-o', output_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/main.o'), input_file(source='main.cpp')) - command('g++', '-o', output_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/test'), '-Wl,--start-group', input_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/main.o'), input_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/libl1.a'), '-Wl,--end-group', '-g', '-static') + command('g++', unordered('-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/lib.o'), input_file(source='lib.cpp')) + command('g++', unordered('-O0', '-fno-inline', '-Wall', '-g', '-c'), '-o', output_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/main.o'), input_file(source='main.cpp')) + command('g++', '-o', output_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/test'), '-Wl,--start-group', input_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/main.o'), input_file('bin/gcc-gnu-4.8.3/debug/link-static/runtime-link-static/libl1.a'), '-Wl,--end-group', unordered('-g', '-static')) + + +if allow_properties("variant=debug", "link=shared", "threading=single", "runtime-link=shared"): + command("g++", unordered("-O0", "-fno-inline", "-Wall", "-g", "-fPIC", "-std=c++1y"), "-c", "-o", output_file("bin/gcc-gnu-4.8.3/debug/lib.o"), input_file(source="lib.cpp")) + command("g++", "-o", output_file("bin/gcc-gnu-4.8.3/debug/libl1.so"), "-Wl,-h", "-Wl,libl1.so", "-shared", "-Wl,--start-group", input_file("bin/gcc-gnu-4.8.3/debug/lib.o"), "-Wl,-Bstatic", "-Wl,-Bdynamic", "-Wl,--end-group", unordered("-g", "-fPIC", "-std=c++1y")) + command("g++", unordered("-O0", "-fno-inline", "-Wall", "-g", "-fPIC", "-std=c++1y"), "-c", "-o", output_file("bin/gcc-gnu-4.8.3/debug/main.o"), input_file(source="main.cpp")) + command("g++", "-Wl,-rpath", arg("-Wl,", target_path("bin/gcc-gnu-4.8.3/debug/libl1.so")), "-Wl,-rpath-link", arg("-Wl,", target_path("bin/gcc-gnu-4.8.3/debug/libl1.so")), "-o", output_file("bin/gcc-gnu-4.8.3/debug/test"), "-Wl,--start-group", input_file("bin/gcc-gnu-4.8.3/debug/main.o"), input_file("bin/gcc-gnu-4.8.3/debug/libl1.so"), "-Wl,-Bstatic", "-Wl,-Bdynamic", "-Wl,--end-group", unordered("-g", "-fPIC", "-std=c++1y")) + main() diff --git a/test/toolset-mock/src/intel-darwin-10.2.py b/test/toolset-mock/src/intel-darwin-10.2.py index 5638cf55e..314d6c458 100644 --- a/test/toolset-mock/src/intel-darwin-10.2.py +++ b/test/toolset-mock/src/intel-darwin-10.2.py @@ -14,30 +14,30 @@ command('icc', '-print-prog-name=ranlib', stdout=script('ranlib.py')) # all builds are multi-threaded for darwin if allow_properties("variant=debug", "link=shared", "runtime-link=shared"): command('icc', '-xc++', unordered('-O0', '-inline-level=0', '-w1', '-g', '-vec-report0', '-fPIC'), '-c', '-o', output_file('bin/intel-darwin-10.2/debug/target-os-darwin/lib.o'), input_file(source='lib.cpp')) - command('icc', '-o', output_file('bin/intel-darwin-10.2/debug/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', 'libl1.dylib', input_file('bin/intel-darwin-10.2/debug/target-os-darwin/lib.o'), '-g', '-shared-intel', '-lstdc++', '-lpthread', '-fPIC') + command('icc', '-o', output_file('bin/intel-darwin-10.2/debug/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', 'libl1.dylib', input_file('bin/intel-darwin-10.2/debug/target-os-darwin/lib.o'), unordered('-g', ordered('-shared-intel', '-lstdc++', '-lpthread'), '-fPIC')) command('icc', '-xc++', unordered('-O0', '-inline-level=0', '-w1', '-g', '-vec-report0', '-fPIC'), '-c', '-o', output_file('bin/intel-darwin-10.2/debug/target-os-darwin/main.o'), input_file(source='main.cpp')) - command('icc', '-o', output_file('bin/intel-darwin-10.2/debug/target-os-darwin/test'), input_file('bin/intel-darwin-10.2/debug/target-os-darwin/main.o'), input_file('bin/intel-darwin-10.2/debug/target-os-darwin/libl1.dylib'), '-g', '-shared-intel', '-lstdc++', '-lpthread', '-fPIC') + command('icc', '-o', output_file('bin/intel-darwin-10.2/debug/target-os-darwin/test'), input_file('bin/intel-darwin-10.2/debug/target-os-darwin/main.o'), input_file('bin/intel-darwin-10.2/debug/target-os-darwin/libl1.dylib'), unordered('-g', ordered('-shared-intel', '-lstdc++', '-lpthread'), '-fPIC')) if allow_properties("variant=release", "link=shared", "runtime-link=shared"): command('icc', '-xc++', unordered('-O3', '-inline-level=2', '-w1', '-vec-report0', '-fPIC'), '-DNDEBUG', '-c', '-o', output_file('bin/intel-darwin-10.2/release/target-os-darwin/lib.o'), input_file(source='lib.cpp')) - command('icc', '-o', output_file('bin/intel-darwin-10.2/release/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', 'libl1.dylib', input_file('bin/intel-darwin-10.2/release/target-os-darwin/lib.o'), '-shared-intel', '-lstdc++', '-lpthread', '-fPIC') + command('icc', '-o', output_file('bin/intel-darwin-10.2/release/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', 'libl1.dylib', input_file('bin/intel-darwin-10.2/release/target-os-darwin/lib.o'), unordered(ordered('-shared-intel', '-lstdc++', '-lpthread'), '-fPIC')) command('icc', '-xc++', unordered('-O3', '-inline-level=2', '-w1', '-vec-report0', '-fPIC'), '-DNDEBUG', '-c', '-o', output_file('bin/intel-darwin-10.2/release/target-os-darwin/main.o'), input_file(source='main.cpp')) - command('icc', '-o', output_file('bin/intel-darwin-10.2/release/target-os-darwin/test'), input_file('bin/intel-darwin-10.2/release/target-os-darwin/main.o'), input_file('bin/intel-darwin-10.2/release/target-os-darwin/libl1.dylib'), '-shared-intel', '-lstdc++', '-lpthread', '-fPIC') + command('icc', '-o', output_file('bin/intel-darwin-10.2/release/target-os-darwin/test'), input_file('bin/intel-darwin-10.2/release/target-os-darwin/main.o'), input_file('bin/intel-darwin-10.2/release/target-os-darwin/libl1.dylib'), unordered(ordered('-shared-intel', '-lstdc++', '-lpthread'), '-fPIC')) if allow_properties("variant=debug", "link=static", "runtime-link=shared"): command('icc', '-xc++', unordered('-O0', '-inline-level=0', '-w1', '-g', '-vec-report0'), '-c', '-o', output_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) command('icc', '-xc++', unordered('-O0', '-inline-level=0', '-w1', '-g', '-vec-report0'), '-c', '-o', output_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) - command('icc', '-o', output_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/test'), input_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/main.o'), input_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/libl1.a'), '-g', '-shared-intel', '-lstdc++', '-lpthread') + command('icc', '-o', output_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/test'), input_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/main.o'), input_file('bin/intel-darwin-10.2/debug/link-static/target-os-darwin/libl1.a'), '-g', ordered('-shared-intel', '-lstdc++', '-lpthread')) if allow_properties("variant=debug", "link=static", "runtime-link=static"): command('icc', '-xc++', unordered('-O0', '-inline-level=0', '-w1', '-g', '-vec-report0'), '-c', '-o', output_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/lib.o'), input_file(source='lib.cpp')) command('icc', '-xc++', unordered('-O0', '-inline-level=0', '-w1', '-g', '-vec-report0'), '-c', '-o', output_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file(source='main.cpp')) - command('icc', '-o', output_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/test'), input_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), '-g', '-static', '-static-intel', '-lstdc++', '-lpthread', '-static') + command('icc', '-o', output_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/test'), input_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/main.o'), input_file('bin/intel-darwin-10.2/debug/link-static/runtime-link-static/target-os-darwin/libl1.a'), unordered('-g', ordered('-static', '-static-intel', '-lstdc++', '-lpthread'), '-static')) if allow_properties("variant=debug", "link=shared", "runtime-link=shared", "architecture=x86", "address-model=32"): - command('icc', '-xc++', unordered('-O0', '-inline-level=0', '-w1', '-g', '-vec-report0'), '-march=i686', '-fPIC', '-m32', '-c', '-o', output_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/lib.o'), input_file(source='lib.cpp')) - command('icc', '-o', output_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', 'libl1.dylib', input_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/lib.o'), '-g', '-shared-intel', '-lstdc++', '-lpthread', '-march=i686', '-fPIC', '-m32') - command('icc', '-xc++', unordered('-O0', '-inline-level=0', '-w1', '-g', '-vec-report0'), '-march=i686', '-fPIC', '-m32', '-c', '-o', output_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/main.o'), input_file(source='main.cpp')) - command('icc', '-o', output_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/test'), input_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/main.o'), input_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/libl1.dylib'), '-g', '-shared-intel', '-lstdc++', '-lpthread', '-march=i686', '-fPIC', '-m32') + command('icc', '-xc++', unordered('-O0', '-inline-level=0', '-w1', '-g', '-vec-report0', '-march=i686', '-fPIC', '-m32'), '-c', '-o', output_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/lib.o'), input_file(source='lib.cpp')) + command('icc', '-o', output_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/libl1.dylib'), '-single_module', '-dynamiclib', '-install_name', 'libl1.dylib', input_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/lib.o'), unordered('-g', ordered('-shared-intel', '-lstdc++', '-lpthread'), '-march=i686', '-fPIC', '-m32')) + command('icc', '-xc++', unordered('-O0', '-inline-level=0', '-w1', '-g', '-vec-report0', '-march=i686', '-fPIC', '-m32'), '-c', '-o', output_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/main.o'), input_file(source='main.cpp')) + command('icc', '-o', output_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/test'), input_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/main.o'), input_file('bin/intel-darwin-10.2/debug/x86/target-os-darwin/libl1.dylib'), unordered('-g', ordered('-shared-intel', '-lstdc++', '-lpthread'), '-march=i686', '-fPIC', '-m32')) main() diff --git a/test/toolset_clang_darwin.py b/test/toolset_clang_darwin.py index e3bb0265f..d8c519b64 100644 --- a/test/toolset_clang_darwin.py +++ b/test/toolset_clang_darwin.py @@ -16,4 +16,5 @@ test_toolset("clang-darwin", "3.9.0", [ ["target-os=darwin", "threading=multi"], ["target-os=darwin", "link=static"], ["target-os=darwin", "link=static", "runtime-link=static"], - ["target-os=darwin", "architecture=x86", "address-model=32"]]) + ["target-os=darwin", "architecture=x86", "address-model=32"], + ["target-os=darwin", "cxxstd=latest"]]) diff --git a/test/toolset_gcc.py b/test/toolset_gcc.py index 9007de3e8..d3d65fcf9 100644 --- a/test/toolset_gcc.py +++ b/test/toolset_gcc.py @@ -15,7 +15,8 @@ test_toolset("gcc", "4.8.3", [ ["target-os=linux", "release"], ["target-os=linux", "threading=multi"], ["target-os=linux", "link=static"], - ["target-os=linux", "link=static", "runtime-link=static"]]) + ["target-os=linux", "link=static", "runtime-link=static"], + ["target-os=linux", "cxxstd=latest"]]) test_toolset("gcc", "4.2.1", [ ["target-os=darwin"], From a0dbab8c78906dd646abff2118b1420a0ae98d5b Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Thu, 4 Jan 2018 09:22:30 -0700 Subject: [PATCH 51/72] Fix handling of implicit-dependency in xsltproc. Previously, was necessary because the include scanner was not set up correctly. --- src/tools/boostbook.jam | 2 +- src/tools/doxygen.jam | 4 +- src/tools/xsltproc.jam | 87 +++++++++++++++++++++++++---------------- 3 files changed, 57 insertions(+), 36 deletions(-) diff --git a/src/tools/boostbook.jam b/src/tools/boostbook.jam index 43e7366da..d99d5d04a 100644 --- a/src/tools/boostbook.jam +++ b/src/tools/boostbook.jam @@ -94,7 +94,7 @@ rule init ( find-tools $(docbook-xsl-dir) : $(docbook-dtd-dir) : $(boostbook-dir) ; # Register generators only if we were called via "using boostbook ;" - local reg-gen = generators.register-standard ; + local reg-gen = generators.register-xslt ; $(reg-gen) boostbook.dtdxml-to-boostbook : DTDXML : XML ; $(reg-gen) boostbook.boostbook-to-docbook : XML : DOCBOOK ; $(reg-gen) boostbook.boostbook-to-tests : XML : TESTS ; diff --git a/src/tools/doxygen.jam b/src/tools/doxygen.jam index 1e5362431..0594e5363 100644 --- a/src/tools/doxygen.jam +++ b/src/tools/doxygen.jam @@ -105,9 +105,9 @@ rule init ( name ? ) : DOXYFILE : DOXYGEN_XML_MULTIFILE ; generators.register-standard doxygen.xml-dir-to-boostbook : DOXYGEN_XML_MULTIFILE : BOOSTBOOK : doxproc ; - generators.register-standard doxygen.xml-to-boostbook + generators.register-xslt doxygen.xml-to-boostbook : DOXYGEN_XML : BOOSTBOOK : xsltproc ; - generators.register-standard doxygen.collect + generators.register-xslt doxygen.collect : DOXYGEN_XML_MULTIFILE : DOXYGEN_XML ; generators.register-standard doxygen.run : DOXYFILE : DOXYGEN_HTML_MULTIFILE ; diff --git a/src/tools/xsltproc.jam b/src/tools/xsltproc.jam index 56de81f36..b08089b92 100644 --- a/src/tools/xsltproc.jam +++ b/src/tools/xsltproc.jam @@ -6,14 +6,17 @@ # This module defines rules to apply an XSLT stylesheet to an XML file using the # xsltproc driver, part of libxslt. +import "class" : new ; import common ; import feature ; +import generators ; import modules ; import os ; import path ; import regex ; import sequence ; - +import toolset ; +import virtual-target ; feature.feature xsl:param : : free ; feature.feature xsl:path : : free ; @@ -108,12 +111,53 @@ rule .is-cygwin ( xsltproc ) } } +class xsltproc-action : action +{ + rule adjust-properties ( property-set ) + { + local s = [ $(self.targets[1]).creating-subvariant ] ; + if $(s) + { + return [ $(property-set).add-raw + [ $(s).implicit-includes "xsl:path" : XML ] ] ; + } + else + { + return $(property-set) ; + } + } +} + +class xsltproc-generator : generator +{ + rule action-class ( ) + { + return xsltproc-action ; + } +} + +rule register-generator ( id : source-types + : target-types + : requirements * ) +{ + if ! $(id) in $(.known-rules) + { + .known-rules += $(id) ; + flags $(id) ; + } + generators.register [ new xsltproc-generator $(id) : + $(source-types) : $(target-types) : $(requirements) ] ; +} + +IMPORT xsltproc : register-generator : : generators.register-xslt ; + +rule flags ( rulename ) +{ + toolset.flags $(rulename) XSL-PATH : : unchecked ; + toolset.flags $(rulename) FLAGS : : unchecked ; +} rule compute-xslt-flags ( target : properties * ) { - # Raw flags. - local flags = [ feature.get-values : $(properties) ] ; - + local flags ; # Translate into command line flags. for local param in [ feature.get-values : $(properties) ] { @@ -121,31 +165,6 @@ rule compute-xslt-flags ( target : properties * ) flags += --stringparam $(namevalue[1]) \"$(namevalue[2])\" ; } - # Translate . - for local path in [ feature.get-values : $(properties) ] - { - flags += --path \"$(path:G=)\" ; - } - - # Take care of implicit dependencies. - local other-deps ; - for local dep in [ feature.get-values : $(properties) - ] - { - other-deps += [ $(dep:G=).creating-subvariant ] ; - } - - local implicit-target-directories ; - for local dep in [ sequence.unique $(other-deps) ] - { - implicit-target-directories += [ $(dep).all-target-directories ] ; - } - - for local dir in $(implicit-target-directories) - { - flags += --path \"$(dir:T)\" ; - } - return $(flags) ; } @@ -186,25 +205,27 @@ rule xslt-dir ( target : source stylesheet : properties * : dirname ) $(dirname) : xslt-xsltproc-dir ] ; } +_ = " " ; + actions xslt-xsltproc.windows { - $(CATALOG) "$(NAME:E=xsltproc)" $(FLAGS) --xinclude -o "$(<)" "$(STYLESHEET:W)" "$(>:W)" + $(CATALOG) "$(NAME:E=xsltproc)" $(FLAGS) --path$(_)"$(XSL-PATH:W)" --xinclude -o "$(<)" "$(STYLESHEET:W)" "$(>:W)" } actions xslt-xsltproc bind STYLESHEET { - $(CATALOG) "$(NAME:E=xsltproc)" $(FLAGS) --xinclude -o "$(<)" "$(STYLESHEET:T)" "$(>:T)" + $(CATALOG) "$(NAME:E=xsltproc)" $(FLAGS) --path$(_)"$(XSL-PATH:T)" --xinclude -o "$(<)" "$(STYLESHEET:T)" "$(>:T)" } actions xslt-xsltproc-dir.windows bind STYLESHEET { - $(CATALOG) "$(NAME:E=xsltproc)" $(FLAGS) --xinclude -o "$(<:D)/" "$(STYLESHEET:W)" "$(>:W)" + $(CATALOG) "$(NAME:E=xsltproc)" $(FLAGS) --path$(_)"$(XSL-PATH:W)" --xinclude -o "$(<:D)/" "$(STYLESHEET:W)" "$(>:W)" } actions xslt-xsltproc-dir bind STYLESHEET { - $(CATALOG) "$(NAME:E=xsltproc)" $(FLAGS) --xinclude -o "$(<:D)/" "$(STYLESHEET:T)" "$(>:T)" + $(CATALOG) "$(NAME:E=xsltproc)" $(FLAGS) --path$(_)"$(XSL-PATH:T)" --xinclude -o "$(<:D)/" "$(STYLESHEET:T)" "$(>:T)" } From a3caa57af34365dceaf0aa7e4817375057c276c9 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Thu, 4 Jan 2018 12:37:32 -0700 Subject: [PATCH 52/72] Clean up library modules. feature.get-values is nicer than property.select + G=. --- src/tools/bzip2.jam | 22 ++++++++-------------- src/tools/libjpeg.jam | 22 ++++++++-------------- src/tools/libpng.jam | 22 ++++++++-------------- src/tools/libtiff.jam | 22 ++++++++-------------- src/tools/lzma.jam | 11 ++++------- src/tools/zlib.jam | 22 ++++++++-------------- src/util/indirect.jam | 13 ++++++++++--- 7 files changed, 54 insertions(+), 80 deletions(-) diff --git a/src/tools/bzip2.jam b/src/tools/bzip2.jam index e6f9dcc13..49d83badd 100644 --- a/src/tools/bzip2.jam +++ b/src/tools/bzip2.jam @@ -14,11 +14,11 @@ import project ; import ac ; import errors ; +import feature ; import "class" : new ; import targets ; import path ; import modules ; -import errors ; import indirect ; import make ; import os ; @@ -113,18 +113,12 @@ rule init ( project bzip2 ; } - local library-path = [ property.select : $(options) ] ; - library-path = $(library-path:G=) ; - local include-path = [ property.select : $(options) ] ; - include-path = $(include-path:G=) ; - local source-path = [ property.select : $(options) ] ; - source-path = $(source-path:G=) ; - local library-name = [ property.select : $(options) ] ; - library-name = $(library-name:G=) ; - local tag = [ property.select : $(options) ] ; - tag = $(tag:G=) ; - local build-name = [ property.select : $(options) ] ; - build-name = $(build-name:G=) ; + local library-path = [ feature.get-values : $(options) ] ; + local include-path = [ feature.get-values : $(options) ] ; + local source-path = [ feature.get-values : $(options) ] ; + local library-name = [ feature.get-values : $(options) ] ; + local tag = [ feature.get-values : $(options) ] ; + local build-name = [ feature.get-values : $(options) ] ; if ! $(library-path) && ! $(include-path) && ! $(source-path) && ! $(library-name) { @@ -171,7 +165,7 @@ rule init ( build-name ?= bz2 ; library-id = [ CALC $(library-id) + 1 ] ; tag = [ MATCH ^@?(.*)$ : $(tag) ] ; - if $(tag) && ! [ MATCH ^([^%]*)%([^%]+)$ : $(tag) ] + if $(tag) { tag = [ indirect.make $(tag) : [ $(caller).project-module ] ] ; } diff --git a/src/tools/libjpeg.jam b/src/tools/libjpeg.jam index f6b7ec91e..f267ecb73 100644 --- a/src/tools/libjpeg.jam +++ b/src/tools/libjpeg.jam @@ -14,11 +14,11 @@ import project ; import ac ; import errors ; +import feature ; import "class" : new ; import targets ; import path ; import modules ; -import errors ; import indirect ; import property ; import property-set ; @@ -119,18 +119,12 @@ rule init ( project libjpeg ; } - local library-path = [ property.select : $(options) ] ; - library-path = $(library-path:G=) ; - local include-path = [ property.select : $(options) ] ; - include-path = $(include-path:G=) ; - local source-path = [ property.select : $(options) ] ; - source-path = $(source-path:G=) ; - local library-name = [ property.select : $(options) ] ; - library-name = $(library-name:G=) ; - local tag = [ property.select : $(options) ] ; - tag = $(tag:G=) ; - local build-name = [ property.select : $(options) ] ; - build-name = $(build-name:G=) ; + local library-path = [ feature.get-values : $(options) ] ; + local include-path = [ feature.get-values : $(options) ] ; + local source-path = [ feature.get-values : $(options) ] ; + local library-name = [ feature.get-values : $(options) ] ; + local tag = [ feature.get-values : $(options) ] ; + local build-name = [ feature.get-values : $(options) ] ; condition = [ property-set.create $(requirements) ] ; condition = [ property-set.create [ $(condition).base ] ] ; @@ -176,7 +170,7 @@ rule init ( build-name ?= jpeg ; library-id = [ CALC $(library-id) + 1 ] ; tag = [ MATCH ^@?(.*)$ : $(tag) ] ; - if $(tag) && ! [ MATCH ^([^%]*)%([^%]+)$ : $(tag) ] + if $(tag) { tag = [ indirect.make $(tag) : [ $(caller).project-module ] ] ; } diff --git a/src/tools/libpng.jam b/src/tools/libpng.jam index 0cab2eb88..43f681763 100644 --- a/src/tools/libpng.jam +++ b/src/tools/libpng.jam @@ -14,11 +14,11 @@ import project ; import ac ; import errors ; +import feature ; import "class" : new ; import targets ; import path ; import modules ; -import errors ; import indirect ; import property ; import property-set ; @@ -110,18 +110,12 @@ rule init ( project libpng ; } - local library-path = [ property.select : $(options) ] ; - library-path = $(library-path:G=) ; - local include-path = [ property.select : $(options) ] ; - include-path = $(include-path:G=) ; - local source-path = [ property.select : $(options) ] ; - source-path = $(source-path:G=) ; - local library-name = [ property.select : $(options) ] ; - library-name = $(library-name:G=) ; - local tag = [ property.select : $(options) ] ; - tag = $(tag:G=) ; - local build-name = [ property.select : $(options) ] ; - build-name = $(build-name:G=) ; + local library-path = [ feature.get-values : $(options) ] ; + local include-path = [ feature.get-values : $(options) ] ; + local source-path = [ feature.get-values : $(options) ] ; + local library-name = [ feature.get-values : $(options) ] ; + local tag = [ feature.get-values : $(options) ] ; + local build-name = [ feature.get-values : $(options) ] ; if ! $(library-path) && ! $(include-path) && ! $(source-path) && ! $(library-name) { @@ -167,7 +161,7 @@ rule init ( build-name ?= png ; library-id = [ CALC $(library-id) + 1 ] ; tag = [ MATCH ^@?(.*)$ : $(tag) ] ; - if $(tag) && ! [ MATCH ^([^%]*)%([^%]+)$ : $(tag) ] + if $(tag) { tag = [ indirect.make $(tag) : [ $(caller).project-module ] ] ; } diff --git a/src/tools/libtiff.jam b/src/tools/libtiff.jam index 94b94cb10..f31561491 100644 --- a/src/tools/libtiff.jam +++ b/src/tools/libtiff.jam @@ -14,11 +14,11 @@ import project ; import ac ; import errors ; +import feature ; import "class" : new ; import targets ; import path ; import modules ; -import errors ; import indirect ; import property ; import property-set ; @@ -113,18 +113,12 @@ rule init ( project libtiff ; } - local library-path = [ property.select : $(options) ] ; - library-path = $(library-path:G=) ; - local include-path = [ property.select : $(options) ] ; - include-path = $(include-path:G=) ; - local source-path = [ property.select : $(options) ] ; - source-path = $(source-path:G=) ; - local library-name = [ property.select : $(options) ] ; - library-name = $(library-name:G=) ; - local tag = [ property.select : $(options) ] ; - tag = $(tag:G=) ; - local build-name = [ property.select : $(options) ] ; - build-name = $(build-name:G=) ; + local library-path = [ feature.get-values : $(options) ] ; + local include-path = [ feature.get-values : $(options) ] ; + local source-path = [ feature.get-values : $(options) ] ; + local library-name = [ feature.get-values : $(options) ] ; + local tag = [ feature.get-values : $(options) ] ; + local build-name = [ feature.get-values : $(options) ] ; if ! $(library-path) && ! $(include-path) && ! $(source-path) && ! $(library-name) { @@ -170,7 +164,7 @@ rule init ( build-name ?= tiff ; library-id = [ CALC $(library-id) + 1 ] ; tag = [ MATCH ^@?(.*)$ : $(tag) ] ; - if $(tag) && ! [ MATCH ^([^%]*)%([^%]+)$ : $(tag) ] + if $(tag) { tag = [ indirect.make $(tag) : [ $(caller).project-module ] ] ; } diff --git a/src/tools/lzma.jam b/src/tools/lzma.jam index 2c9c77b6f..619f309f6 100644 --- a/src/tools/lzma.jam +++ b/src/tools/lzma.jam @@ -14,11 +14,11 @@ import project ; import ac ; import errors ; +import feature ; import "class" : new ; import targets ; import path ; import modules ; -import errors ; import indirect ; import property ; import property-set ; @@ -62,12 +62,9 @@ rule init ( project lzma ; } - local library-path = [ property.select : $(options) ] ; - library-path = $(library-path:G=) ; - local include-path = [ property.select : $(options) ] ; - include-path = $(include-path:G=) ; - local library-name = [ property.select : $(options) ] ; - library-name = $(library-name:G=) ; + local library-path = [ feature.get-values : $(options) ] ; + local include-path = [ feature.get-values : $(options) ] ; + local library-name = [ feature.get-values : $(options) ] ; if ! $(options) { diff --git a/src/tools/zlib.jam b/src/tools/zlib.jam index 4651e35a7..e1cc0cbcb 100644 --- a/src/tools/zlib.jam +++ b/src/tools/zlib.jam @@ -14,11 +14,11 @@ import project ; import ac ; import errors ; +import feature ; import "class" : new ; import targets ; import path ; import modules ; -import errors ; import indirect ; import property ; import property-set ; @@ -111,18 +111,12 @@ rule init ( project zlib ; } - local library-path = [ property.select : $(options) ] ; - library-path = $(library-path:G=) ; - local include-path = [ property.select : $(options) ] ; - include-path = $(include-path:G=) ; - local source-path = [ property.select : $(options) ] ; - source-path = $(source-path:G=) ; - local library-name = [ property.select : $(options) ] ; - library-name = $(library-name:G=) ; - local tag = [ property.select : $(options) ] ; - tag = $(tag:G=) ; - local build-name = [ property.select : $(options) ] ; - build-name = $(build-name:G=) ; + local library-path = [ feature.get-values : $(options) ] ; + local include-path = [ feature.get-values : $(options) ] ; + local source-path = [ feature.get-values : $(options) ] ; + local library-name = [ feature.get-values : $(options) ] ; + local tag = [ feature.get-values : $(options) ] ; + local build-name = [ feature.get-values : $(options) ] ; if ! $(library-path) && ! $(include-path) && ! $(source-path) && ! $(library-name) { @@ -168,7 +162,7 @@ rule init ( build-name ?= z ; library-id = [ CALC $(library-id) + 1 ] ; tag = [ MATCH ^@?(.*)$ : $(tag) ] ; - if $(tag) && ! [ MATCH ^([^%]*)%([^%]+)$ : $(tag) ] + if $(tag) { tag = [ indirect.make $(tag) : [ $(caller).project-module ] ] ; } diff --git a/src/util/indirect.jam b/src/util/indirect.jam index 40884da96..9f5f9dedd 100644 --- a/src/util/indirect.jam +++ b/src/util/indirect.jam @@ -31,9 +31,16 @@ local rule indirect-rule ( x ) # rule make ( rulename bound-args * : context ? ) { - context ?= [ CALLER_MODULE ] ; - context ?= "" ; - return $(context)%$(rulename) $(bound-args) ; + if [ MATCH $(.pattern) : $(rulename) ] + { + return $(rulename) $(bound-args) ; + } + else + { + context ?= [ CALLER_MODULE ] ; + context ?= "" ; + return $(context)%$(rulename) $(bound-args) ; + } } From a4962133a05e9502a1bd84cd38a5232cd3f1b12c Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 6 Jan 2018 13:55:05 -0700 Subject: [PATCH 53/72] Kill code that has no effect because it accesses a non-existent variable. This is already handled elsewhere. --- src/build/ac.jam | 1 - 1 file changed, 1 deletion(-) diff --git a/src/build/ac.jam b/src/build/ac.jam index 0255b7793..846965a03 100644 --- a/src/build/ac.jam +++ b/src/build/ac.jam @@ -79,7 +79,6 @@ rule find-include-path ( properties : header : provided-path ? : test-source ? ) rule construct-library ( name : property-set : provided-path ? ) { - property-set = [ $(property-set).refine [ property-set.create $(link-opt) ] ] ; local lib-props = [ $(property-set).add-raw $(name) $(provided-path) ] ; return [ generators.construct $(.project) lib-$(name) : SEARCHED_LIB : $(lib-props) : : true ] ; From 15c876025afb3caa2961642179b112f0532dcdf1 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 6 Jan 2018 13:55:38 -0700 Subject: [PATCH 54/72] Make target requirements handle subfeatures and composites correctly * feature.add-defaults: No longer accepts conditionals and returns expanded properties. This matches the actual usage, and conditionals never really worked right anyway. * property.refine: Remove subfeatures of removed features. * Moved property-set expansion and adding defaults into targets.evaluate-requirements so that they correctly interact with the target requirements. * Expand subfeatures when matching target alternatives. * Non-property-specific subfeatures like 11-iso are expanded correctly. --- src/build/feature.jam | 94 ++++++++++++++++++++++++++++++------------ src/build/property.jam | 16 ++++++- src/build/targets.jam | 36 ++++++---------- test/alternatives.py | 21 ++++++++-- test/expansion.py | 72 ++++++++++++++++++++++++++++++-- 5 files changed, 182 insertions(+), 57 deletions(-) diff --git a/src/build/feature.jam b/src/build/feature.jam index 4dbe107bb..c4f681867 100644 --- a/src/build/feature.jam +++ b/src/build/feature.jam @@ -289,7 +289,8 @@ local rule find-implied-subfeature ( feature subvalue : value-string ? ) import errors ; errors.error invalid feature $(feature) ; } - return $($(feature)$(value-string:E="")<>$(subvalue).subfeature) ; + value-string += "" ; + return $($(feature)$(value-string)<>$(subvalue).subfeature) ; } @@ -1039,6 +1040,8 @@ local rule split-top-feature ( feature-plus ) # Given a set of properties, add default values for features not represented in # the set. # +# properties must be fully expanded and must not contain conditionals. +# # Note: if there's an ordinary feature F1 and a composite feature F2 which # includes some value for F1 and both feature have default values then the # default value of F1 will be added (as opposed to the value in F2). This might @@ -1066,27 +1069,65 @@ rule add-defaults ( properties * ) feature ; } } - # We don't add default for elements with ":" inside. This catches: - # 1. Conditional properties --- we don't want debug:DEBUG - # to be takes as specified value for - # 2. Free properties with ":" in values. We don't care, since free - # properties don't have defaults. - local xproperties = [ MATCH "^([^:]+)$" : $(properties) ] ; - local missing-top = [ set.difference $(.all-top-features) : $(xproperties:G) ] ; + local missing-top = [ set.difference $(.all-top-features) : $(properties:G) ] ; local more = [ defaults $(missing-top) ] ; - properties += $(more) ; - xproperties += $(more) ; - # Add defaults for subfeatures of features which are present. - for local p in $(xproperties) + # This is similar to property.refine, except that it + # does not remove subfeatures, because we might be adding + # the default value of a subfeature. + local to-remove ; + for local f in $(properties:G) { - local s = $($(p:G).subfeatures) ; - local f = [ utility.ungrist $(p:G) ] ; - local missing-subs = [ set.difference <$(f)-$(s)> : $(properties:G) ] ; - properties += [ defaults [ select-subfeatures $(p) : $(missing-subs) ] ] ; + if ! free in [ attributes $(f) ] + { + to-remove += $(f) ; + } } - return $(properties) ; + local worklist = $(properties) ; + local expanded-from-composite ; + local to-expand = $(more) ; + while $(worklist) + { + # Add defaults for subfeatures of features which are present. + for local p in $(worklist) + { + local s = $($(p:G).subfeatures) ; + local f = [ utility.ungrist $(p:G) ] ; + local missing-subs = [ set.difference <$(f)-$(s)> : $(properties:G) ] ; + local sd = [ defaults [ select-subfeatures $(p) : $(missing-subs) ] ] ; + to-expand += $(sd) ; + } + worklist = ; + + # Expand subfeatures of newly added properties + for local m in [ sequence.transform expand-composite : $(to-expand) ] + { + if ! $(m:G) in $(to-remove) + { + local att = [ attributes $(m:G) ] ; + if $(m:G) in $(expanded-from-composite) && + ! free in $(att) && + ! $(m) in $(more) + { + import errors ; + errors.error "default values for $(p:G) conflict" ; + } + if ! $(m) in $(to-expand) + { + expanded-from-composite += $(m:G) ; + } + more += $(m) ; + if ! subfeature in $(att) && ! free in $(att) + { + worklist += $(m) ; + } + } + } + to-expand = ; + } + + return [ sequence.unique $(properties) $(more) ] ; } @@ -1233,17 +1274,18 @@ rule __test__ ( ) assert.result optional : attributes ; - assert.result static foobar on - gcc:FOO gcc debug native - dummy1 2.95.2 - : add-defaults static foobar on - gcc:FOO ; + assert.result [ SORT _DEBUG static + foobar on + gcc debug native + dummy1 2.95.2 ] + : add-defaults static foobar on ; - assert.result static foobar on - gcc:FOO fu1 gcc debug - native dummy1 q 2.95.2 + assert.result [ SORT _DEBUG static + foobar on + fu1 gcc debug + native dummy1 q 2.95.2 ] : add-defaults static foobar on - gcc:FOO fu1 ; + fu1 ; set-default : static ; assert.result static : defaults ; diff --git a/src/build/property.jam b/src/build/property.jam index 78a9744b1..e583071ad 100644 --- a/src/build/property.jam +++ b/src/build/property.jam @@ -28,8 +28,20 @@ rule refine ( properties * : requirements * ) for local r in $(requirements) { # Do not consider conditional requirements. - if ! [ MATCH (:) : $(r:G=) ] && ! free in [ feature.attributes $(r:G) ] + if ! [ MATCH (:<) : $(r:G=) ] && ! free in [ feature.attributes $(r:G) ] { + if ! $(r) in $(properties) + { + # Kill subfeatures of properties that we're changing + local sub = [ modules.peek feature : $(r:G).subfeatures ] ; + if $(sub) + { + # non-specific subfeatures are still valid + sub = [ MATCH "(.*:.*)" : $(sub) ] ; + local name = [ utility.ungrist $(r:G) ] ; + unset += <$(name)-$(sub)> ; + } + } unset += $(r:G) ; } } @@ -37,7 +49,7 @@ rule refine ( properties * : requirements * ) # Remove properties that are overridden by requirements for local p in $(properties) { - if [ MATCH (:) : $(p:G=) ] || ! $(p:G) in $(unset) + if [ MATCH (:<) : $(p:G=) ] || ! $(p:G) in $(unset) { result += $(p) ; } diff --git a/src/build/targets.jam b/src/build/targets.jam index 16caaa814..f7f1f116f 100644 --- a/src/build/targets.jam +++ b/src/build/targets.jam @@ -734,10 +734,6 @@ class main-target : abstract-target { start-building $(__name__) ; - # We want composite properties in the build request to act as if all the - # properties they expand to have been explicitly specified. - property-set = [ $(property-set).expand ] ; - local all-property-sets = [ apply-default-build $(property-set) ] ; local usage-requirements = [ property-set.empty ] ; local result ; @@ -901,8 +897,10 @@ rule apply-default-build ( property-set : default-build ) # 1. First, see what properties from default-build are already present in # property-set. + local expanded = [ $(property-set).expand ] ; local raw = [ $(property-set).raw ] ; - local specified-features = $(raw:G) ; + local specified-features = [ $(expanded).raw ] ; + specified-features = $(specified-features:G) ; local defaults-to-apply ; for local d in [ $(default-build).raw ] @@ -936,7 +934,7 @@ rule apply-default-build ( property-set : default-build ) for local p in $(properties) { result += [ property-set.create - [ feature.expand [ feature.split $(p) ] ] ] ; + [ feature.split $(p) ] ] ; } } else @@ -1042,6 +1040,10 @@ rule evaluate-requirements ( requirements : context : what ) local ok ; while $(count) { + # We need to expand composites here so that the requirements can + # safely override composite features. + current = [ feature.expand-composites $(current) ] ; + current = [ feature.add-defaults $(current) ] ; # Evaluate conditionals in context of current properties. local e = [ property.evaluate-conditionals-in-context $(conditionals) : $(current) ] ; @@ -1095,19 +1097,6 @@ rule evaluate-requirements ( requirements : context : what ) rule common-properties2 ( build-request requirements ) { - # This guarantees that default properties are present in the result, unless - # they are overriden by some requirement. FIXME: There is a possibility that - # we have added bar, which is composite and expands to bar2, but - # default value of is not bar2, in which case it is not clear what to - # do. - # - build-request = [ $(build-request).add-defaults ] ; - # Features added by 'add-defaults' can be composite and expand to features - # without default values -- which therefore have not been added yet. It - # could be clearer/faster to expand only newly added properties but that is - # not critical. - build-request = [ $(build-request).expand ] ; - return [ evaluate-requirements $(requirements) : $(build-request) : refined ] ; } @@ -1214,9 +1203,9 @@ class basic-target : abstract-target # rule match ( property-set debug ? ) { - # The condition is composed of all base non-conditional properties. It - # is not clear if we should expand 'self.requirements' or not. For one - # thing, it would be nice to be able to put + # The condition is composed of all base non-conditional properties. We + # only expand subfeatures in the condition. We do not expand + # composites. We want to be able to put # msvc-6.0 # in requirements. On the other hand, if we have release as a # condition it does not make sense to require full to be @@ -1224,6 +1213,7 @@ class basic-target : abstract-target local bcondition = [ $(self.requirements).base ] ; local ccondition = [ $(self.requirements).conditional ] ; local condition = [ set.difference $(bcondition) : $(ccondition) ] ; + condition = [ feature.expand-subfeatures $(condition) : unchecked ] ; if $(debug) { ECHO " next alternative: required properties:" @@ -1294,7 +1284,7 @@ class basic-target : abstract-target # define=FOO # he most likely wants this define to be set for all compiles. # Make it before check for already built. - property-set = [ $(property-set).refine + property-set = [ $(property-set).add [ build-system.command-line-free-features ] ] ; if ! $(self.generated.$(property-set)) diff --git a/test/alternatives.py b/test/alternatives.py index e8f9220ff..7a52427d2 100644 --- a/test/alternatives.py +++ b/test/alternatives.py @@ -88,7 +88,7 @@ exe a : a_empty.cpp ; exe a : a.cpp ; """) t.run_build_system(["--no-error-backtrace"], status=None) -t.fail_test(string.find(t.stdout(), "No best alternative") == -1) +t.expect_output_lines("error: No best alternative for ./a") # Another ambiguity test: two matches properties in one alternative are neither # better nor worse than a single one in another alternative. @@ -98,7 +98,8 @@ exe a : a.cpp : on ; """) t.run_build_system(["--no-error-backtrace"], status=None) -t.fail_test(string.find(t.stdout(), "No best alternative") == -1) +t.expect_output_lines("error: No best alternative for ./a") +t.rm("bin") # Test that we can have alternative without sources. t.write("jamfile.jam", """\ @@ -108,7 +109,21 @@ feature.extend os : MAGIC ; alias specific-sources : b.cpp : MAGIC ; exe a : a.cpp specific-sources ; """) -t.rm("bin") t.run_build_system() +t.expect_addition("bin/$toolset/debug*/a.exe") +t.rm("bin") + +# Test that subfeatures are expanded in alternatives +# and that unknown subfeatures fail to match instead of +# causing errors. +t.write("jamfile.jam", """\ +import feature : feature subfeature ; +feature X : off on : propagated ; +subfeature X on : version : 1 : propagated ; +exe a : a.cpp : on-1 ; +exe a : a_empty.cpp ; +exe a : a_empty.cpp : on-2 ; +""") +t.run_build_system(["X=on-1"]) t.cleanup() diff --git a/test/expansion.py b/test/expansion.py index c5bd30379..ed8690312 100644 --- a/test/expansion.py +++ b/test/expansion.py @@ -16,7 +16,7 @@ int main() {} """) t.write("b.cpp", """ -#ifdef CF_1 +#if defined(CF_1) && !defined(CF_IS_OFF) int main() {} #endif """) @@ -27,6 +27,36 @@ int main() {} #endif """) +t.write("d.cpp", """ +#ifndef CF_IS_OFF +int main() {} +#endif +""") + +t.write("e.cpp", """ +#if !defined(CF_IS_OFF) && defined(CF_2) && !defined(CF_1) +int main() {} +#endif +""") + +t.write("f.cpp", """ +#if defined(CF_1) +int main() {} +#endif +""") + +t.write("g.cpp", """ +#if defined(FOPT_2) +int main() {} +#endif +""") + +t.write("h.cpp", """ +#if defined(CX_2) +int main() {} +#endif +""") + t.write("jamfile.jam", """ # See if default value of composite feature 'cf' will be expanded to # CF_IS_OFF. @@ -38,14 +68,45 @@ exe b : b.cpp : on-1 ; # See if conditional requirements are recursively expanded. exe c : c.cpp : $toolset:release release:FOO ; + +# Composites specified in the default build should not +# be expanded if they are overridden in the the requirements. +exe d : d.cpp : on : off ; + +# Overriding a feature should clear subfeatures and +# apply default values of subfeatures. +exe e : e.cpp : always : on-1 ; + +# Subfeatures should not be changed if the parent feature doesn't change +exe f : f.cpp : on : on-1 ; + +# If a subfeature is not specific to the value of the parent feature, +# then changing the parent value should not clear the subfeature. +exe g : g.cpp : off : on-2 ; + +# If the default value of a composite feature adds an optional +# feature which has a subfeature with a default, then that +# default should be added. +exe h : h.cpp ; """) t.write("jamroot.jam", """ import feature ; -feature.feature cf : off on : composite incidental ; +feature.feature cf : off on always : composite incidental ; feature.compose off : CF_IS_OFF ; feature.subfeature cf on : version : 1 2 : composite optional incidental ; feature.compose 1 : CF_1 ; +feature.subfeature cf always : version : 1 2 : composite incidental ; +feature.compose 1 : CF_2 ; +feature.feature fopt : on off : optional incidental ; +feature.subfeature fopt : version : 1 2 : composite incidental ; +feature.compose 2 : FOPT_2 ; + +feature.feature cx1 : on : composite incidental ; +feature.feature cx2 : on : optional incidental ; +feature.subfeature cx2 on : sub : 1 : composite incidental ; +feature.compose on : on ; +feature.compose 1 : CX_2 ; """) t.expand_toolset("jamfile.jam") @@ -53,7 +114,12 @@ t.expand_toolset("jamfile.jam") t.run_build_system() t.expect_addition(["bin/$toolset/debug*/a.exe", "bin/$toolset/debug*/b.exe", - "bin/$toolset/release*/c.exe"]) + "bin/$toolset/release*/c.exe", + "bin/$toolset/debug*/d.exe", + "bin/$toolset/debug*/e.exe", + "bin/$toolset/debug*/f.exe", + "bin/$toolset/debug*/g.exe", + "bin/$toolset/debug*/h.exe"]) t.rm("bin") From e5d385d390710671f31165bf3acb62f09a35323d Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 6 Jan 2018 16:01:36 -0700 Subject: [PATCH 55/72] Rework handling of indirect conditionals. * property-set now considers to be conditional * property.evaluate-conditionals-in-context now handles indirect conditionals as well. This is the correct behavior for all places where evaluate-conditionals-in-context is currently used. * Indirect conditionals now translate paths relative to the project in which they were defined, not relative to the current project. * usage-requirements no longer use targets.evaluate-requirements, as the iterative algorithm is completely unnecessary (It's also wrong, since the new features shouldn't be applied to the evaluation context). * indirect conditionals are removed from the property set when they are evaluated, just list regular conditionals. (This is a consequence of passing them through evaluate-conditionals-in-context) * This also allows non-free features in usage-requirements to "work" again (for some definition of work). --- src/build/project.jam | 4 ++-- src/build/property-set.jam | 2 +- src/build/property.jam | 23 +++++++++++++++++++ src/build/targets.jam | 45 +++++++------------------------------- test/path_features.py | 15 +++++++++++-- 5 files changed, 47 insertions(+), 42 deletions(-) diff --git a/src/build/project.jam b/src/build/project.jam index e8834b421..d02240a4f 100644 --- a/src/build/project.jam +++ b/src/build/project.jam @@ -900,9 +900,9 @@ rule get-jamroot-module ( project ) # Returns the project target corresponding to the 'project-module'. # -rule target ( project-module ) +rule target ( project-module : allow-missing ? ) { - if ! $(.target.$(project-module)) + if ! $(.target.$(project-module)) && ! $(allow-missing) { import errors ; errors.user-error Project target requested but not yet assigned for diff --git a/src/build/property-set.jam b/src/build/property-set.jam index 55cb55645..feb4fb42e 100644 --- a/src/build/property-set.jam +++ b/src/build/property-set.jam @@ -369,7 +369,7 @@ class property-set # characters as well, e.g. free or indirect properties. Indirect # properties for example contain a full Jamfile path in their value # which on Windows file systems contains ':' as the drive separator. - if [ MATCH (:) : $(p:G=) ] + if [ MATCH (:) : $(p:G=) ] || $(p:G) = { self.conditional += $(p) ; } diff --git a/src/build/property.jam b/src/build/property.jam index e583071ad..4be08eeb7 100644 --- a/src/build/property.jam +++ b/src/build/property.jam @@ -67,12 +67,17 @@ rule evaluate-conditionals-in-context ( properties * : context * ) { local base ; local conditionals ; + local indirect ; for local p in $(properties) { if [ MATCH (:<) : $(p) ] { conditionals += $(p) ; } + else if $(p:G) = + { + indirect += $(p) ; + } else { base += $(p) ; @@ -128,6 +133,24 @@ rule evaluate-conditionals-in-context ( properties * : context * ) } } } + # Import here to avoid cyclic dependency + import project ; + for local i in [ MATCH "^@(.*)" : $(indirect:G=) ] + { + # If the rule was set in a project module, translate paths + # relative to that project's location. + local m = [ indirect.get-module $(i) ] ; + local p = [ project.target $(m) : allow-missing ] ; + local new = [ indirect.call $(i) $(context) ] ; + if $(p) && [ $(p).location ] + { + result += [ translate-paths $(new) : [ $(p).location ] ] ; + } + else + { + result += $(new) ; + } + } return $(result) ; } diff --git a/src/build/targets.jam b/src/build/targets.jam index f7f1f116f..0964b0d86 100644 --- a/src/build/targets.jam +++ b/src/build/targets.jam @@ -991,7 +991,7 @@ rule common-properties ( build-request requirements ) # If 'what' is 'refined' returns context refined with new requirements. If # 'what' is 'added' returns just the requirements to be applied. # -rule evaluate-requirements ( requirements : context : what ) +rule evaluate-requirements ( requirements : context ) { # Apply non-conditional requirements. It is possible that further # conditional requirement change a value set by non-conditional @@ -1017,26 +1017,18 @@ rule evaluate-requirements ( requirements : context : what ) local conditionals = [ $(requirements).conditional ] ; # The 'count' variable has one element for each conditional feature and for - # each occurrence of '' feature. It is used as a loop + # each occurrence of '' feature. It is used as a loop # counter: for each iteration of the loop before we remove one element and # the property set should stabilize before we are done. It is assumed that # #conditionals iterations should be enough for properties to propagate # along conditions in any direction. - local count = $(conditionals) [ $(requirements).get ] + local count = $(conditionals) and-once-more ; local added-requirements ; local current = $(raw) ; - # It is assumed that ordinary conditional requirements can not add - # properties (a.k.a. indirect conditional properties), and - # that rules referred to by properties can not add new - # properties. So the list of indirect conditionals does not - # change. - local indirect = [ $(requirements).get ] ; - indirect = [ MATCH ^@(.*) : $(indirect) ] ; - local ok ; while $(count) { @@ -1048,15 +1040,6 @@ rule evaluate-requirements ( requirements : context : what ) local e = [ property.evaluate-conditionals-in-context $(conditionals) : $(current) ] ; - # Evaluate indirect conditionals. - for local i in $(indirect) - { - local t = [ current ] ; - local p = [ $(t).project ] ; - local new = [ indirect.call $(i) $(current) ] ; - e += [ property.translate-paths $(new) : [ $(p).location ] ] ; - } - if $(e) = $(added-requirements) { # If we got the same result, we have found the final properties. @@ -1079,26 +1062,13 @@ rule evaluate-requirements ( requirements : context : what ) errors.error Can not evaluate conditional properties $(conditionals) ; } - if $(what) = added - { - return [ property-set.create $(unconditional) $(added-requirements) ] ; - } - else if $(what) = refined - { - return [ property-set.create $(current) ] ; - } - else - { - import errors ; - errors.error "Invalid value of the 'what' parameter." ; - } + return [ property-set.create $(current) ] ; } rule common-properties2 ( build-request requirements ) { - return [ evaluate-requirements $(requirements) : $(build-request) : - refined ] ; + return [ evaluate-requirements $(requirements) : $(build-request) ] ; } @@ -1435,8 +1405,9 @@ class basic-target : abstract-target rule compute-usage-requirements ( subvariant ) { local rproperties = [ $(subvariant).build-properties ] ; - xusage-requirements = [ targets.evaluate-requirements - $(self.usage-requirements) : $(rproperties) : added ] ; + xusage-requirements = + [ $(self.usage-requirements).evaluate-conditionals + $(rproperties) ] ; # We generate all dependency properties and add them, as well as their # usage requirements, to the result. diff --git a/test/path_features.py b/test/path_features.py index b43b86d4c..5b23150be 100644 --- a/test/path_features.py +++ b/test/path_features.py @@ -100,7 +100,16 @@ def test_paths_set_by_indirect_conditionals(): header = "child_dir/folder_to_include/some_header.h" - t.write("jamroot.jam", "build-project child_dir ;") + t.write("jamroot.jam", """ +build-project child_dir ; +rule attach-include-parent ( properties * ) +{ + return another_folder ; +} +# requirements inherited from a parent project will bind paths +# relative to the project that actually names the rule. +project : requirements @attach-include-parent ; +""") t.write("child_dir/jamfile.jam", """\ import remote/remote ; @@ -121,9 +130,11 @@ rule attach-include-remote ( properties * ) """) t.write("child_dir/x.cpp", """\ #include +#include int main() {} """) t.write(header, "int some_func();\n") + t.write("another_folder/header2.h", "int f2();\n") t.write("child_dir/folder_to_include/jamfile.jam", "") expected_x1 = "child_dir/bin/$toolset/debug*/x1.obj" @@ -149,4 +160,4 @@ int main() {} test_basic() test_absolute_paths() test_ordered_paths() -test_paths_set_by_indirect_conditionals() \ No newline at end of file +test_paths_set_by_indirect_conditionals() From 429081e45e51dd4910c5d69ec8072d1b13804c48 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Mon, 8 Jan 2018 15:56:53 -0700 Subject: [PATCH 56/72] expect_content inadvertently ignored the first element. --- test/BoostBuild.py | 2 +- test/project_test3.py | 16 ++++++++-------- test/project_test4.py | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/test/BoostBuild.py b/test/BoostBuild.py index 9f66c39d7..e7ed1c3ed 100644 --- a/test/BoostBuild.py +++ b/test/BoostBuild.py @@ -773,7 +773,7 @@ class Tester(TestCmd.TestCmd): lambda x, y: x and reduce( lambda a, b: a and b, y), - matched) + matched, True) if not matched: print "Expected:\n" diff --git a/test/project_test3.py b/test/project_test3.py index 82b238f68..ddd24e848 100644 --- a/test/project_test3.py +++ b/test/project_test3.py @@ -24,7 +24,7 @@ t.run_build_system() t.expect_addition("bin/$toolset/debug*/a.obj") t.expect_content("bin/$toolset/debug*/a.obj", """\ -$toolset/debug +$toolset/debug* a.cpp """) @@ -39,43 +39,43 @@ t.expect_content("bin/$toolset/debug*/a.exe", t.expect_addition("lib/bin/$toolset/debug*/b.obj") t.expect_content("lib/bin/$toolset/debug*/b.obj", """\ -$toolset/debug +$toolset/debug* lib/b.cpp """) t.expect_addition("lib/bin/$toolset/debug*/m.exe") t.expect_content("lib/bin/$toolset/debug*/m.exe", """\ -$toolset/debug +$toolset/debug* lib/bin/$toolset/debug*/b.obj lib2/bin/$toolset/debug*/c.obj """) t.expect_addition("lib2/bin/$toolset/debug*/c.obj") t.expect_content("lib2/bin/$toolset/debug*/c.obj", """\ -$toolset/debug +$toolset/debug* lib2/c.cpp """) t.expect_addition("lib2/bin/$toolset/debug*/d.obj") t.expect_content("lib2/bin/$toolset/debug*/d.obj", """\ -$toolset/debug +$toolset/debug* lib2/d.cpp """) t.expect_addition("lib2/bin/$toolset/debug*/l.exe") t.expect_content("lib2/bin/$toolset/debug*/l.exe", """\ -$toolset/debug +$toolset/debug* lib2/bin/$toolset/debug*/c.obj bin/$toolset/debug*/a.obj """) t.expect_addition("lib2/helper/bin/$toolset/debug*/e.obj") t.expect_content("lib2/helper/bin/$toolset/debug*/e.obj", """\ -$toolset/debug +$toolset/debug* lib2/helper/e.cpp """) t.expect_addition("lib3/bin/$toolset/debug*/f.obj") t.expect_content("lib3/bin/$toolset/debug*/f.obj", """\ -$toolset/debug +$toolset/debug* lib3/f.cpp lib2/helper/bin/$toolset/debug*/e.obj """) diff --git a/test/project_test4.py b/test/project_test4.py index ee12c4d91..30aabacce 100644 --- a/test/project_test4.py +++ b/test/project_test4.py @@ -16,13 +16,13 @@ t.run_build_system() t.expect_addition("bin/$toolset/debug*/a.obj") t.expect_content("bin/$toolset/debug*/a.obj", -"""$toolset/debug*/include-everything +"""$toolset/debug*/include-everything* a.cpp """) t.expect_addition("bin/$toolset/debug*/a.exe") t.expect_content("bin/$toolset/debug*/a.exe", -"$toolset/debug*/include-everything\n" + +"$toolset/debug*/include-everything*\n" + "bin/$toolset/debug*/a.obj lib/bin/$toolset/debug/optimization-speed*/b.obj\n" ) From 6244e5ad21aac77f53d06c0747c41ba7ac0ec493 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Mon, 8 Jan 2018 17:01:32 -0700 Subject: [PATCH 57/72] Add specific tests for the processing of properties on the command line. * Fix problems in x-product that could make it return extra property-sets in complex cases. Also clarify exactly what it is supposed to do. * free_features_request.py: This is subsumed by the new test. * direct_request_test.py: This is mostly subsumed by the new test except for the last test for chained build-projects, which doesn't make much sense in the current code base as build-project is implemented very differently. * Document using / to separate properties. --- doc/src/overview.xml | 6 ++ src/build/build-request.jam | 55 ++++++++++-- test/command_line_properties.py | 150 ++++++++++++++++++++++++++++++++ test/direct_request_test.py | 68 --------------- test/free_features_request.py | 42 --------- test/test_all.py | 3 +- 6 files changed, 206 insertions(+), 118 deletions(-) create mode 100644 test/command_line_properties.py delete mode 100644 test/direct_request_test.py delete mode 100644 test/free_features_request.py diff --git a/doc/src/overview.xml b/doc/src/overview.xml index 44fc2e8fd..b5501d351 100644 --- a/doc/src/overview.xml +++ b/doc/src/overview.xml @@ -1021,6 +1021,12 @@ b2 include=static,shared is not treated specially. + Multiple features may be grouped by using a forwards slash. + +b2 gcc/link=shared msvc/link=static,shared + + This will build 3 different variants, altogether. +
diff --git a/src/build/build-request.jam b/src/build/build-request.jam index 3110713b7..4c767c3b2 100644 --- a/src/build/build-request.jam +++ b/src/build/build-request.jam @@ -38,6 +38,23 @@ rule expand-no-defaults ( property-sets * ) } +# Update the list of expected conflicts based on the new +# features. +# +local rule remove-conflicts ( conflicts * : features * ) +{ + local result ; + for local c in $(conflicts) + { + if ! [ set.intersection [ regex.split $(c) "/" ] : $(features) ] + { + result += $(c) ; + } + } + return $(result) ; +} + + # Implementation of x-product, below. Expects all the project files to already # be loaded. # @@ -47,36 +64,54 @@ local rule x-product-aux ( property-sets + ) local p = [ feature.split $(property-sets[1]) ] ; local f = [ set.difference $(p:G) : [ feature.free-features ] ] ; local seen ; + local extra-conflicts ; + # No conflict with things used at a higher level? if ! [ set.intersection $(f) : $(x-product-used) ] { local x-product-seen ; + local x-product-conflicts = + [ remove-conflicts $(x-product-conflicts) : $(f) ] ; { # Do not mix in any conflicting features. local x-product-used = $(x-product-used) $(f) ; if $(property-sets[2]) { - local rest = [ x-product-aux $(property-sets[2-]) : $(feature-space) ] ; + local rest = [ x-product-aux $(property-sets[2-]) ] ; result = $(property-sets[1])/$(rest) ; } - - result ?= $(property-sets[1]) ; + if ! $(x-product-conflicts) + { + result ?= $(property-sets[1]) ; + } } # If we did not encounter a conflicting feature lower down, do not # recurse again. - if ! [ set.intersection $(f) : $(x-product-seen) ] + if ! [ set.intersection $(f) : $(x-product-seen) ] + || [ remove-conflicts $(x-product-conflicts) : $(x-product-seen) ] { property-sets = ; } + else + { + # A property is only allowed to be absent if it conflicts + # with either a higher or lower layer. We don't need to + # bother setting this if we already know that we don't need + # to recurse again. + extra-conflicts = $(f:J=/) ; + } seen = $(x-product-seen) ; } if $(property-sets[2]) { - result += [ x-product-aux $(property-sets[2-]) : $(feature-space) ] ; + # Lower layers expansion must conflict with this + local x-product-conflicts = $(x-product-conflicts) $(extra-conflicts) ; + + result += [ x-product-aux $(property-sets[2-]) ] ; } # Note that we have seen these features so that higher levels will recurse @@ -90,13 +125,21 @@ local rule x-product-aux ( property-sets + ) # contain conflicting values for single-valued features. Expects all the project # files to already be loaded. # +# Formal definition: +# Returns all maximum non-conflicting subsets of property-sets. +# The result is a list of all property-sets p such that +# 1. p is composed by joining a subset of property-sets without removing +# duplicates +# 2. p contains at most one instance of every single-valued feature +# 3. Adding any additional element of property-sets to p be would +# violate (2) local rule x-product ( property-sets * ) { if $(property-sets).non-empty { # Prepare some "scoped globals" that can be used by the implementation # function, x-product-aux. - local x-product-seen x-product-used ; + local x-product-seen x-product-used x-product-conflicts ; return [ x-product-aux $(property-sets) : $(feature-space) ] ; } # Otherwise return empty. diff --git a/test/command_line_properties.py b/test/command_line_properties.py new file mode 100644 index 000000000..938ec52fb --- /dev/null +++ b/test/command_line_properties.py @@ -0,0 +1,150 @@ +#!/usr/bin/python + +import BoostBuild + +def test_basic(): + '''Tests that feature=value works''' + t = BoostBuild.Tester() + t.write('Jamroot.jam', ''' + import feature : feature ; + import toolset : flags ; + feature f1 : 1 2 ; + make output.txt : : @run ; + flags run OPTIONS ; + actions run { echo $(OPTIONS) > $(<) } + ''') + t.run_build_system(['f1=2']) + t.expect_content("bin/*/output.txt", "2") + t.cleanup() + +def test_implicit(): + '''Tests that implicit features can be named without a feature''' + t = BoostBuild.Tester() + t.write('Jamroot.jam', ''' + import feature : feature ; + import toolset : flags ; + feature f1 : v1 v2 : implicit ; + make output.txt : : @run ; + flags run OPTIONS ; + actions run { echo $(OPTIONS) > $(<) } + ''') + t.run_build_system(['v2']) + t.expect_content("bin/*/output.txt", "v2") + t.cleanup() + +def test_free(): + '''Free features named on the command line apply to all targets + everywhere. Free features can contain any characters, even those + that have a special meaning.''' + t = BoostBuild.Tester() + t.write('Jamroot.jam', ''' + import feature : feature ; + import toolset : flags ; + feature f1 : : free ; + make output1.txt : : @run : output2.txt ; + make output2.txt : : @run ; + explicit output2.txt ; + flags run OPTIONS ; + actions run { echo $(OPTIONS) > $(<) } + ''') + t.run_build_system(['f1=x,/:-']) + t.expect_content("bin/*/output1.txt", "x,/:-") + t.expect_content("bin/*/output2.txt", "x,/:-") + t.cleanup() + +def test_subfeature(): + '''Subfeatures should be expressed as feature=value-subvalue''' + t = BoostBuild.Tester() + t.write('Jamroot.jam', ''' + import feature : feature subfeature ; + import toolset : flags ; + feature f1 : 1 2 ; + subfeature f1 2 : sub : x y ; + make output.txt : : @run ; + flags run OPTIONS ; + actions run { echo $(OPTIONS) > $(<) } + ''') + t.run_build_system(['f1=2-y']) + t.expect_content("bin/*/output.txt", "y") + t.cleanup() + +def test_multiple_values(): + '''Multiple values of a feature can be given in a comma-separated list''' + t = BoostBuild.Tester() + t.write('Jamroot.jam', ''' + import feature : feature ; + import toolset : flags ; + feature f1 : 1 2 3 ; + make output.txt : : @run ; + flags run OPTIONS ; + actions run { echo $(OPTIONS) > $(<) } + ''') + t.run_build_system(['f1=2,3']) + t.expect_content("bin*/f1-2*/output.txt", "2") + t.expect_content("bin*/f1-3*/output.txt", "3") + t.cleanup() + +def test_multiple_properties(): + '''Multiple properties can be grouped with /''' + t = BoostBuild.Tester() + t.write('Jamroot.jam', ''' + import feature : feature ; + import toolset : flags ; + feature f1 : 1 2 ; + feature f2 : 3 4 ; + make output.txt : : @run ; + flags run OPTIONS ; + flags run OPTIONS ; + actions run { echo $(OPTIONS) > $(<) } + ''') + t.run_build_system(['f1=2/f2=4']) + t.expect_content("bin/*/output.txt", "2 4") + t.cleanup() + +def test_cross_product(): + '''If multiple properties are specified on the command line + we expand to every possible maximum set of non-conflicting features. + This test should be run after testing individual components in + isolation.''' + t = BoostBuild.Tester() + t.write('Jamroot.jam', ''' + import feature : feature ; + import toolset : flags ; + # Make features symmetric to make the paths easier to distingush + feature f1 : 11 12 13 14 15 : symmetric ; + feature f2 : 21 22 23 : symmetric ; + feature f3 : v1 v2 v3 v4 : implicit symmetric ; + feature f4 : : free ; + make output.txt : : @run ; + flags run OPTIONS ; + flags run OPTIONS ; + flags run OPTIONS ; + flags run OPTIONS ; + actions run { echo $(OPTIONS) > $(<) } + ''') + t.run_build_system(['f1=12,13/f2=22', 'v2', 'v3', 'f1=14', 'f2=23', + 'f4=xxx', 'f4=yyy', 'v4/f1=15/f4=zzz']) + t.expect_content("bin*/v2*/f1-12/f2-22*/output.txt", "12 22 v2 xxx yyy") + t.expect_addition("bin*/v2*/f1-12/f2-22*/output.txt") + t.expect_content("bin*/v2*/f1-13/f2-22*/output.txt", "13 22 v2 xxx yyy") + t.expect_addition("bin*/v2*/f1-13/f2-22*/output.txt") + t.expect_content("bin*/v2*/f1-14/f2-23*/output.txt", "14 23 v2 xxx yyy") + t.expect_addition("bin*/v2*/f1-14/f2-23*/output.txt") + t.expect_content("bin*/v3*/f1-12/f2-22*/output.txt", "12 22 v3 xxx yyy") + t.expect_addition("bin*/v3*/f1-12/f2-22*/output.txt") + t.expect_content("bin*/v3*/f1-13/f2-22*/output.txt", "13 22 v3 xxx yyy") + t.expect_addition("bin*/v3*/f1-13/f2-22*/output.txt") + t.expect_content("bin*/v3*/f1-14/f2-23*/output.txt", "14 23 v3 xxx yyy") + t.expect_addition("bin*/v3*/f1-14/f2-23*/output.txt") + t.expect_content("bin*/v4*/f1-15/f2-23*/output.txt", "15 23 v4 xxx yyy zzz") + t.expect_addition("bin*/v4*/f1-15/f2-23*/output.txt") + t.expect_nothing_more() + t.cleanup() + +test_basic() +test_implicit() +test_free() +test_subfeature() +test_multiple_values() +test_multiple_properties() +test_cross_product() diff --git a/test/direct_request_test.py b/test/direct_request_test.py deleted file mode 100644 index 422276938..000000000 --- a/test/direct_request_test.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/python - -import BoostBuild - -t = BoostBuild.Tester(use_test_config=False) - -# First check some startup. - -t.write("jamroot.jam", "") -t.write("jamfile.jam", """\ -exe a : a.cpp b ; -lib b : b.cpp ; -""") - -t.write("a.cpp", """\ -void -# ifdef _WIN32 -__declspec(dllimport) -# endif -foo(); -int main() { foo(); } -""") - -t.write("b.cpp", """\ -#ifdef MACROS -void -# ifdef _WIN32 -__declspec(dllexport) -# endif -foo() {} -#endif - -# ifdef _WIN32 -int __declspec(dllexport) force_implib_creation; -# endif -""") - -t.run_build_system(["define=MACROS"]) -t.expect_addition("bin/$toolset/debug*/" - * (BoostBuild.List("a.obj b.obj b.dll a.exe"))) - - -# When building a debug version, the 'define' still applies. -t.rm("bin") -t.run_build_system(["debug", "define=MACROS"]) -t.expect_addition("bin/$toolset/debug*/" - * (BoostBuild.List("a.obj b.obj b.dll a.exe"))) - - -# When building a release version, the 'define' still applies. -t.write("jamfile.jam", """\ -exe a : a.cpp b : debug ; -lib b : b.cpp ; -""") -t.rm("bin") -t.run_build_system(["release", "define=MACROS"]) - - -# Regression test: direct build request was not working when there was more -# than one level of 'build-project'. -t.rm(".") -t.write("jamroot.jam", "") -t.write("jamfile.jam", "build-project a ;") -t.write("a/jamfile.jam", "build-project b ;") -t.write("a/b/jamfile.jam", "") -t.run_build_system(["release"]) - -t.cleanup() diff --git a/test/free_features_request.py b/test/free_features_request.py deleted file mode 100644 index c6bb4e9d6..000000000 --- a/test/free_features_request.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/python - -# Copyright (C) Vladimir Prus 2007. -# Distributed under the Boost Software License, Version 1.0. (See -# accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -# Tests that a free feature specified on the command line applies to all -# targets ever built. - -import BoostBuild - -t = BoostBuild.Tester(use_test_config=False) - -t.write("jamroot.jam", """\ -exe hello : hello.cpp foo ; -lib foo : foo.cpp ; -""") - -t.write("hello.cpp", """\ -extern void foo(); -#ifdef FOO -int main() { foo(); } -#endif -""") - -t.write("foo.cpp", """\ -#ifdef FOO -#ifdef _WIN32 -__declspec(dllexport) -#endif -void foo() {} -#endif -""") - -# If FOO is not defined when compiling the 'foo' target, we will get a link -# error at this point. -t.run_build_system(["hello", "define=FOO"]) - -t.expect_addition("bin/$toolset/debug*/hello.exe") - -t.cleanup() diff --git a/test/test_all.py b/test/test_all.py index 78aba01d0..38255d967 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -176,6 +176,7 @@ tests = ["absolute_sources", "c_file", "chain", "clean", + "command_line_properties", "composite", "conditionals", "conditionals2", @@ -211,7 +212,6 @@ tests = ["absolute_sources", # "default_toolset", "dependency_property", "dependency_test", - "direct_request_test", "disambiguation", "dll_path", "double_loading", @@ -222,7 +222,6 @@ tests = ["absolute_sources", "expansion", "explicit", "feature_cxxflags", - "free_features_request", "generator_selection", "generators_test", "implicit_dependency", From 6c5735a06dd333a049db035e070f787cd4db7b66 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Mon, 8 Jan 2018 18:37:17 -0700 Subject: [PATCH 58/72] Add test for passing optional features on the command line. --- test/command_line_properties.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/command_line_properties.py b/test/command_line_properties.py index 938ec52fb..a69bf1282 100644 --- a/test/command_line_properties.py +++ b/test/command_line_properties.py @@ -32,6 +32,21 @@ def test_implicit(): t.expect_content("bin/*/output.txt", "v2") t.cleanup() +def test_optional(): + '''Tests that feature= works for optional features''' + t = BoostBuild.Tester() + t.write('Jamroot.jam', ''' + import feature : feature ; + import toolset : flags ; + feature f1 : 1 2 : optional ; + make output.txt : : @run ; + flags run OPTIONS ; + actions run { echo b $(OPTIONS) > $(<) } + ''') + t.run_build_system(['f1=']) + t.expect_content("bin/*/output.txt", "b") + t.cleanup() + def test_free(): '''Free features named on the command line apply to all targets everywhere. Free features can contain any characters, even those @@ -143,6 +158,7 @@ def test_cross_product(): test_basic() test_implicit() +test_optional() test_free() test_subfeature() test_multiple_values() From c4bfb6d2f72c8bfc50f367b61cd25f96a0445ae6 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Mon, 8 Jan 2018 19:15:46 -0700 Subject: [PATCH 59/72] Make mock-program compile in C++03 --- test/toolset-mock/src/mock-program.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/toolset-mock/src/mock-program.cpp b/test/toolset-mock/src/mock-program.cpp index 109e27503..62dd4b8a4 100644 --- a/test/toolset-mock/src/mock-program.cpp +++ b/test/toolset-mock/src/mock-program.cpp @@ -37,6 +37,6 @@ int main(int argc, char ** argv) args.push_back(script); args.insert(args.end(), argv + 1, argv + argc); args.push_back(NULL); - execv(python_cmd, args.data()); + execv(python_cmd, &args[0]); perror("exec"); } From c01182064e6e45ab650a81976ab1431ac88f533a Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Mon, 8 Jan 2018 19:52:41 -0700 Subject: [PATCH 60/72] Attempt to fix a couple tests with qcc. --- src/tools/qcc.jam | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tools/qcc.jam b/src/tools/qcc.jam index faa353064..9ed92465f 100644 --- a/src/tools/qcc.jam +++ b/src/tools/qcc.jam @@ -21,7 +21,6 @@ import unix ; feature.extend toolset : qcc ; toolset.inherit-generators qcc : unix : unix.link unix.link.dll ; -generators.override builtin.lib-generator : qcc.prebuilt ; toolset.inherit-flags qcc : unix ; toolset.inherit-rules qcc : unix ; @@ -101,7 +100,7 @@ actions compile.c++ actions compile.c { - "$(CONFIG_COMMAND)" $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" + "$(CONFIG_COMMAND)" -lang-c $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" } actions compile.asm From e35036609611e1a300991ca864a2d0c32c8d4e8a Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 9 Jan 2018 07:24:58 -0700 Subject: [PATCH 61/72] Add a Jamfile in the test directory which runs test_all.py. Refs #268. * python.jam: Allow run-pyd to work with just a python script. * BoostBuild.py: Adjust paths to work regardless of the current working directory. --- src/tools/python.jam | 2 +- test/BoostBuild.py | 7 ++++--- test/Jamfile.jam | 29 +++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 test/Jamfile.jam diff --git a/src/tools/python.jam b/src/tools/python.jam index 71feff689..c9f6f4c25 100644 --- a/src/tools/python.jam +++ b/src/tools/python.jam @@ -1272,7 +1272,7 @@ rule capture-output ( target : sources * : properties * ) } local path-separator = [ os.path-separator [ translate-os $(target-os) ] ] ; local set-PYTHONPATH = [ common.variable-setting-command PYTHONPATH : - $(PYTHONPATH:J=$(path-separator)) ] ; + $(PYTHONPATH:E=:J=$(path-separator)) ] ; LAUNCHER on $(target) = $(set-PYTHONPATH) [ on $(target) return \"$(PYTHON)\" ] ; } diff --git a/test/BoostBuild.py b/test/BoostBuild.py index e7ed1c3ed..e15fe6798 100644 --- a/test/BoostBuild.py +++ b/test/BoostBuild.py @@ -219,7 +219,7 @@ class Tester(TestCmd.TestCmd): **keywords): assert arguments.__class__ is not str - self.original_workdir = os.getcwd() + self.original_workdir = os.path.dirname(__file__) if workdir and not os.path.isabs(workdir): raise ("Parameter workdir <%s> must point to an absolute " "directory: " % workdir) @@ -280,8 +280,9 @@ class Tester(TestCmd.TestCmd): # Find where jam_src is located. Try for the debug version if it is # lying around. - dirs = [os.path.join("..", "src", "engine", jam_build_dir + ".debug"), - os.path.join("..", "src", "engine", jam_build_dir)] + srcdir = os.path.join(os.path.dirname(__file__), "..", "src") + dirs = [os.path.join(srcdir, "engine", jam_build_dir + ".debug"), + os.path.join(srcdir, "engine", jam_build_dir)] for d in dirs: if os.path.exists(d): jam_build_dir = d diff --git a/test/Jamfile.jam b/test/Jamfile.jam new file mode 100644 index 000000000..7ec0bf303 --- /dev/null +++ b/test/Jamfile.jam @@ -0,0 +1,29 @@ +# Copyright 2018 Steven Watanabe +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import python ; +import testing ; + +if ! [ python.configured ] +{ + using python ; +} + +# Not quite perfect, but good enough for most purposes +local test-files = [ glob *.py ] ; + +local boost-build-files = [ glob + ../src/tools/*.jam + ../src/tools/*/*.jam + ../src/build/*.jam + ../src/util/*.jam + ../src/kernel/*.jam + ../src/options/*.jam + ../src/*.jam ] ; + +testing.make-test run-pyd : test_all.py : + $(test-files) + $(boost-build-files) + ; From 6945dad0369db7d03a37d90ef62ef9119a389bae Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 9 Jan 2018 08:23:19 -0700 Subject: [PATCH 62/72] Added python tool examples. Contributed by Tom Kent. Fixes #171. --- doc/src/reference.xml | 116 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/doc/src/reference.xml b/doc/src/reference.xml index 24652f15f..8c45dfb05 100644 --- a/doc/src/reference.xml +++ b/doc/src/reference.xml @@ -1783,6 +1783,122 @@ using bzip2 : 1.0.6 : <source>C:/Devel/src/bzip2-1.0.6 : <toolset>ms using bzip2 : 1.0.6 : : <toolset>gcc ;
+ +
+ Python + Python + + Provides support for the + python language + environment to be linked in as a library. + + python can be initialized using the following syntax + +using python : version : command-or-prefix : includes : libraries : conditions : extension-suffix ; + + Options for using python: + + + version + + the version of Python to use. Should be in Major.Minor + format, for example 2.3. Do not include the subminor version. + + + + + command-or-prefix + + Preferably, a command that invokes a Python interpreter. + Alternatively, the installation prefix for Python libraries + and includes. If empty, will be guessed from the version, the + platform's installation patterns, and the python executables + that can be found in PATH. + + + + includes + + the include path to Python headers. If empty, will be + guessed. + + + + libraries + + the path to Python library binaries. If empty, will + be guessed. On MacOS/Darwin, you can also pass the path of the + Python framework. + + + + conditions + + if specified, should be a set of properties that are + matched against the build configuration when Boost.Build + selects a Python configuration to use. + + + + extension-suffix + + A string to append to the name of extension modules + before the true filename extension. Ordinarily we would just + compute this based on the value of the <python-debugging> + feature. However ubuntu's python-dbg package uses the windows + convention of appending _d to debug-build extension modules. We + have no way of detecting ubuntu, or of probing python for the + "_d" requirement, and if you configure and build python using + --with-pydebug, you'll be using the standard *nix convention. + Defaults to "" (or "_d" when targeting windows and + <python-debugging> is set). + + + + Examples: + +# Find python in the default system location +using python ; +# 2.7 +using python : 2.7 ; +# 3.5 +using python : 3.5 ; + +# On ubuntu 16.04 +using python +: 2.7 # version +: # Interpreter/path to dir +: /usr/include/python2.7 # includes +: /usr/lib/x86_64-linux-gnu # libs +: # conditions +; + +using python +: 3.5 # version +: # Interpreter/path to dir +: /usr/include/python3.5 # includes +: /usr/lib/x86_64-linux-gnu # libs +: # conditions +; + +# On windows +using python +: 2.7 # version +: C:\\Python27-32\\python.exe # Interperter/path to dir +: C:\\Python27-32\\include # includes +: C:\\Python27-32\\libs # libs +: <address-model>32 <address-model> # conditions - both 32 and unspecified +; + +using python +: 2.7 # version +: C:\\Python27-64\\python.exe # Interperter/path to dir +: C:\\Python27-64\\include # includes +: C:\\Python27-64\\libs # libs +: <address-model>64 # conditions +; + +
From f3133e945e909fa48cac55376f895d436c8a9a35 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Thu, 11 Jan 2018 13:57:53 -0700 Subject: [PATCH 63/72] Rework configuration file loading to be more consistent. Any configuration file can be set (or disabled) with --xxx-config=. --config= overrides all configuration files. --- doc/src/overview.xml | 34 ++++++++ src/build-system.jam | 185 +++++++++++++++++++++++++++++------------- src/build/project.jam | 4 +- test/configuration.py | 69 ++++++++++++++++ 4 files changed, 235 insertions(+), 57 deletions(-) diff --git a/doc/src/overview.xml b/doc/src/overview.xml index b5501d351..65aa966b0 100644 --- a/doc/src/overview.xml +++ b/doc/src/overview.xml @@ -449,6 +449,8 @@ actions create-file-from-another + Any of these files may also be overridden on the command line + You can use the --debug-configuration option to @@ -785,6 +787,38 @@ b2 toolset=gcc variant=debug optimization=space + + + + config + Override all configuration files + + + + + + + site-config.jam + Override the default site-config.jam + + + + + + + user-config.jam + Override the default user-config.jam + + + + + + + project-config.jam + Override the default project-config.jam + + + diff --git a/src/build-system.jam b/src/build-system.jam index a2f64f624..c111a2312 100644 --- a/src/build-system.jam +++ b/src/build-system.jam @@ -272,6 +272,35 @@ local rule load-config ( module-name : filename : path + : must-find ? ) return $(where) ; } +# Parses options of the form --xxx-config=path/to/config.jam +# and environmental variables of the form BOOST_BUILD_XXX_CONFIG. +# If not found, returns an empty list. The option may be +# explicitly set to the empty string, in which case, handle-config-option +# will return "". +# +local rule handle-config-option ( name : env ? ) +{ + local result = [ MATCH ^--$(name)=(.*)$ : $(.argv) ] ; + if ! $(result)-is-defined && $(env) + { + result = [ os.environ $(env) ] ; + } + # Special handling for the case when the OS does not strip the quotes + # around the file name, as is the case when using Cygwin bash. + result = [ utility.unquote $(result[-1]) ] ; + if ! $(result) + { + return $(result) ; + } + # Treat explicitly entered user paths as native OS path + # references and, if non-absolute, root them at the current + # working directory. + result = [ path.make $(result) ] ; + result = [ path.root $(result) [ path.pwd ] ] ; + result = [ path.native $(result) ] ; + return $(result) ; +} + # Loads all the configuration files used by Boost Build in the following order: # @@ -282,11 +311,21 @@ local rule load-config ( module-name : filename : path + : must-find ? ) # files will not be. If a relative path is specified, file is searched for in # the current folder. # +# -- all-config -- +# Loaded only if specified on the command-line using the --config command +# line option. If a file name is specified, it must exist and replaces all +# other configuration files. If an empty file name is passed, no configuration +# files will be loaded. +# # -- site-config -- -# Always named site-config.jam. Will only be found if located on the system -# root path (Windows), /etc (non-Windows), user's home folder or the Boost Build -# path, in that order. Not loaded in case the test-config configuration file is -# loaded or the --ignore-site-config command-line option is specified. +# Named site-config.jam by default or may be named explicitly using the +# --site-config command-line option. If named explicitly, the file is found +# relative to the current working directory and must exist. If the default one +# is used then it is searched for in the system root path (Windows), +# /etc (non-Windows), user's home folder or the Boost Build path, in that +# order. Not loaded in case the test-config configuration file is loaded, +# the file is explicitly set to the empty string or the --ignore-site-config +# command-line option is specified. # # -- user-config -- # Named user-config.jam by default or may be named explicitly using the @@ -299,8 +338,12 @@ local rule load-config ( module-name : filename : path + : must-find ? ) # file must exist. # # -- project-config -- -# Always named project-config.jam. Looked up in the current working folder and -# then upwards through its parents up to the root folder. +# Named project-config.jam. Looked up in the current working folder and +# then upwards through its parents up to the root folder. It may also be +# named explicitly using the --project-config command-line option. If a file +# is specified explicitly, it is found relative to the current working +# directory and must exist. If an empty file name is passed, project-config +# will not be loaded. # # Test configurations have been added primarily for use by Boost Build's # internal unit testing system but may be used freely in other places as well. @@ -310,14 +353,11 @@ local rule load-configuration-files # Flag indicating that site configuration should not be loaded. local ignore-site-config = [ MATCH ^(--ignore-site-config)$ : $(.argv) ] ; + local ignore-user-config ; + local ignore-project-config ; initialize-config-module test-config ; - local test-config = [ MATCH ^--test-config=(.*)$ : $(.argv) ] ; - local uq = [ MATCH \"(.*)\" : $(test-config) ] ; - if $(uq) - { - test-config = $(uq) ; - } + local test-config = [ handle-config-option test-config ] ; if $(test-config) { local where = [ load-config test-config : $(test-config:BS) : @@ -330,12 +370,32 @@ local rule load-configuration-files ECHO "notice: be ignored due to the test configuration being" "loaded." ; } + ignore-site-config = true ; + ignore-user-config = true ; } - else + } + + initialize-config-module all-config ; + local all-config = [ handle-config-option config ] ; + if $(all-config) + { + load-config all-config : $(all-config:D=) : $(all-config:D) : required ; + if $(.debug-config) { - test-config = ; + ECHO "notice: Regular configuration files will be ignored due" ; + ECHO "notice: to the global configuration being loaded." ; } } + if $(all-config)-is-defined + { + if $(.debug-config) && ! $(all-config) + { + ECHO "notice: Configuration file loading explicitly disabled." ; + } + ignore-site-config = true ; + ignore-user-config = true ; + ignore-project-config = true ; + } local user-path = [ os.home-directories ] [ os.environ BOOST_BUILD_PATH ] ; local site-path = /etc $(user-path) ; @@ -344,55 +404,52 @@ local rule load-configuration-files site-path = [ modules.peek : SystemRoot ] $(user-path) ; } - if $(.debug-config) && ! $(test-config) && $(ignore-site-config) + if $(.debug-config) && $(ignore-site-config) = --ignore-site-config { ECHO "notice: Site configuration files will be ignored due to the" ; ECHO "notice: --ignore-site-config command-line option." ; } initialize-config-module site-config ; - if ! $(test-config) && ! $(ignore-site-config) + if ! $(ignore-site-config) { - load-config site-config : site-config.jam : $(site-path) ; + local site-config = [ handle-config-option site-config ] ; + if $(site-config) + { + load-config site-config : $(site-config:D=) : $(site-config:D) + : must-exist ; + } + else if ! $(site-config)-is-defined + { + load-config site-config : site-config.jam : $(site-path) ; + } + else if $(.debug-config) + { + ECHO notice: Site configuration file loading explicitly disabled. ; + } } initialize-config-module user-config ; - if ! $(test-config) + if ! $(ignore-user-config) { - local user-config = [ MATCH ^--user-config=(.*)$ : $(.argv) ] ; - user-config = $(user-config[-1]) ; - user-config ?= [ os.environ BOOST_BUILD_USER_CONFIG ] ; - # Special handling for the case when the OS does not strip the quotes - # around the file name, as is the case when using Cygwin bash. - user-config = [ utility.unquote $(user-config) ] ; - local explicitly-requested = $(user-config) ; - user-config ?= user-config.jam ; + local user-config = + [ handle-config-option user-config : BOOST_BUILD_USER_CONFIG ] ; if $(user-config) { - if $(explicitly-requested) + if $(.debug-config) { - # Treat explicitly entered user paths as native OS path - # references and, if non-absolute, root them at the current - # working directory. - user-config = [ path.make $(user-config) ] ; - user-config = [ path.root $(user-config) [ path.pwd ] ] ; - user-config = [ path.native $(user-config) ] ; - - if $(.debug-config) - { - ECHO notice: Loading explicitly specified user configuration - file: ; - ECHO " $(user-config)" ; - } - - load-config user-config : $(user-config:BS) : $(user-config:D) - : must-exist ; - } - else - { - load-config user-config : $(user-config) : $(user-path) ; + ECHO notice: Loading explicitly specified user configuration + file: ; + ECHO " $(user-config)" ; } + + load-config user-config : $(user-config:D=) : $(user-config:D) + : must-exist ; + } + else if ! $(user-config)-is-defined + { + load-config user-config : user-config.jam : $(user-path) ; } else if $(.debug-config) { @@ -406,15 +463,33 @@ local rule load-configuration-files # - We need to load project-config.jam before Jamroot # - We probably need to load project-config.jam even if there is no Jamroot # - e.g. to implement automake-style out-of-tree builds. - local file = [ path.glob "." : project-config.jam ] ; - if ! $(file) + if ! $(ignore-project-config) { - file = [ path.glob-in-parents "." : project-config.jam ] ; - } - if $(file) - { - initialize-config-module project-config : $(file:D) ; - load-config project-config : project-config.jam : $(file:D) ; + local project-config = [ handle-config-option project-config ] ; + if $(project-config) + { + initialize-config-module project-config : $(project-config:D=) ; + load-config project-config : $(project-config:D=) + : $(project-config:D) : must-exist ; + } + else if ! $(project-config)-is-defined + { + local file = [ path.glob "." : project-config.jam ] ; + if ! $(file) + { + file = [ path.glob-in-parents "." : project-config.jam ] ; + } + if $(file) + { + initialize-config-module project-config : $(file:D) ; + load-config project-config : project-config.jam : $(file:D) ; + } + } + else if $(.debug-config) + { + ECHO notice: Project configuration file loading explicitly + disabled. ; + } } project.end-load ; diff --git a/src/build/project.jam b/src/build/project.jam index d02240a4f..803574052 100644 --- a/src/build/project.jam +++ b/src/build/project.jam @@ -441,7 +441,7 @@ rule initialize ( local jamroot ; local parent-module ; - if $(module-name) = test-config + if $(module-name) in test-config all-config { # No parent. } @@ -502,7 +502,7 @@ rule initialize ( } else { - local cfgs = project site test user ; + local cfgs = project site test user all ; if ! $(module-name) in $(cfgs)-config { # This is a standalone project with known location. Set its diff --git a/test/configuration.py b/test/configuration.py index 724ecd7c9..0a9df6a6c 100755 --- a/test/configuration.py +++ b/test/configuration.py @@ -8,6 +8,7 @@ # Test Boost Build configuration file handling. import BoostBuild +import TestCmd import os import os.path @@ -316,6 +317,71 @@ for x in $(names) t.cleanup() +def test_site_config(): + # Ignore user-config, just in case it depends on the user's site-config.jam + t = BoostBuild.Tester(["--user-config="], use_test_config=False, + pass_toolset=0) + # We can immediately exit after we finish loading the config files + t.write("Jamroot", "EXIT Done : 0 ;") + t.write("my-site-config.jam", "ECHO Loaded my-site-config ;") + + t.run_build_system(["--site-config=my-site-config.jam"], + stdout="Loaded my-site-config\nDone\n") + + t.run_build_system(["--ignore-site-config", "--debug-configuration"]) + t.expect_output_lines("""\ +notice: Site configuration files will be ignored due to the +notice: --ignore-site-config command-line option.""") + + t.run_build_system(["--site-config=", "--debug-configuration"]) + t.expect_output_lines("""\ +notice: Site configuration file loading explicitly disabled.""") + + t.cleanup() + +def test_global_config(): + t = BoostBuild.Tester(use_test_config=False, pass_toolset=0) + t.write("my-config.jam", "ECHO Loading my-config ;") + t.write("Jamroot", "EXIT Done : 0 ;") + t.write("project-config.jam", "ECHO bad ;") + t.run_build_system(["--config=my-config.jam", "--debug-configuration"], + match=TestCmd.match_re, stdout= +r"""notice: found boost-build\.jam at .* +notice: loading Boost\.Build from .* +notice: Searching '.*' for all-config configuration file 'my-config\.jam'\. +notice: Loading all-config configuration file 'my-config\.jam' from '.*'\. +Loading my-config +notice: Regular configuration files will be ignored due +notice: to the global configuration being loaded\. +Done +""") + t.run_build_system(["--config=", "--debug-configuration"], + match=TestCmd.match_re, stdout= +r"""notice: found boost-build\.jam at .* +notice: loading Boost\.Build from .* +notice: Configuration file loading explicitly disabled. +Done +""") + t.cleanup() + +def test_project_config(): + t = BoostBuild.Tester(["--user-config=", "--site-config="], + use_test_config=False, pass_toolset=False) + t.write("Jamroot", "EXIT Done : 0 ;") + t.write("project-config.jam", "ECHO Loading Root ;") + t.write("my-project-config.jam", "ECHO Loading explicit ;") + t.write("sub/project-config.jam", "ECHO Loading subdir ;") + t.write("sub/Jamfile", "") + + t.run_build_system(stdout="Loading Root\nDone\n") + t.run_build_system(subdir="sub", stdout="Loading subdir\nDone\n") + t.rm("sub/project-config.jam") + t.run_build_system(subdir="sub", stdout="Loading Root\nDone\n") + t.run_build_system(["--project-config=my-project-config.jam"], + stdout="Loading explicit\nDone\n") + + t.cleanup() + ############################################################################### # # main() @@ -326,3 +392,6 @@ for x in $(names) canSetEmptyEnvironmentVariable = _canSetEmptyEnvironmentVariable() test_user_configuration() +test_site_config() +test_global_config() +test_project_config() From 05a741996983ab925010250f86ae47cb547bd289 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Thu, 11 Jan 2018 15:26:28 -0700 Subject: [PATCH 64/72] Remove an evil hack. The comment explaining why it is necessary appears to be out-dated. --- src/tools/generators/linking-generator.jam | 9 +-------- test/dll_path.py | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/tools/generators/linking-generator.jam b/src/tools/generators/linking-generator.jam index 2184eea5a..0c9d38f3e 100644 --- a/src/tools/generators/linking-generator.jam +++ b/src/tools/generators/linking-generator.jam @@ -55,15 +55,8 @@ class linking-generator : generator { if [ type.is-derived [ $(s).type ] SHARED_LIB ] && ! [ $(s).action ] { - # Unfortunately, we do not have a good way to find the path to a - # file, so use this nasty approach. - # - # TODO: This needs to be done better. One thing that is really - # broken with this is that it does not work correctly with - # projects having multiple source locations. - local p = [ $(s).project ] ; local location = [ path.root [ $(s).name ] - [ $(p).get source-location ] ] ; + [ $(s).path ] ] ; extra-xdll-paths += [ path.parent $(location) ] ; } } diff --git a/test/dll_path.py b/test/dll_path.py index e71b704b9..6282fae9f 100644 --- a/test/dll_path.py +++ b/test/dll_path.py @@ -143,4 +143,21 @@ es2 = t.adjust_name("b/bin/$toolset/debug*") t.expect_content_lines("bin/$toolset/debug*/mp.pathlist", "*" + es1); t.expect_content_lines("bin/$toolset/debug*/mp.pathlist", "*" + es2); +t.rm("bin/$toolset/debug*/mp.pathlist") + +# Now run the same checks with pre-built libraries +adll = t.glob_file("a/bin/$toolset/debug*/a.dll") +bdll = t.glob_file("b/bin/$toolset/debug*/b.dll") +t.write("b/jamfile.jam", """ +local bdll = %s ; +# Make sure that it is found even with multiple source-locations +project : source-location c $(bdll:D) ; +lib b : ../a//a : $(bdll:D=) ; +""" % bdll.replace("\\", "\\\\")) +t.run_build_system(["hardcode-dll-paths=true"]) +t.expect_addition("bin/$toolset/debug*/mp.pathlist") + +t.expect_content_lines("bin/$toolset/debug*/mp.pathlist", "*" + es1) +t.expect_content_lines("bin/$toolset/debug*/mp.pathlist", "*" + es2) + t.cleanup() From 79dd4a729273dcb22a2f1a2340c176863925699b Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Fri, 12 Jan 2018 09:56:18 -0700 Subject: [PATCH 65/72] The manpage type should not break shared libraries with a version suffix. --- src/tools/types/man.jam | 2 +- test/test_all.py | 1 + test/types.py | 44 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 test/types.py diff --git a/src/tools/types/man.jam b/src/tools/types/man.jam index 7dc9cb353..4fb59a0fe 100644 --- a/src/tools/types/man.jam +++ b/src/tools/types/man.jam @@ -5,4 +5,4 @@ accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |# -type MANPAGE : man 0 1 1M 2 3 4 5 6 7 8 9 n p x ; +type MANPAGE : man 1M n p x ; diff --git a/test/test_all.py b/test/test_all.py index 38255d967..edad58da4 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -282,6 +282,7 @@ tests = ["absolute_sources", "toolset_gcc", "toolset_intel_darwin", "toolset_requirements", + "types", "unit_test", "unused", "use_requirements", diff --git a/test/types.py b/test/types.py new file mode 100644 index 000000000..e6d9bf840 --- /dev/null +++ b/test/types.py @@ -0,0 +1,44 @@ +#!/usr/bin/python +# +# Copyright 2018 Steven Watanabe +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Tests the mapping of various suffixes +# In particular, .so[.version] needs to +# be mapped as a SHARED_LIB. + +import BoostBuild + +t = BoostBuild.Tester() + +t.write("Jamroot.jam", """\ +import type : type ; +ECHO [ type source.c ] ; +ECHO [ type source.cc ] ; +ECHO [ type source.cxx ] ; +ECHO [ type source.cpp ] ; +ECHO [ type source.o ] ; +ECHO [ type source.obj ] ; +ECHO [ type boost_system.lib ] ; +ECHO [ type boost_system.so ] ; +ECHO [ type boost_system.dll ] ; +EXIT [ type boost_system.so.1.66.0 ] : 0 ; +""") + +t.run_build_system(stdout="""\ +C +CPP +CPP +CPP +OBJ +OBJ +STATIC_LIB +SHARED_LIB +SHARED_LIB +SHARED_LIB +""") + +t.cleanup() From ed37fd04afd3b006629a57644995dfbbbb029b5c Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Fri, 12 Jan 2018 15:44:22 -0700 Subject: [PATCH 66/72] Merge regression.py, testing_support.py and test_result_dumping.py into testing.py. Also, make the tests from more systematic. --- test/BoostBuild.py | 2 +- test/regression.py | 113 ----------- test/test_all.py | 4 +- test/test_result_dumping.py | 33 ---- test/{testing_support.py => testing.py} | 245 ++++++++++++++++++++++++ 5 files changed, 247 insertions(+), 150 deletions(-) delete mode 100644 test/regression.py delete mode 100755 test/test_result_dumping.py rename test/{testing_support.py => testing.py} (53%) diff --git a/test/BoostBuild.py b/test/BoostBuild.py index e15fe6798..19b346f77 100644 --- a/test/BoostBuild.py +++ b/test/BoostBuild.py @@ -773,7 +773,7 @@ class Tester(TestCmd.TestCmd): matched = reduce( lambda x, y: x and reduce( lambda a, b: a and b, - y), + y, True), matched, True) if not matched: diff --git a/test/regression.py b/test/regression.py deleted file mode 100644 index 071e7ca54..000000000 --- a/test/regression.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/python - -# Copyright (C) Vladimir Prus 2003. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -# Test for the regression testing framework. - -import BoostBuild - -# Create a temporary working directory. -t = BoostBuild.Tester(use_test_config=False) - -t.write("c.cpp", "\n") -t.write("r.cpp", """\ -void helper(); - -#include -int main( int ac, char * av[] ) -{ - helper(); - for ( int i = 1; i < ac; ++i ) - std::cout << av[ i ] << '\\n'; -} -""") -t.write("c-f.cpp", "int\n") -t.write("r-f.cpp", "int main() { return 1; }\n") - -t.write("jamroot.jam", "") -t.write("jamfile.jam", """\ -import testing ; -compile c.cpp ; -compile-fail c-f.cpp ; -run r.cpp libs//helper : foo bar ; -run-fail r-f.cpp ; -""") - -t.write("libs/jamfile.jam", "lib helper : helper.cpp ;") -t.write("libs/helper.cpp", """\ -void -#if defined(_WIN32) -__declspec(dllexport) -#endif -helper() {} -""") - -# First test that when outcomes are expected, all .test files are created. -t.run_build_system(["hardcode-dll-paths=false"], stderr=None, status=None) -t.expect_addition("bin/c.test/$toolset/debug*/c.test") -t.expect_addition("bin/c-f.test/$toolset/debug*/c-f.test") -t.expect_addition("bin/r.test/$toolset/debug*/r.test") -t.expect_addition("bin/r-f.test/$toolset/debug*/r-f.test") - -# Make sure args are handled. -t.expect_content("bin/r.test/$toolset/debug*/r.output", - "foo\nbar\n*\nEXIT STATUS: 0*\n", True) - -# Test that input file is handled as well. -t.write("r.cpp", """\ -#include -#include -int main( int ac, char * av[] ) -{ - for ( int i = 1; i < ac; ++i ) - { - std::ifstream ifs( av[ i ] ); - std::cout << ifs.rdbuf(); - } -} -""") - -t.write("dir/input.txt", "test input") - -t.write("jamfile.jam", """\ -import testing ; -compile c.cpp ; -obj c-obj : c.cpp ; -compile-fail c-f.cpp ; -run r.cpp : : dir/input.txt ; -run-fail r-f.cpp ; -time execution : r ; -time compilation : c-obj ; -""") - -t.run_build_system(["hardcode-dll-paths=false"]) -t.expect_content("bin/r.test/$toolset/debug*/r.output", """\ -test input -EXIT STATUS: 0 -""") - -t.expect_addition('bin/$toolset/debug*/execution.time') -t.expect_addition('bin/$toolset/debug*/compilation.time') - -# Make sure test failures are detected. Reverse expectation and see if .test -# files are created or not. -t.write("jamfile.jam", """\ -import testing ; -compile-fail c.cpp ; -compile c-f.cpp ; -run-fail r.cpp : : dir/input.txt ; -run r-f.cpp ; -""") - -t.touch(BoostBuild.List("c.cpp c-f.cpp r.cpp r-f.cpp")) - -t.run_build_system(["hardcode-dll-paths=false"], stderr=None, status=1) -t.expect_removal("bin/c.test/$toolset/debug*/c.test") -t.expect_removal("bin/c-f.test/$toolset/debug*/c-f.test") -t.expect_removal("bin/r.test/$toolset/debug*/r.test") -t.expect_removal("bin/r-f.test/$toolset/debug*/r-f.test") - -t.cleanup() diff --git a/test/test_all.py b/test/test_all.py index edad58da4..591b11aae 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -255,7 +255,6 @@ tests = ["absolute_sources", "project_test4", "property_expansion", "rebuilds", - "regression", "relative_sources", "remove_requirement", "rescan_header", @@ -272,9 +271,8 @@ tests = ["absolute_sources", "static_and_shared_library", "suffix", "tag", - "test_result_dumping", "test_rc", - "testing_support", + "testing", "timedata", "toolset_clang_darwin", "toolset_clang_linux", diff --git a/test/test_result_dumping.py b/test/test_result_dumping.py deleted file mode 100755 index bdfc41ee2..000000000 --- a/test/test_result_dumping.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/python - -# Copyright 2008 Jurko Gospodnetic -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -# Tests dumping Boost Build based testing results. - -import BoostBuild - - -############################################################################### -# -# Test that dumping Boost Build based testing results works in case test code -# is not located in a folder under the Jamroot folder. -# -############################################################################### - -t = BoostBuild.Tester(["--dump-tests"], use_test_config=False) - -t.write("TestBuild/jamroot.jam", """\ -import testing ; -test-suite testit : [ run ../TestSource/test.cpp ] ; -""") - -t.write("TestSource/test.cpp", "int main() {}\n") - -t.run_build_system(subdir="TestBuild") -t.expect_output_lines('boost-test(RUN) "*/TestBuild/test" : ' - '"../TestSource/test.cpp"') - -t.cleanup() diff --git a/test/testing_support.py b/test/testing.py similarity index 53% rename from test/testing_support.py rename to test/testing.py index 229d3763d..c1c3d8d5f 100755 --- a/test/testing_support.py +++ b/test/testing.py @@ -8,6 +8,7 @@ # Tests different aspects of Boost Builds automated testing support. import BoostBuild +import TestCmd def test_run(): t = BoostBuild.Tester(use_test_config=False) @@ -73,6 +74,125 @@ run-fail fail-run.cpp ; t.cleanup() +def test_run_change(): + """Tests that the test file is removed when a test fails after it + previously passed.""" + + t = BoostBuild.Tester(use_test_config=False) + + t.write("pass.cpp", "int main() { return 1; }\n") + t.write("fail-compile.cpp", "int main() {}\n") + t.write("fail-link.cpp", "int main() {}\n") + t.write("fail-run.cpp", "int main() {}\n") + + t.write("Jamroot.jam", """import testing ; +run-fail pass.cpp ; +run fail-compile.cpp ; +run fail-link.cpp ; +run fail-run.cpp ; +""") + t.run_build_system() + # Sanity check + t.expect_addition("bin/pass.test/$toolset/debug*/pass.test") + t.expect_addition("bin/fail-compile.test/$toolset/debug*/fail-compile.test") + t.expect_addition("bin/fail-link.test/$toolset/debug*/fail-link.test") + t.expect_addition("bin/fail-run.test/$toolset/debug*/fail-run.test") + + # Now make them fail + t.write("pass.cpp", "int main() {}\n") + t.write("fail-compile.cpp", "#error expected to fail\n") + t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") + t.write("fail-run.cpp", "int main() { return 1; }\n") + t.run_build_system(status=1) + + t.expect_removal("bin/pass.test/$toolset/debug*/pass.test") + t.expect_removal("bin/fail-compile.test/$toolset/debug*/fail-compile.test") + t.expect_removal("bin/fail-link.test/$toolset/debug*/fail-link.test") + t.expect_removal("bin/fail-run.test/$toolset/debug*/fail-run.test") + + t.cleanup() + +def test_run_path(): + """Tests that run can find shared libraries even without + hardcode-dll-paths. Important: The library is in neither the + current working directory, nor any system path, nor the same + directory as the executable, so it should never be found without + help from Boost.Build.""" + t = BoostBuild.Tester(["hardcode-dll-paths=false"], use_test_config=False) + + t.write("l.cpp", """ +void +#if defined(_WIN32) +__declspec(dllexport) +#endif +f() {} +""") + t.write("pass.cpp", "void f(); int main() { f(); }\n") + + t.write("Jamroot.jam", """import testing ; +lib l : l.cpp : shared ; +run pass.cpp l ; +""") + + t.run_build_system() + t.expect_addition("bin/$toolset/debug*/l.obj") + t.expect_addition("bin/$toolset/debug*/l.dll") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.obj") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.exe") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.output") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.run") + t.expect_addition("bin/pass.test/$toolset/debug*/pass.test") + t.expect_nothing_more() + + t.cleanup() + +def test_run_args(): + """Tests the handling of args and input-files""" + t = BoostBuild.Tester(use_test_config=False) + t.write("test.cpp", """ +#include +#include +int main(int argc, const char ** argv) +{ + for(int i = 1; i < argc; ++i) + { + if(argv[i][0] == '-') + { + std::cout << argv[i] << std::endl; + } + else + { + std::ifstream ifs(argv[i]); + std::cout << ifs.rdbuf(); + } + } +} +""") + t.write("input1.in", "first input\n") + t.write("input2.in", "second input\n") + t.write("Jamroot.jam", """import testing ; +import common ; +# FIXME: The order actually depends on the lexigraphical +# ordering of the virtual target objects, which is just +# crazy. Switch the order of input1.txt and input2.txt +# to make this fail. Joining the arguments with && might +# work, but might get a bit complicated to implement as +# dependency properties do not currently support &&. +make input1.txt : input1.in : @common.copy ; +make input2.txt : input2.in : @common.copy ; +run test.cpp : -y -a : input1.txt input2.txt ; +""") + t.run_build_system() + t.expect_content("bin/test.test/$toolset/debug*/test.output", """\ +-y +-a +first input +second input + +EXIT STATUS: 0 +""") + t.cleanup() + def test_link(): t = BoostBuild.Tester(use_test_config=False) @@ -131,6 +251,39 @@ link-fail fail-run.cpp ; t.cleanup() +def test_link_change(): + """Tests that the test file is removed when a test fails after it + previously passed.""" + + t = BoostBuild.Tester(use_test_config=False) + + t.write("pass.cpp", "int f();\nint main() { return f(); }\n") + t.write("fail-compile.cpp", "int main() {}\n") + t.write("fail-link.cpp", "int main() {}\n") + + t.write("Jamroot.jam", """import testing ; +link-fail pass.cpp ; +link fail-compile.cpp ; +link fail-link.cpp ; +""") + t.run_build_system() + # Sanity check + t.expect_addition("bin/pass.test/$toolset/debug*/pass.test") + t.expect_addition("bin/fail-compile.test/$toolset/debug*/fail-compile.test") + t.expect_addition("bin/fail-link.test/$toolset/debug*/fail-link.test") + + # Now make them fail + t.write("pass.cpp", "int main() {}\n") + t.write("fail-compile.cpp", "#error expected to fail\n") + t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") + t.run_build_system(status=1) + + t.expect_removal("bin/pass.test/$toolset/debug*/pass.test") + t.expect_removal("bin/fail-compile.test/$toolset/debug*/fail-compile.test") + t.expect_removal("bin/fail-link.test/$toolset/debug*/fail-link.test") + + t.cleanup() + def test_compile(): t = BoostBuild.Tester(use_test_config=False) @@ -183,6 +336,34 @@ compile-fail fail-run.cpp ; t.cleanup() +def test_compile_change(): + """Tests that the test file is removed when a test fails after it + previously passed.""" + + t = BoostBuild.Tester(use_test_config=False) + + t.write("pass.cpp", "#error expected to fail\n") + t.write("fail-compile.cpp", "int main() {}\n") + + t.write("Jamroot.jam", """import testing ; +compile-fail pass.cpp ; +compile fail-compile.cpp ; +""") + t.run_build_system() + # Sanity check + t.expect_addition("bin/pass.test/$toolset/debug*/pass.test") + t.expect_addition("bin/fail-compile.test/$toolset/debug*/fail-compile.test") + + # Now make them fail + t.write("pass.cpp", "int main() {}\n") + t.write("fail-compile.cpp", "#error expected to fail\n") + t.run_build_system(status=1) + + t.expect_removal("bin/pass.test/$toolset/debug*/pass.test") + t.expect_removal("bin/fail-compile.test/$toolset/debug*/fail-compile.test") + + t.cleanup() + def test_remove_test_targets(option): t = BoostBuild.Tester(use_test_config=False) @@ -228,6 +409,64 @@ run-fail fail-run.cpp ; t.cleanup() +def test_dump_tests(): + """Tests the output of the --dump-tests option""" + t = BoostBuild.Tester(use_test_config=False) + + t.write("pass-compile.cpp", "int main() {}\n") + t.write("pass-link.cpp", "int main() {}\n") + t.write("pass-run.cpp", "int main() {}\n") + t.write("fail-compile.cpp", "#error expected to fail\n") + t.write("fail-link.cpp", "int f();\nint main() { return f(); }\n") + t.write("fail-run.cpp", "int main() { return 1; }\n") + + t.write("Jamroot.jam", """import testing ; +run pass-run.cpp ; +run-fail fail-run.cpp ; +link pass-link.cpp ; +link-fail fail-link.cpp ; +compile pass-compile.cpp ; +compile-fail fail-compile.cpp ; +build-project libs/any/test ; +build-project libs/any/example ; +build-project libs/any ; +build-project tools/bcp/test ; +build-project tools/bcp/example ; +build-project subdir/test ; +build-project status ; +build-project outside/project ; +""") + def write_subdir(dir): + t.write(dir + "/test.cpp", "int main() {}\n") + t.write(dir + "/Jamfile", "run test.cpp ;") + write_subdir("libs/any/test") + write_subdir("libs/any/example") + write_subdir("libs/any") + write_subdir("tools/bcp/test") + write_subdir("tools/bcp/example") + write_subdir("status") + write_subdir("subdir/test") + t.write("outside/other/test.cpp", "int main() {}\n") + t.write("outside/project/Jamroot", "run ../other/test.cpp ;") + t.run_build_system(["--dump-tests", "-n", "-d0"], + match=TestCmd.match_re, stdout= +"""boost-test\(RUN\) ".*/pass-run" : "pass-run\.cpp" +boost-test\(RUN_FAIL\) ".*/fail-run" : "fail-run\.cpp" +boost-test\(LINK\) ".*/pass-link" : "pass-link\.cpp" +boost-test\(LINK_FAIL\) ".*/fail-link" : "fail-link\.cpp" +boost-test\(COMPILE\) ".*/pass-compile" : "pass-compile\.cpp" +boost-test\(COMPILE_FAIL\) ".*/fail-compile" : "fail-compile\.cpp" +boost-test\(RUN\) "any/test" : "libs/any/test\.cpp" +boost-test\(RUN\) "any/test" : "libs/any/test/test\.cpp" +boost-test\(RUN\) "any/test" : "libs/any/example/test\.cpp" +boost-test\(RUN\) "bcp/test" : "tools/bcp/test/test\.cpp" +boost-test\(RUN\) "bcp/test" : "tools/bcp/example/test\.cpp" +boost-test\(RUN\) ".*/subdir/test/test" : "subdir/test/test\.cpp" +boost-test\(RUN\) "test" : "status/test\.cpp" +boost-test\(RUN\) ".*/outside/project/test" : "../other/test.cpp" +""") + t.cleanup() + ################################################################################ # # test_files_with_spaces_in_their_name() @@ -279,10 +518,16 @@ testing.compile-fail "invalid source.cpp" ; test_run() test_run_fail() +test_run_change() +test_run_path() +test_run_args() test_link() test_link_fail() +test_link_change() test_compile() test_compile_fail() +test_compile_change() test_remove_test_targets("--remove-test-targets") test_remove_test_targets("preserve-test-targets=off") +test_dump_tests() test_files_with_spaces_in_their_name() From ae4e15196704c4372206b5f71799d52e9fa448e3 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Fri, 12 Jan 2018 16:03:57 -0700 Subject: [PATCH 67/72] Passing -a -n usually means that we just want to see all the commands. Actually re-running configuration checks just wastes time. --- src/build/config-cache.jam | 2 +- test/configure.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/build/config-cache.jam b/src/build/config-cache.jam index d97ec45d5..0c47917e2 100644 --- a/src/build/config-cache.jam +++ b/src/build/config-cache.jam @@ -69,7 +69,7 @@ rule load ( cache-file ) { FILE_CONTENTS on $(cache-file) = "" ; config-cache.write $(cache-file) ; - UPDATE_NOW $(cache-file) : [ modules.peek configure : .log-fd ] : ignore-minus-n ; + UPDATE_NOW $(cache-file) : [ modules.peek configure : .log-fd ] ; include $(cache-file) ; } .cache-file = $(cache-file) ; diff --git a/test/configure.py b/test/configure.py index 73b39e9db..3f0c958a0 100644 --- a/test/configure.py +++ b/test/configure.py @@ -65,6 +65,13 @@ obj bar : foo.cpp : t.expect_touch("bin/$toolset/debug*/pass.obj") t.expect_nothing_more() + # -a -n should not rebuild configuration checks + t.run_build_system(["-a", "-n"]) + t.expect_output_lines([ + " - pass builds : yes (cached)", + " - fail builds : no (cached)"]) + t.expect_nothing_more() + t.cleanup() def test_choose(): From ee613a6a289934181bcfb69c881864bf2d2f385f Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 13 Jan 2018 09:13:49 -0700 Subject: [PATCH 68/72] Implement feature relevance. * New feature which is automatically deduced in most cases. * Features which are not relevant do not affect target paths and do not prevent merging of virtual targets. * generators.jam: generator.run always returns usage-requirements to allow usage-requirements in non-top-level generators. This is necessary because we're using usage-requirements to track relevance from flags. * New rule toolset.uses-features to specify features that the rule checks manually, instead of using toolset.flags. In the future, we should consider restricting the properties actually passed, to detect errors. * Adjust tests to handle the new paths (verified by inspection). * Add temporary option --ignore-relevance to consider all features relevant to aid migration. * New rule property.evaluate-conditional-relevance which helps tracking relevance in . * Widely scattered changes to use the new interfaces. --- doc/src/reference.xml | 57 ++++++- src/build/ac.jam | 5 +- src/build/configure.jam | 15 +- src/build/feature.jam | 43 ++++++ src/build/generators.jam | 43 ++++-- src/build/property-set.jam | 56 ++++++- src/build/property.jam | 32 +++- src/build/targets.jam | 92 +++++++++++- src/build/toolset.jam | 76 ++++++++++ src/build/virtual-target.jam | 6 +- src/tools/bison.jam | 14 +- src/tools/doxygen.jam | 3 + src/tools/features/relevant-feature.jam | 10 ++ src/tools/features/threadapi-feature.jam | 2 +- src/tools/gcc.jam | 4 +- src/tools/generators/archive-generator.jam | 5 +- src/tools/generators/lib-generator.jam | 3 +- src/tools/generators/linking-generator.jam | 5 +- .../generators/searched-lib-generator.jam | 4 +- src/tools/lex.jam | 12 +- src/tools/make.jam | 7 +- src/tools/mpi.jam | 4 + src/tools/msvc.jam | 13 +- src/tools/python.jam | 4 + src/tools/stlport.jam | 3 + src/tools/testing.jam | 5 + src/tools/xsltproc.jam | 1 + test/MockToolset.py | 5 +- test/TestToolset.py | 19 +-- test/command_line_properties.py | 4 +- test/custom_generator.py | 2 +- test/example_make.py | 2 +- test/feature_relevant.py | 142 ++++++++++++++++++ test/gcc_runtime.py | 5 +- test/generator_selection.py | 10 +- test/generators_test.py | 8 +- test/inline.py | 13 +- test/make_rule.py | 4 +- test/project-test3/jamroot.jam | 4 + test/project-test4/jamroot.jam | 7 +- test/project_id.py | 4 +- test/project_root_rule.py | 2 +- test/remove_requirement.py | 2 + test/rescan_header.py | 20 +-- test/source_order.py | 4 +- test/space_in_path.py | 2 +- test/static_and_shared_library.py | 2 +- test/suffix.py | 2 +- test/tag.py | 8 +- test/test_all.py | 1 + 50 files changed, 674 insertions(+), 122 deletions(-) create mode 100644 src/tools/features/relevant-feature.jam create mode 100644 test/feature_relevant.py diff --git a/doc/src/reference.xml b/doc/src/reference.xml index 8c45dfb05..59a03483b 100644 --- a/doc/src/reference.xml +++ b/doc/src/reference.xml @@ -856,6 +856,60 @@ path-constant DATA : data/a.txt ; + relevant + + + featuresrelevance + relevant + + + Allowed values: the name of any feature. + + + + This feature is used to indicate which other features are relevant for + a given target. It is usually not necessary to manage it explicitly, + as Boost.Build can deduce it in most cases. Features which are not + relevant will not affect target paths, and will not cause conflicts. + + + + A feature will be considered relevant if any of the following are true + + It is referenced by toolset.flags or toolset.uses-features + It is used by the requirements of a generator + It is a subfeature of a relevant feature + It has a subfeature which is relevant + It is a composite feature, and any composed feature is relevant + It affects target alternative selection for a main target + It is a propagated feature and is relevant for any dependency + It is relevant for any dependency created by the same main target + It is used in the condition of a conditional property and the corresponding value is relevant + It is explicitly named as relevent + + + + Relevant features cannot be automatically deduced in the following cases: + + Indirect conditionals. Solution: return properties of the form + <relevant>result-feature:<relevant>condition-feature + This isn't really a conditional, + although for most purposes it functions like one. In particular, it does not support + multiple comma-separated elements in the condition, and it does work correctly even + in contexts where conditional properties are not allowed + + Action rules that read properties. Solution: add toolset.uses-features + to tell Boost.Build that the feature is actually used. + + + Generators and targets that manipulate property-sets directly. + Solution: set <relevant> manually. + + + + + + @@ -2539,7 +2593,8 @@ exe a : a.cpp the directory bin unless this is overridden by the build-dir project attribute. Under bin is a path that depends on the properties used to build each target. This path is uniquely determined by - all non-free, non-incidental properties. For example, + all relevant + non-free, non-incidental properties. For example, given a property set containing: <toolset>gcc <toolset-gcc:version>4.6.1 <variant>debug <warnings>all <define>_DEBUG <include>/usr/local/include diff --git a/src/build/ac.jam b/src/build/ac.jam index 846965a03..718765649 100644 --- a/src/build/ac.jam +++ b/src/build/ac.jam @@ -316,5 +316,8 @@ rule check-library ( target : true-properties * : false-properties * ) { local instance = [ class.new check-library-worker $(target) : $(true-properties) : $(false-properties) ] ; - return @$(instance).check ; + return @$(instance).check + [ property.evaluate-conditional-relevance + $(true-properties) $(false-properties) + : [ configure.get-relevant-features ] ] ; } diff --git a/src/build/configure.jam b/src/build/configure.jam index 3f3f97034..b5d85c456 100644 --- a/src/build/configure.jam +++ b/src/build/configure.jam @@ -507,6 +507,11 @@ class configure-choose-worker } } } + rule all-properties ( ) + { + local i = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; + return $(self.props.$(i)) ; + } rule check ( properties * ) { local i = [ configure.find-builds $(self.message) : $(properties) @@ -542,7 +547,10 @@ rule check-target-builds ( target message ? : true-properties * : { local instance = [ new check-target-builds-worker $(target) $(message) : $(true-properties) : $(false-properties) ] ; - return @$(instance).check ; + return @$(instance).check + [ property.evaluate-conditional-relevance + $(true-properties) $(false-properties) + : [ configure.get-relevant-features ] ] ; } # Usage: @@ -556,7 +564,10 @@ rule choose ( message : * ) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) : $(10) : $(11) : $(12) : $(13) : $(14) : $(15) : $(16) : $(17) : $(18) : $(19) ] ; - return @$(instance).check ; + return @$(instance).check + [ property.evaluate-conditional-relevance + [ $(instance).all-properties ] + : [ configure.get-relevant-features ] ] ; } diff --git a/src/build/feature.jam b/src/build/feature.jam index c4f681867..d833d70e4 100644 --- a/src/build/feature.jam +++ b/src/build/feature.jam @@ -662,6 +662,10 @@ rule subfeature ( local f = [ utility.ungrist $(feature) ] ; feature $(f)-$(subfeature-name) : $(subvalues) : $(attributes) subfeature ; + # Features and subfeatures are always relevent as a group + .feature-dependencies.$(f) += $(f)-$(subfeature-name) ; + .feature-dependencies.$(f)-$(subfeature-name) += $(f) ; + # Now make sure the subfeature values are known. extend-subfeature $(feature) $(value-string) : $(subfeature) : $(subvalues) ; } @@ -692,6 +696,10 @@ rule compose ( composite-property : component-properties * ) errors.error composite property "$(composite-property)" cannot have itself as a component ; } $(composite-property).components = $(component-properties) ; + + # A composite feature is relevant if any composed feature is relevant + local component-features = [ sequence.transform utility.ungrist : $(component-properties:G) ] ; + .feature-dependencies.$(component-features) += [ utility.ungrist $(feature) ] ; } @@ -1161,6 +1169,41 @@ rule split ( property-set ) return $(result) ; } +# Returns all the features that also must be relevant when these features are relevant +rule expand-relevant ( features * ) +{ + local conditional ; + local result ; + for f in $(features) + { + # This looks like a conditional, even though it isn't really. + # (Free features can never be used in conditionals) + local split = [ MATCH "^(.*):(.*)$" : $(f) ] ; + if $(split) + { + local-dependencies.$(split[1]) += $(split[2]) ; + conditional += local-dependencies.$(split[1]) ; + } + else + { + result += $(f) ; + } + } + local queue = $(result) ; + while $(queue) + { + local added = [ set.difference + $(.feature-dependencies.$(queue)) + $(local-dependencies.$(queue)) + : $(result) ] ; + result += $(added) ; + queue = $(added) ; + } + # Clean up local map + $(conditional) = ; + return $(result) ; +} + # Tests of module feature. # diff --git a/src/build/generators.jam b/src/build/generators.jam index c26db7257..d00f5242c 100644 --- a/src/build/generators.jam +++ b/src/build/generators.jam @@ -167,8 +167,10 @@ class generator import utility ; import path ; import property ; + import property-set ; import sequence ; import set ; + import toolset ; import type ; import virtual-target ; @@ -236,6 +238,10 @@ class generator # Note that 'transform' here, is the same as 'for_each'. sequence.transform type.validate : $(self.source-types) ; sequence.transform type.validate : $(self.target-types) ; + + local relevant-for-generator = + [ sequence.transform utility.ungrist : $(requirements:G) ] ; + self.relevant-features = [ property-set.create $(relevant-for-generator) ] ; } ################# End of constructor ################# @@ -406,10 +412,10 @@ class generator } local result ; - if $(consumed) + if $(consumed[2]) { - result = [ construct-result $(consumed) : $(project) $(name) : - $(property-set) ] ; + result = [ construct-result $(consumed[2-]) : $(project) $(name) : + [ $(property-set).add $(consumed[1]) ] ] ; } if $(result) @@ -421,7 +427,11 @@ class generator generators.dout [ indent ] " FAILURE" ; } generators.dout ; - return $(result) ; + if $(result) + { + # Make sure that we propagate usage-requirements up the stack. + return [ $(result[1]).add $(consumed[1]) ] $(result[2-]) ; + } } # Constructs the dependency graph to be returned by this generator. @@ -443,6 +453,11 @@ class generator ) { local result ; + + local relevant = [ toolset.relevant $(self.rule-name) ] ; + relevant = [ $(relevant).add $(self.relevant-features) ] ; + property-set = [ $(property-set).add $(relevant) ] ; + # If this is a 1->1 transformation, apply it to all consumed targets in # order. if ! $(self.source-types[2]) && ! $(self.composing) @@ -458,7 +473,10 @@ class generator result += [ generated-targets $(consumed) : $(property-set) : $(project) $(name) ] ; } - return $(result) ; + if $(result) + { + return $(relevant) $(result) ; + } } # Determine target name from fullname (maybe including path components) @@ -576,6 +594,7 @@ class generator { local _consumed ; local missing-types ; + local usage-requirements ; if $(sources[2]) { @@ -588,6 +607,7 @@ class generator local temp = [ consume-directly $(sources) ] ; if $(temp[1]) { + usage-requirements = [ property-set.empty ] ; _consumed = $(temp[1]) ; } missing-types = $(temp[2-]) ; @@ -613,7 +633,7 @@ class generator # everything to the required type. There is no need to rerun it on # targets of different types. - # NOTE: ignoring usage requirements. + usage-requirements = $(transformed[1]) ; for local t in $(transformed[2-]) { if [ $(t).type ] in $(missing-types) @@ -623,7 +643,7 @@ class generator } } - return [ sequence.unique $(_consumed) ] ; + return $(usage-requirements) [ sequence.unique $(_consumed) ] ; } # Converts several files to consumable types. Called for composing @@ -638,10 +658,11 @@ class generator if ! $(self.source-types) { # Anything is acceptible - return $(sources) ; + return [ property-set.empty ] $(sources) ; } else { + local usage-requirements = [ property-set.empty ] ; local acceptible-types = [ sequence.unique [ sequence.transform type.all-derived : $(self.source-types) ] ] ; for local source in $(sources) @@ -661,13 +682,17 @@ class generator { generators.dout [ indent ] " failed to convert " $(source) ; } + else + { + usage-requirements = [ $(usage-requirements).add $(transformed[1]) ] ; + } } else { result += $(source) ; } } - return [ sequence.unique $(result) : stable ] ; + return $(usage-requirements) [ sequence.unique $(result) : stable ] ; } } diff --git a/src/build/property-set.jam b/src/build/property-set.jam index feb4fb42e..194b3e0bc 100644 --- a/src/build/property-set.jam +++ b/src/build/property-set.jam @@ -34,6 +34,7 @@ class property-set { import errors ; import feature ; + import modules ; import path ; import property ; import property-set ; @@ -86,6 +87,26 @@ class property-set return $(self.free) ; } + # Returns relevant base properties + rule base-relevant ( ) + { + if ! $(self.relevant-initialized) + { + init-relevant ; + } + return $(self.base-relevant) ; + } + + # Returns all relevant properties + rule relevant + { + if ! $(self.relevant-initialized) + { + init-relevant ; + } + return $(self.relevant) ; + } + # Returns dependency properties. # rule dependency ( ) @@ -215,7 +236,7 @@ class property-set { if ! $(self.as-path) { - self.as-path = [ property.as-path [ base ] ] ; + self.as-path = [ property.as-path [ base-relevant ] ] ; } return $(self.as-path) ; } @@ -345,6 +366,30 @@ class property-set self.base-initialized = true ; } + rule init-relevant ( ) + { + local relevant-features = [ get ] ; + relevant-features = [ feature.expand-relevant $(relevant-features) ] ; + relevant-features = <$(relevant-features)> ; + ignore-relevance = [ modules.peek property-set : .ignore-relevance ] ; + for local p in $(self.raw) + { + if $(ignore-relevance) || $(p:G) in $(relevant-features) + { + local att = [ feature.attributes $(p:G) ] ; + if ! ( incidental in $(att) ) + { + self.relevant += $(p) ; + if ! ( free in $(att) ) + { + self.base-relevant += $(p) ; + } + } + } + } + self.relevant-initialized = true ; + } + rule init-dependency ( ) { for local p in $(self.raw) @@ -369,7 +414,7 @@ class property-set # characters as well, e.g. free or indirect properties. Indirect # properties for example contain a full Jamfile path in their value # which on Windows file systems contains ':' as the drive separator. - if [ MATCH (:) : $(p:G=) ] || $(p:G) = + if ( [ MATCH (:) : $(p:G=) ] && ! ( free in [ feature.attributes $(p:G) ] ) ) || $(p:G) = { self.conditional += $(p) ; } @@ -382,6 +427,13 @@ class property-set } } +# This is a temporary measure to help users work around +# any problems. Remove it once we've verified that +# everything works. +if --ignore-relevance in [ modules.peek : ARGV ] +{ + .ignore-relevance = true ; +} # Creates a new 'property-set' instance for the given raw properties or returns # an already existing ones. diff --git a/src/build/property.jam b/src/build/property.jam index 4be08eeb7..c172bd253 100644 --- a/src/build/property.jam +++ b/src/build/property.jam @@ -70,7 +70,7 @@ rule evaluate-conditionals-in-context ( properties * : context * ) local indirect ; for local p in $(properties) { - if [ MATCH (:<) : $(p) ] + if [ MATCH (:<) : $(p) ] && ! free in [ feature.attributes $(p:G) ] { conditionals += $(p) ; } @@ -155,6 +155,36 @@ rule evaluate-conditionals-in-context ( properties * : context * ) } +# Returns properties indicating how the conditionals in +# properties affect feature relevance. If the optional argument cond +# is passed, it is treated as extra conditions for all properties. +# +rule evaluate-conditional-relevance ( properties * : cond * ) +{ + cond = [ sequence.transform utility.ungrist : $(cond:G) ] ; + local result ; + for local p in $(properties) + { + # Separate condition and property. + local s = [ MATCH ^(.*):(<.*) : $(p) ] ; + if ! $(s) || free in [ feature.attributes $(p:G) ] + { + local value = [ utility.ungrist $(p:G) ] ; + result += $(value):$(cond) ; + } + else + { + local condition = [ regex.split $(s[1]) "," ] ; + condition = [ MATCH ^!?(.*) : $(condition) ] ; + condition = [ sequence.transform utility.ungrist : $(condition:G) ] $(cond) ; + local value = [ utility.ungrist $(s[2]:G) ] ; + result += $(value):$(condition) ; + } + } + return [ sequence.unique $(result) ] ; +} + + rule expand-subfeatures-in-conditions ( properties * ) { local result ; diff --git a/src/build/targets.jam b/src/build/targets.jam index 0964b0d86..6ffc082a4 100644 --- a/src/build/targets.jam +++ b/src/build/targets.jam @@ -191,6 +191,7 @@ class project-target : abstract-target import property-set ; import set ; import sequence ; + import toolset ; import "class" : new ; rule __init__ ( name : project-module parent-project ? @@ -584,6 +585,8 @@ class project-target : abstract-target IMPORT $(parent-module) : $(user-rules) : $(this-module) : $(user-rules) ; EXPORT $(this-module) : $(user-rules) ; + + toolset.inherit-flags $(this-module) : $(parent-module) ; } } @@ -621,10 +624,11 @@ class main-target : abstract-target { import assert ; import feature ; - import print ; import property-set ; import sequence ; + import set ; import targets : start-building end-building ; + import utility ; rule __init__ ( name : project ) { @@ -719,6 +723,43 @@ class main-target : abstract-target } } + # Features are relevant here if they could affect alternative + # selection. That is, base, non-conditional properties that + # are not identical in all target alternatives. + rule relevant-features ( ) + { + if $(self.alternatives[2-]) + { + if $(self.relevant-features) + { + return $(self.relevant-features) ; + } + local all-properties ; + for t in $(self.alternatives) + { + local ps = [ $(t).requirements ] ; + ps = [ property-set.create [ $(ps).non-conditional ] ] ; + all-properties += [ $(ps).base ] ; + } + all-properties = [ sequence.unique $(all-properties) ] ; + local result ; + for t in $(self.alternatives) + { + local ps = [ $(t).requirements ] ; + ps = [ property-set.create [ $(ps).non-conditional ] ] ; + local properties = [ set.difference $(all-properties) : [ $(ps).base ] ] ; + result += $(properties:G) ; + } + result = [ sequence.transform utility.ungrist : [ sequence.unique $(result) ] ] ; + self.relevant-features = [ property-set.create $(result) ] ; + return $(self.relevant-features) ; + } + else + { + return [ property-set.empty ] ; + } + } + rule apply-default-build ( property-set ) { return [ targets.apply-default-build $(property-set) : @@ -735,11 +776,12 @@ class main-target : abstract-target start-building $(__name__) ; local all-property-sets = [ apply-default-build $(property-set) ] ; + local relevant = [ relevant-features ] ; local usage-requirements = [ property-set.empty ] ; local result ; for local p in $(all-property-sets) { - local r = [ generate-really $(p) ] ; + local r = [ generate-really [ $(p).add $(relevant) ] ] ; if $(r) { usage-requirements = [ $(usage-requirements).add $(r[1]) ] ; @@ -1317,6 +1359,15 @@ class basic-target : abstract-target local gur = $(result[1]) ; result = $(result[2-]) ; + # Relevant is automatically applied to usage requirements + # and only applies for propagated features + local relevant = [ propagated-relevant + [ $(gur).get ] + [ $(rproperties).get ] ] ; + gur = [ property-set.create + [ property.change [ $(gur).raw ] : ] + $(relevant) ] ; + if $(self.always) { for local t in $(result) @@ -1409,6 +1460,22 @@ class basic-target : abstract-target [ $(self.usage-requirements).evaluate-conditionals $(rproperties) ] ; + # Filter out non-propagated properties + local relevant ; + for local r in [ $(xusage-requirements).get ] + { + local check = [ MATCH "(.*):(.*)" : $(r) ] ; + if $(check) { check = $(check[2]) ; } + else { check = $(r) ; } + if propagated in [ feature.attributes <$(check)> ] + { + relevant += $(r) ; + } + } + xusage-requirements = [ property-set.create + [ property.change [ $(xusage-requirements).raw ] : ] + $(relevant) ] ; + # We generate all dependency properties and add them, as well as their # usage requirements, to the result. local extra ; @@ -1448,6 +1515,19 @@ class basic-target : abstract-target return [ $(result).add [ property-set.create $(raw) ] ] ; } + local rule propagated-relevant ( values * ) + { + local result ; + for local v in [ feature.expand-relevant $(values) ] + { + if propagated in [ feature.attributes <$(v)> ] + { + result += $(v) ; + } + } + return $(result) ; + } + # Creates new subvariant instances for 'targets'. # 'root-targets' - virtual targets to be returned to dependants # 'all-targets' - virtual targets created while building this main target @@ -1594,7 +1674,8 @@ rule main-target-requirements ( import errors ; errors.error "Conflicting requirements for target:" $(requirements) ; } - return [ $(requirements).add [ toolset.requirements ] ] ; + local result = [ $(requirements).add [ toolset.requirements ] ] ; + return [ $(result).add-raw [ property.evaluate-conditional-relevance [ $(result).raw ] ] ] ; } @@ -1617,7 +1698,10 @@ rule main-target-usage-requirements ( $(specification) : [ $(project).project-module ] [ $(project).get location ] ] ; - return [ $(project-usage-requirements).add $(usage-requirements) ] ; + local result = [ $(project-usage-requirements).add $(usage-requirements) ] ; + local relevant = + [ property.evaluate-conditional-relevance [ $(result).raw ] ] ; + return [ $(result).add-raw $(relevant) ] ; } diff --git a/src/build/toolset.jam b/src/build/toolset.jam index a942cd906..d5b326488 100644 --- a/src/build/toolset.jam +++ b/src/build/toolset.jam @@ -19,6 +19,7 @@ import set ; import property-set ; import order ; import "class" : new ; +import utility ; .flag-no = 1 ; @@ -76,6 +77,36 @@ rule pop-checking-for-flags-module ( ) } +# Specifies features that are referenced by the action rule. +# This is necessary in order to detect that these features +# are relevant. +# +rule uses-features ( rule-or-module : features * : unchecked ? ) +{ + local caller = [ CALLER_MODULE ] ; + if ! [ MATCH ".*([.]).*" : $(rule-or-module) ] + && [ MATCH "(Jamfile<.*)" : $(caller) ] + { + # Unqualified rule name, used inside Jamfile. Most likely used with + # 'make' or 'notfile' rules. This prevents setting flags on the entire + # Jamfile module (this will be considered as rule), but who cares? + # Probably, 'flags' rule should be split into 'flags' and + # 'flags-on-module'. + rule-or-module = $(caller).$(rule-or-module) ; + } + else + { + local module_ = [ MATCH "([^.]*).*" : $(rule-or-module) ] ; + if $(unchecked) != unchecked + && $(.flags-module-checking[1]) != unchecked + && $(module_) != $(caller) + { + errors.error "Module $(caller) attempted to set flags for module $(module_)" ; + } + } + .uses-features.$(rule-or-module) += $(features) ; +} + # Specifies the flags (variables) that must be set on targets under certain # conditions, described by arguments. # @@ -399,6 +430,34 @@ rule relevant-features ( rule-or-module ) } } +# Returns a list of all the features which were +# passed to uses-features. +local rule used-features ( rule-or-module ) +{ + if ! $(.used-features.$(rule-or-module)) + { + local result = $(.uses-features.$(rule-or-module)) ; + + # Strip away last dot separated part and recurse. + local next = [ MATCH ^(.+)\\.([^\\.])* : $(rule-or-module) ] ; + if $(next) + { + result += [ used-features $(next[1]) ] ; + } + result = [ sequence.unique $(result) ] ; + if $(result[1]) = "" + { + result = $(result) ; + } + .used-features.$(rule-or-module) = $(result) ; + return $(result) ; + } + else + { + return $(.used-features.$(rule-or-module)) ; + } +} + rule filter-property-set ( rule-or-module : property-set ) { local key = .filtered.property-set.$(rule-or-module).$(property-set) ; @@ -454,6 +513,23 @@ rule set-target-variables ( rule-or-module targets + : property-set ) } +# Returns a property-set indicating which features are relevant +# for the given rule. +# +rule relevant ( rule-name ) +{ + if ! $(.relevant-features-ps.$(rule-name)) + { + local features = [ sequence.transform utility.ungrist : + [ relevant-features $(rule-name) ] + [ used-features $(rule-name) ] ] ; + .relevant-features-ps.$(rule-name) = + [ property-set.create $(features) ] ; + } + return $(.relevant-features-ps.$(rule-name)) ; +} + + # Make toolset 'toolset', defined in a module of the same name, inherit from # 'base'. # 1. The 'init' rule from 'base' is imported into 'toolset' with full name. diff --git a/src/build/virtual-target.jam b/src/build/virtual-target.jam index 2d139bd7f..cb8128362 100644 --- a/src/build/virtual-target.jam +++ b/src/build/virtual-target.jam @@ -999,10 +999,8 @@ rule register ( target ) { local ps1 = [ $(a1).properties ] ; local ps2 = [ $(a2).properties ] ; - local p1 = [ $(ps1).base ] [ $(ps1).free ] [ set.difference - [ $(ps1).dependency ] : [ $(ps1).incidental ] ] ; - local p2 = [ $(ps2).base ] [ $(ps2).free ] [ set.difference - [ $(ps2).dependency ] : [ $(ps2).incidental ] ] ; + local p1 = [ $(ps1).relevant ] ; + local p2 = [ $(ps2).relevant ] ; if $(p1) = $(p2) { result = $(t) ; diff --git a/src/tools/bison.jam b/src/tools/bison.jam index 0689d4bd8..96b86a327 100644 --- a/src/tools/bison.jam +++ b/src/tools/bison.jam @@ -4,8 +4,8 @@ import generators ; import feature ; +import toolset : flags ; import type ; -import property ; feature.feature bison.prefix : : free ; type.register Y : y ; @@ -17,16 +17,10 @@ rule init ( ) { } -rule bison ( dst dst_header : src : properties * ) -{ - local r = [ property.select bison.prefix : $(properties) ] ; - if $(r) - { - PREFIX_OPT on $(<) = -p $(r:G=) ; - } -} +flags bison.bison PREFIX ; +_ = " " ; actions bison { - bison $(PREFIX_OPT) -d -o $(<[1]) $(>) + bison -p$(_)$(PREFIX) -d -o $(<[1]) $(>) } diff --git a/src/tools/doxygen.jam b/src/tools/doxygen.jam index 0594e5363..19de6d0ec 100644 --- a/src/tools/doxygen.jam +++ b/src/tools/doxygen.jam @@ -274,6 +274,7 @@ rule translate-path ( path ) } } +toolset.uses-features doxygen.headers-to-doxyfile : "" ; # Generates a doxygen configuration file (doxyfile) given a set of C++ sources # and a property list that may contain features. @@ -321,6 +322,7 @@ rule headers-to-doxyfile ( target : sources * : properties * ) print.text $(text) : true ; } +toolset.uses-features doxygen.run : "" ; # Run Doxygen. See doxygen-action for a description of the strange properties of # this rule. @@ -406,6 +408,7 @@ rule collect ( target : source : properties * ) : doxygen.xml.path=$(native-path) ; } +toolset.uses-features doxygen.xml-to-boostbook : ; # Translate Doxygen XML into BoostBook. # diff --git a/src/tools/features/relevant-feature.jam b/src/tools/features/relevant-feature.jam new file mode 100644 index 000000000..f55bd7f4c --- /dev/null +++ b/src/tools/features/relevant-feature.jam @@ -0,0 +1,10 @@ +# Copyright 2017 Steven Watanabe +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Identifies relevant features. + +import feature ; + +feature.feature relevant : : incidental free ; diff --git a/src/tools/features/threadapi-feature.jam b/src/tools/features/threadapi-feature.jam index 1a2b0923d..0f9d42fa5 100644 --- a/src/tools/features/threadapi-feature.jam +++ b/src/tools/features/threadapi-feature.jam @@ -25,5 +25,5 @@ rule detect ( properties * ) local ps = [ property-set.create $(properties) ] ; local api = [ $(ps).get ] ; if ! $(api) { api = [ get-default $(ps) ] ; } - return $(api) ; + return $(api) threadapi:target-os ; } diff --git a/src/tools/gcc.jam b/src/tools/gcc.jam index 6ba56967e..e9e40aa5a 100644 --- a/src/tools/gcc.jam +++ b/src/tools/gcc.jam @@ -550,8 +550,8 @@ class gcc-pch-generator : pch-generator # Return result of base class and pch-file property as # usage-requirements. return - [ property-set.create $(pch-file) -Winvalid-pch ] - $(pch-file) + [ $(pch-file[1]).add-raw $(pch-file[2-]) -Winvalid-pch ] + $(pch-file[2-]) ; } diff --git a/src/tools/generators/archive-generator.jam b/src/tools/generators/archive-generator.jam index 88ef16559..57a46bf92 100644 --- a/src/tools/generators/archive-generator.jam +++ b/src/tools/generators/archive-generator.jam @@ -11,6 +11,7 @@ import generators ; # class archive-generator : generator { + import generators ; import property-set ; rule __init__ ( id composing ? : source-types + : target-types + @@ -56,9 +57,7 @@ class archive-generator : generator } } - usage-requirements = [ property-set.create $(usage-requirements) ] ; - - return $(usage-requirements) $(result) ; + return [ generators.add-usage-requirements $(result) : $(usage-requirements) ] ; } } diff --git a/src/tools/generators/lib-generator.jam b/src/tools/generators/lib-generator.jam index f520b6102..e4ba23e2c 100644 --- a/src/tools/generators/lib-generator.jam +++ b/src/tools/generators/lib-generator.jam @@ -54,8 +54,9 @@ class lib-generator : generator } property-set = [ $(property-set).add-raw LIB ] ; # Construct the target. - return [ generators.construct $(project) $(name) : $(actual-type) + local result = [ generators.construct $(project) $(name) : $(actual-type) : $(property-set) : $(sources) ] ; + return [ $(result[1]).add-raw link ] $(result[2-]) ; } } diff --git a/src/tools/generators/linking-generator.jam b/src/tools/generators/linking-generator.jam index 0c9d38f3e..2d905faf6 100644 --- a/src/tools/generators/linking-generator.jam +++ b/src/tools/generators/linking-generator.jam @@ -83,11 +83,12 @@ class linking-generator : generator local ur ; if $(result) { - ur = [ extra-usage-requirements $(result) : $(property-set) ] ; + ur = [ extra-usage-requirements $(result[2-]) : $(property-set) ] ; ur = [ $(ur).add [ property-set.create $(extra-xdll-paths) ] ] ; + ur = [ $(ur).add $(result[1]) ] ; } - return $(ur) $(result) ; + return $(ur) $(result[2-]) ; } rule extra-usage-requirements ( created-targets * : property-set ) diff --git a/src/tools/generators/searched-lib-generator.jam b/src/tools/generators/searched-lib-generator.jam index 174d137e3..dc451970d 100644 --- a/src/tools/generators/searched-lib-generator.jam +++ b/src/tools/generators/searched-lib-generator.jam @@ -38,7 +38,7 @@ class searched-lib-generator : generator local search = [ feature.get-values : $(properties) ] ; - local a = [ new null-action $(property-set) ] ; + local a = [ new null-action [ $(property-set).add-raw link ] ] ; local lib-name = [ feature.get-values : $(properties) ] ; lib-name ?= $(name) ; local t = [ new searched-lib-target $(lib-name) : $(project) @@ -47,7 +47,7 @@ class searched-lib-generator : generator # lib png : z : png ; # the 'z' target should be returned, so that apps linking to 'png' # will link to 'z', too. - return [ property-set.create $(search) ] + return [ property-set.create $(search) link ] [ virtual-target.register $(t) ] $(sources) ; } } diff --git a/src/tools/lex.jam b/src/tools/lex.jam index 75d641318..e85d1d1ad 100644 --- a/src/tools/lex.jam +++ b/src/tools/lex.jam @@ -5,8 +5,7 @@ import type ; import generators ; import feature ; -import property ; - +import toolset : flags ; feature.feature flex.prefix : : free ; type.register LEX : l ; @@ -18,14 +17,7 @@ rule init ( ) { } -rule lex ( target : source : properties * ) -{ - local r = [ property.select flex.prefix : $(properties) ] ; - if $(r) - { - PREFIX on $(<) = $(r:G=) ; - } -} +flags lex.lex PREFIX ; actions lex { diff --git a/src/tools/make.jam b/src/tools/make.jam index 40b59faf3..7c9a7ca68 100644 --- a/src/tools/make.jam +++ b/src/tools/make.jam @@ -17,6 +17,8 @@ import targets ; class make-target-class : basic-target { import "class" : new ; + import indirect ; + import toolset ; import type ; import virtual-target ; @@ -34,10 +36,11 @@ class make-target-class : basic-target # below. local m = [ MATCH ^@(.*) : $(action-name) ] ; - local a = [ new action $(source-targets) : $(m[1]) : $(property-set) ] ; + local relevant = [ toolset.relevant [ indirect.get-rule $(m[1]) ] ] ; + local a = [ new action $(source-targets) : $(m[1]) : [ $(property-set).add $(relevant) ] ] ; local t = [ new file-target $(self.name) exact : [ type.type $(self.name) ] : $(self.project) : $(a) ] ; - return [ property-set.empty ] [ virtual-target.register $(t) ] ; + return $(relevant) [ virtual-target.register $(t) ] ; } } diff --git a/src/tools/mpi.jam b/src/tools/mpi.jam index 1ccc54133..a4d29340e 100644 --- a/src/tools/mpi.jam +++ b/src/tools/mpi.jam @@ -595,6 +595,10 @@ feature mpi:processes : : free incidental ; # apply to mpi.capture output at the moment. # Redo this explicitly. toolset.flags mpi.capture-output ARGS ; +toolset.uses-features mpi.capture-output : + + ; + rule capture-output ( target : sources * : properties * ) { # Use the standard capture-output rule to run the tests diff --git a/src/tools/msvc.jam b/src/tools/msvc.jam index f096e64f4..9365a7e12 100644 --- a/src/tools/msvc.jam +++ b/src/tools/msvc.jam @@ -527,6 +527,7 @@ actions compile.rc $(.SETUP) $(.RC) -l 0x409 -U$(UNDEFS) -D$(DEFINES) -I"$(INCLUDES:W)" -fo "$(<:W)" "$(>:W)" } +toolset.uses-features msvc.link : ; rule link ( targets + : sources * : properties * ) { @@ -706,7 +707,7 @@ class msvc-pch-generator : pch-generator : $(pch-header) ] ; local pch-file ; - for local g in $(generated) + for local g in $(generated[2-]) { if [ type.is-derived [ $(g).type ] PCH ] { @@ -714,8 +715,8 @@ class msvc-pch-generator : pch-generator } } - return [ property-set.create $(pch-header) - $(pch-file) ] $(generated) ; + return [ $(generated[1]).add-raw $(pch-header) + $(pch-file) ] $(generated[2-]) ; } } @@ -878,7 +879,7 @@ local rule set-setup-command ( targets * : properties * ) if ! $($(key)) { properties = [ feature.expand $(properties) ] ; - properties = [ property.select : $(properties) ] ; + properties = [ property.select : $(properties) ] ; local ps = [ property-set.create $(properties) $(setup-options) ] ; local original = [ virtual-target.from-file $(setup-script) : [ path.pwd ] : $(.project) ] ; local action = [ new non-scanning-action $(original) : msvc.adjust-setup-command : $(ps) ] ; @@ -1422,8 +1423,8 @@ class msvc-linking-generator : linking-generator if $(result) { - local name-main = [ $(result[0]).name ] ; - local action = [ $(result[0]).action ] ; + local name-main = [ $(result[1]).name ] ; + local action = [ $(result[1]).action ] ; if [ $(property-set).get ] = "on" { diff --git a/src/tools/python.jam b/src/tools/python.jam index c9f6f4c25..0459f8575 100644 --- a/src/tools/python.jam +++ b/src/tools/python.jam @@ -1243,6 +1243,10 @@ local rule pyd-pythonpath ( source ) toolset.flags python.capture-output ARGS ; toolset.flags python.capture-output INPUT_FILES ; +toolset.uses-features python.capture-output : + + ; + rule capture-output ( target : sources * : properties * ) { # Setup up a proper DLL search path. Here, $(sources[1]) is a python module diff --git a/src/tools/stlport.jam b/src/tools/stlport.jam index ed0947ca5..4a08c8c9b 100644 --- a/src/tools/stlport.jam +++ b/src/tools/stlport.jam @@ -89,6 +89,9 @@ class stlport-target-class : basic-target local requirements ; requirements += $(self.version) ; + requirements += runtime-debugging ; + requirements += toolset ; + requirements += runtime-link ; self.requirements = [ property-set.create $(requirements) ] ; } diff --git a/src/tools/testing.jam b/src/tools/testing.jam index c7383cd03..a36258ed3 100644 --- a/src/tools/testing.jam +++ b/src/tools/testing.jam @@ -331,6 +331,8 @@ generators.register-standard testing.capture-output : EXE : RUN_OUTPUT ; # http://article.gmane.org/gmane.comp.lib.boost.build/6353). generators.register-standard testing.unit-test : EXE : UNIT_TEST ; +toolset.uses-features testing.expect-success : ; +toolset.uses-features testing.expect-failure : ; # The action rules called by generators. @@ -456,6 +458,9 @@ toolset.flags testing.capture-output ARGS ; toolset.flags testing.capture-output INPUT_FILES ; toolset.flags testing.capture-output LAUNCHER ; +toolset.uses-features testing.capture-output : + ; + if --remove-test-targets in [ modules.peek : ARGV ] { feature.set-default preserve-test-targets : off ; diff --git a/src/tools/xsltproc.jam b/src/tools/xsltproc.jam index b08089b92..f6bf1af98 100644 --- a/src/tools/xsltproc.jam +++ b/src/tools/xsltproc.jam @@ -151,6 +151,7 @@ IMPORT xsltproc : register-generator : : generators.register-xslt ; rule flags ( rulename ) { + toolset.uses-features $(rulename) : : unchecked ; toolset.flags $(rulename) XSL-PATH : : unchecked ; toolset.flags $(rulename) FLAGS : : unchecked ; } diff --git a/test/MockToolset.py b/test/MockToolset.py index aa280b83a..bc02bf8f5 100755 --- a/test/MockToolset.py +++ b/test/MockToolset.py @@ -214,8 +214,9 @@ generators.register-linker mock.link : LIB OBJ : EXE : mock ; generators.register-linker mock.link.dll : LIB OBJ : SHARED_LIB : mock ; generators.register-archiver mock.archive : OBJ : STATIC_LIB : mock ; -toolset.flags mock.compile INCLUDES ; -toolset.flags mock.compile DEFINES ; +toolset.flags mock.compile OPTIONS shared : -fPIC ; +toolset.flags mock.compile INCLUDES : ; +toolset.flags mock.compile DEFINES : ; actions compile.c { diff --git a/test/TestToolset.py b/test/TestToolset.py index 98bc7c82b..8915e78cc 100644 --- a/test/TestToolset.py +++ b/test/TestToolset.py @@ -60,7 +60,7 @@ def expand_properties(properties): result += ["target-os=" + default_target_os] return result -def compute_path(properties): +def compute_path(properties, target_type): path = "" if "variant=release" in properties: path += "/release" @@ -74,9 +74,9 @@ def compute_path(properties): path += "/cxxstd-latest-iso" if "link=static" in properties: path += "/link-static" - if "runtime-link=static" in properties: + if "runtime-link=static" in properties and target_type in ["exe"]: path += "/runtime-link-static" - if "strip=on" in properties: + if "strip=on" in properties and target_type in ["dll", "exe", "obj2"]: path += "/strip-on" if get_target_os(properties) != default_target_os: path += "/target-os-" + get_target_os(properties) @@ -96,16 +96,17 @@ def test_toolset(toolset, version, property_sets): for properties in property_sets: t.set_toolset(toolset + "-" + version, get_target_os(properties)) properties = adjust_properties(properties) - path = toolset.split("-")[0] + "-*" + version + compute_path(properties) + def path(t): + return toolset.split("-")[0] + "-*" + version + compute_path(properties, t) os.environ["B2_PROPERTIES"] = " ".join(expand_properties(properties)) t.run_build_system(["--user-config="] + properties) - t.expect_addition("bin/%s/lib.obj" % (path)) + t.expect_addition("bin/%s/lib.obj" % (path("obj"))) if "link=static" not in properties: - t.expect_addition("bin/%s/l1.dll" % (path)) + t.expect_addition("bin/%s/l1.dll" % (path("dll"))) else: - t.expect_addition("bin/%s/l1.lib" % (path)) - t.expect_addition("bin/%s/main.obj" % (path)) - t.expect_addition("bin/%s/test.exe" % (path)) + t.expect_addition("bin/%s/l1.lib" % (path("lib"))) + t.expect_addition("bin/%s/main.obj" % (path("obj2"))) + t.expect_addition("bin/%s/test.exe" % (path("exe"))) t.expect_nothing_more() t.rm("bin") diff --git a/test/command_line_properties.py b/test/command_line_properties.py index a69bf1282..ebb186ea4 100644 --- a/test/command_line_properties.py +++ b/test/command_line_properties.py @@ -63,8 +63,8 @@ def test_free(): actions run { echo $(OPTIONS) > $(<) } ''') t.run_build_system(['f1=x,/:-']) - t.expect_content("bin/*/output1.txt", "x,/:-") - t.expect_content("bin/*/output2.txt", "x,/:-") + t.expect_content("bin*/output1.txt", "x,/:-") + t.expect_content("bin*/output2.txt", "x,/:-") t.cleanup() def test_subfeature(): diff --git a/test/custom_generator.py b/test/custom_generator.py index f98a46878..00860f643 100644 --- a/test/custom_generator.py +++ b/test/custom_generator.py @@ -61,6 +61,6 @@ t.write("r.rcc", """ """) t.run_build_system() -t.expect_content("bin/$toolset/debug*/r.obj", "rc-object") +t.expect_content("bin/r.obj", "rc-object") t.cleanup() diff --git a/test/example_make.py b/test/example_make.py index e65158ec2..d72423cb2 100644 --- a/test/example_make.py +++ b/test/example_make.py @@ -13,5 +13,5 @@ import sys t = BoostBuild.Tester(['example.python.interpreter=%s' % sys.executable]) t.set_tree("../example/make") t.run_build_system() -t.expect_addition(["bin/$toolset/debug*/main.cpp"]) +t.expect_addition(["bin/main.cpp"]) t.cleanup() diff --git a/test/feature_relevant.py b/test/feature_relevant.py new file mode 100644 index 000000000..4e7a0c451 --- /dev/null +++ b/test/feature_relevant.py @@ -0,0 +1,142 @@ +#!/usr/bin/python + +# Copyright 2018 Steven Watanabe +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Tests the feature + +import BoostBuild + +t = BoostBuild.Tester(use_test_config=False) + +t.write("xxx.jam", """ +import type ; +import feature : feature ; +import toolset : flags ; +import generators ; +type.register XXX : xxx ; +type.register YYY : yyy ; +feature xxxflags : : free ; +generators.register-standard xxx.run : YYY : XXX ; +# xxxflags is relevant because it is used by flags +flags xxx.run OPTIONS : ; +actions run +{ + echo okay > $(<) +} +""") + +t.write("zzz.jam", """ +import xxx ; +import type ; +import feature : feature ; +import generators ; +type.register ZZZ : zzz ; +feature zzz.enabled : off on : propagated ; +# zzz.enabled is relevant because it is used in the generator's +# requirements +generators.register-standard zzz.run : XXX : ZZZ : on ; +actions run +{ + echo okay > $(<) +} +""") + +t.write("aaa.jam", """ +import zzz ; +import type ; +import feature : feature ; +import generators ; +import toolset : flags ; +type.register AAA : aaa ; +feature aaaflags : : free ; +generators.register-standard aaa.run : ZZZ : AAA ; +flags aaa.run OPTIONS : ; +actions run +{ + echo okay > $(<) +} +""") + +t.write("Jamroot.jam", """ +import xxx ; +import zzz ; +import aaa ; +import feature : feature ; + +# f1 is relevant, because it is composite and is relevant +feature f1 : n y : composite propagated ; +feature.compose y : -no1 ; +# f2 is relevant, because it is used in a conditional +feature f2 : n y : propagated ; +# f3 is relevant, because it is used to choose the target alternative +feature f3 : n y : propagated ; +# f4 is relevant, because it is marked as such explicitly +feature f4 : n y : propagated ; +# f5 is relevant because of the conditional usage-requirements +feature f5 : n y : propagated ; +# f6 is relevant because the indirect conditional indicates so +feature f6 : n y : propagated ; +# f7 is relevant because the icond7 says so +feature f7 : n y : propagated ; + +# The same as f[n], except not propagated +feature g1 : n y : composite ; +feature.compose y : -no1 ; +feature g2 : n y ; +feature g3 : n y ; +feature g4 : n y ; +feature g5 : n y ; +feature g6 : n y ; +feature g7 : n y ; + +project : default-build + y y y y y y y + y y y y y y y on ; + +rule icond6 ( properties * ) +{ + local result ; + if y in $(properties) || y in $(properties) + { + result += -yes6 ; + } + return $(result) + xxxflags:f6 + xxxflags:g6 ; +} + +rule icond7 ( properties * ) +{ + local result ; + if y in $(properties) || y in $(properties) + { + result += -yes7 ; + } + return $(result) + aaaflags:f7 + aaaflags:g7 ; +} + +zzz out : in.yyy + : y:-no2 y:-no2 f4 g4 + @icond6 + : + : y:-yes5 y:-yes5 @icond7 + ; +alias out : : n ; +alias out : : n ; +# Features that are relevant for out are also relevant for check-propagate +aaa check-propagate : out ; +""") + +t.write("in.yyy", "") + +t.run_build_system() +t.expect_addition("bin/f1-y/f2-y/f3-y/f4-y/f6-y/g1-y/g2-y/g3-y/g4-y/g6-y/out.xxx") +t.expect_addition("bin/f1-y/f2-y/f3-y/f4-y/f6-y/g1-y/g2-y/g3-y/g4-y/g6-y/zzz.enabled-on/out.zzz") +t.expect_addition("bin/f1-y/f2-y/f3-y/f4-y/f5-y/f6-y/f7-y/zzz.enabled-on/check-propagate.aaa") + +t.cleanup() diff --git a/test/gcc_runtime.py b/test/gcc_runtime.py index 28b6410a5..76c95e1af 100644 --- a/test/gcc_runtime.py +++ b/test/gcc_runtime.py @@ -20,9 +20,8 @@ t.expect_output_lines("warning: On gcc, DLLs can not be built with " t.expect_nothing_more() t.run_build_system(["link=static", "runtime-link=static"]) -binFolder = "bin/$toolset/debug*/link-static/runtime-link-static" -t.expect_addition("%s/hello.obj" % binFolder) -t.expect_addition("%s/hello.lib" % binFolder) +t.expect_addition("bin/$toolset/debug*/link-static/hello.obj") +t.expect_addition("bin/$toolset/debug*/link-static/hello.lib") t.expect_nothing_more() t.cleanup() diff --git a/test/generator_selection.py b/test/generator_selection.py index 64f9cc7b3..1ecca7100 100755 --- a/test/generator_selection.py +++ b/test/generator_selection.py @@ -87,9 +87,9 @@ my-obj other-obj : source.extension ; t.run_build_system() t.expect_output_lines("Generating a CPP file...") - t.expect_addition("bin/$toolset/debug*/dummy.my_obj") - t.expect_addition("Other/bin/$toolset/debug*/other-obj.cpp") - t.expect_addition("Other/bin/$toolset/debug*/other-obj.my_obj") + t.expect_addition("bin/dummy.my_obj") + t.expect_addition("Other/bin/other-obj.cpp") + t.expect_addition("Other/bin/other-obj.my_obj") t.expect_nothing_more() t.cleanup() @@ -139,8 +139,8 @@ yyy other : source.xxx2 ; """) t.run_build_system() - t.expect_addition("bin/$toolset/debug*/dummy.yyy") - t.expect_addition("Other/bin/$toolset/debug*/other.yyy") + t.expect_addition("bin/dummy.yyy") + t.expect_addition("Other/bin/other.yyy") t.expect_nothing_more() t.cleanup() diff --git a/test/generators_test.py b/test/generators_test.py index 7d0997404..a29a3a538 100644 --- a/test/generators_test.py +++ b/test/generators_test.py @@ -215,17 +215,17 @@ nm-exe e : e.cpp ; """) t.run_build_system() - t.expect_addition("bin/$toolset/debug*/" * BoostBuild.List("a.my_exe " + t.expect_addition("bin/" * BoostBuild.List("a.my_exe " "a.my_obj b.my_obj c.tui_h c.cpp c.my_obj d_parser.whl d_lexer.dlp " "d_parser.cpp d_lexer.cpp d_lexer.my_obj d_parser.lr0 d_parser.h " "d_parser.my_obj d_parser_symbols.h x.c x.my_obj y.x1 y.x2 y.cpp " "y.my_obj e.marked_cpp e.positions e.target_cpp e.my_obj e.my_exe " "f.my_exe obj_1.my_obj obj_2.my_obj")) - t.expect_addition("lib/bin/$toolset/debug*/" * BoostBuild.List("c.my_obj " + t.expect_addition("lib/bin/" * BoostBuild.List("c.my_obj " "auxilliary.my_lib")) t.expect_nothing_more() - folder = "bin/$toolset/debug*" + folder = "bin" t.expect_content_lines("%s/obj_1.my_obj" % folder, " Sources: 'z.cpp'") t.expect_content_lines("%s/obj_2.my_obj" % folder, " Sources: 'z.cpp'") t.expect_content_lines("%s/a.my_obj" % folder, " Sources: 'a.cpp'") @@ -311,7 +311,7 @@ ddd _xxx : _xxx._a ; def suffix(rename): if rename: return "_x" return "" - name = "bin/$toolset/debug*/_xxx" + name = "bin/_xxx" e = t.expect_addition e("%s%s._b1" % (name, suffix(rename1))) e("%s%s._b2" % (name, suffix(rename2))) diff --git a/test/inline.py b/test/inline.py index d0ce91ae8..03d91a5d0 100644 --- a/test/inline.py +++ b/test/inline.py @@ -21,12 +21,11 @@ int main() {} t.write("helper.cpp", "void helper() {}\n") t.run_build_system() -t.expect_addition("bin/$toolset/debug/link-static*/a__helper.lib") -t.rm("bin/$toolset/debug/link-static/a__helper.lib") -t.rm("bin/$toolset/debug/link-static/*/a__helper.lib") +t.expect_addition("bin/$toolset/debug*/a__helper.lib") +t.rm("bin/$toolset/debug*/a__helper.lib") t.run_build_system(["a__helper"]) -t.expect_addition("bin/$toolset/debug/link-static*/a__helper.lib") +t.expect_addition("bin/$toolset/debug*/a__helper.lib") t.rm("bin") @@ -41,8 +40,8 @@ exe a2 : a.cpp [ lib helper : helper.cpp ] ; t.run_build_system() t.expect_addition("bin/$toolset/debug/link-static*/a.exe") -t.expect_addition("bin/$toolset/debug/link-static*/a__helper.lib") -t.expect_addition("bin/$toolset/debug/link-static*/a2__helper.lib") +t.expect_addition("bin/$toolset/debug*/a__helper.lib") +t.expect_addition("bin/$toolset/debug*/a2__helper.lib") # Check that the 'alias' target does not change the name of inline targets, and @@ -58,6 +57,6 @@ t.run_build_system() t.expect_nothing_more() t.run_build_system(["a"]) -t.expect_addition("bin/$toolset/debug/link-static*/helper.lib") +t.expect_addition("bin/$toolset/debug*/helper.lib") t.cleanup() diff --git a/test/make_rule.py b/test/make_rule.py index 4a2e09ad9..ab994376e 100644 --- a/test/make_rule.py +++ b/test/make_rule.py @@ -28,8 +28,8 @@ make foo.bar : : creator : 12345678 ; """) t.run_build_system() -t.expect_addition("bin/$toolset/debug*/foo.bar") -t.fail_test(string.find(t.read("bin/$toolset/debug*/foo.bar"), "12345678") == -1) +t.expect_addition("bin/foo.bar") +t.fail_test(string.find(t.read("bin/foo.bar"), "12345678") == -1) # Regression test. Make sure that if a main target is requested two times, and diff --git a/test/project-test3/jamroot.jam b/test/project-test3/jamroot.jam index 3d4dfa19a..d7cd490eb 100644 --- a/test/project-test3/jamroot.jam +++ b/test/project-test3/jamroot.jam @@ -6,6 +6,7 @@ import os ; import gcc ; import property ; +import toolset ; rule properties-as-path ( properties * ) { @@ -21,6 +22,9 @@ rule properties-as-path ( properties * ) [ property.remove incidental : $(r) ] ] ; } +toolset.flags yfc-compile KNOWN-PROPERTIES : ; +toolset.flags yfc-link KNOWN-PROPERTIES : ; + rule yfc-compile ( target : sources * : property-set * ) { PROPERTIES on $(target) = [ properties-as-path $(property-set) ] ; diff --git a/test/project-test4/jamroot.jam b/test/project-test4/jamroot.jam index fbbe0abf1..d8cf571ae 100644 --- a/test/project-test4/jamroot.jam +++ b/test/project-test4/jamroot.jam @@ -5,6 +5,7 @@ import os ; import gcc ; import property ; +import toolset ; rule properties-as-path ( properties * ) { @@ -21,6 +22,10 @@ rule properties-as-path ( properties * ) } +toolset.flags yfc-compile KNOWN-PROPERTIES : ; +toolset.flags yfc-link KNOWN-PROPERTIES : ; + + rule yfc-compile ( target : sources * : property-set * ) { PROPERTIES on $(target) = [ properties-as-path $(property-set) ] ; @@ -60,4 +65,4 @@ if [ os.name ] = VMS } } -IMPORT $(__name__) : yfc-compile yfc-link : : yfc-compile yfc-link ; +#IMPORT $(__name__) : yfc-compile yfc-link : : yfc-compile yfc-link ; diff --git a/test/project_id.py b/test/project_id.py index 7f4070e07..6477f5957 100755 --- a/test/project_id.py +++ b/test/project_id.py @@ -98,7 +98,7 @@ project /project-a3 ; """) t.run_build_system() - t.expect_addition("bin/$toolset/b%d._b" % x for x in range(1, 8)) + t.expect_addition("bin/b%d._b" % x for x in range(1, 8)) t.expect_nothing_more() t.cleanup() @@ -280,7 +280,7 @@ bbb b-invalid-target : /foo//invalid ; """) t.run_build_system(["b1", "b2"]) - t.expect_addition("bin/$toolset/debug*/b%d._b" % x for x in range(1, 3)) + t.expect_addition("bin/b%d._b" % x for x in range(1, 3)) t.expect_nothing_more() t.run_build_system(["b-invalid"], status=1) diff --git a/test/project_root_rule.py b/test/project_root_rule.py index 956c8953b..503b3cad2 100644 --- a/test/project_root_rule.py +++ b/test/project_root_rule.py @@ -29,6 +29,6 @@ my-lib foo ; t.run_build_system(subdir="sub") -t.expect_addition("sub/bin/$toolset/debug/link-static*/foo.lib") +t.expect_addition("sub/bin/$toolset/debug*/foo.lib") t.cleanup() diff --git a/test/remove_requirement.py b/test/remove_requirement.py index 8009e0f64..6efd44116 100644 --- a/test/remove_requirement.py +++ b/test/remove_requirement.py @@ -12,6 +12,8 @@ t = BoostBuild.Tester(use_test_config=False) t.write("jamroot.jam", """ project : requirements multi debug:static ; +# Force link to be relevant +project : requirements shared:TEST_DLL ; build-project sub ; build-project sub2 ; diff --git a/test/rescan_header.py b/test/rescan_header.py index 37b37c7d4..1257a223c 100755 --- a/test/rescan_header.py +++ b/test/rescan_header.py @@ -35,7 +35,7 @@ obj test : test.cpp : header3.h ; """) t.run_build_system(["-j2"]) -t.expect_addition("bin/$toolset/debug*/header3.h") +t.expect_addition("bin/header3.h") t.expect_addition("bin/$toolset/debug*/test.obj") t.expect_nothing_more() @@ -72,9 +72,9 @@ obj test : test.cpp : """) t.run_build_system(["-j2", "test"]) -t.expect_addition("bin/$toolset/debug*/header1.h") -t.expect_addition("bin/$toolset/debug*/header2.h") -t.expect_addition("bin/$toolset/debug*/header3.h") +t.expect_addition("bin/header1.h") +t.expect_addition("bin/header2.h") +t.expect_addition("bin/header3.h") t.expect_addition("bin/$toolset/debug*/test.obj") t.expect_nothing_more() @@ -122,9 +122,9 @@ obj test : test.cpp : """) t.run_build_system(["-j2", "test"]) -t.expect_addition("bin/$toolset/debug*/header1.h") -t.expect_addition("bin/$toolset/debug*/header2.h") -t.expect_addition("bin/$toolset/debug*/header3.h") +t.expect_addition("bin/header1.h") +t.expect_addition("bin/header2.h") +t.expect_addition("bin/header3.h") t.expect_addition("bin/$toolset/debug*/test.obj") t.expect_nothing_more() @@ -184,7 +184,7 @@ exe test : test2.cpp test1.cpp : header3.h ; """) t.run_build_system(["-j2", "test"]) -t.expect_addition("bin/$toolset/debug*/header3.h") +t.expect_addition("bin/header3.h") t.expect_addition("bin/$toolset/debug*/test1.obj") t.expect_addition("bin/$toolset/debug*/test2.obj") t.expect_addition("bin/$toolset/debug*/test.exe") @@ -192,7 +192,7 @@ t.expect_nothing_more() t.touch("header3.in") t.run_build_system(["-j2", "test"]) -t.expect_touch("bin/$toolset/debug*/header3.h") +t.expect_touch("bin/header3.h") t.expect_touch("bin/$toolset/debug*/test1.obj") t.expect_touch("bin/$toolset/debug*/test2.obj") t.expect_touch("bin/$toolset/debug*/test.exe") @@ -256,7 +256,7 @@ exe test : test2.cpp test1.cpp : header2.h . ; """) t.run_build_system(["-j2", "test"]) -t.expect_addition("bin/$toolset/debug*/header2.h") +t.expect_addition("bin/header2.h") t.expect_addition("bin/$toolset/debug*/test1.obj") t.expect_addition("bin/$toolset/debug*/test2.obj") t.expect_addition("bin/$toolset/debug*/test.exe") diff --git a/test/source_order.py b/test/source_order.py index d3cc2ab20..f21710a8c 100755 --- a/test/source_order.py +++ b/test/source_order.py @@ -74,8 +74,8 @@ t.write("file2.c", "") t.write("file3.c", "") t.run_build_system() -t.expect_addition("bin/$toolset/debug*/check.order-test") -t.expect_content("bin/$toolset/debug*/check.order-test", """\ +t.expect_addition("bin/check.order-test") +t.expect_content("bin/check.order-test", """\ file2.c file1.c file3.c diff --git a/test/space_in_path.py b/test/space_in_path.py index f4c6c579a..7f0c041a3 100755 --- a/test/space_in_path.py +++ b/test/space_in_path.py @@ -36,7 +36,7 @@ os.environ["TMPDIR"] = tmpdir; # *nix try: t.run_build_system(["has space"]) - t.expect_addition("has space/bin/$toolset/debug*/test.txt") + t.expect_addition("has space/bin/test.txt") t.expect_addition("has space/bin/$toolset/debug*/test.passed") finally: if oldtmp is not None: diff --git a/test/static_and_shared_library.py b/test/static_and_shared_library.py index da010a241..5b3a6b73a 100755 --- a/test/static_and_shared_library.py +++ b/test/static_and_shared_library.py @@ -31,7 +31,7 @@ t.expect_nothing_more() reset() t.run_build_system(["link=static"], subdir="lib") -t.expect_addition("lib/bin/$toolset/debug/link-static*/" * BoostBuild.List( +t.expect_addition("lib/bin/$toolset/debug*/" * BoostBuild.List( "c.obj auxilliary1.lib auxilliary2.lib")) t.expect_nothing_more() diff --git a/test/suffix.py b/test/suffix.py index b6946a48a..b31dd1730 100644 --- a/test/suffix.py +++ b/test/suffix.py @@ -73,6 +73,6 @@ second a : a.cpp ; """) t.run_build_system() -t.expect_addition("bin/$toolset/debug*/a") +t.expect_addition("bin/a") t.cleanup() diff --git a/test/tag.py b/test/tag.py index 87f537c8c..adf2fce6f 100644 --- a/test/tag.py +++ b/test/tag.py @@ -91,11 +91,11 @@ __declspec (dllexport) void x () {} BoostBuild.List("bin/$toolset/release*/a_rs.exe") + BoostBuild.List("bin/$toolset/release*/b_rs.dll") + BoostBuild.List("c/a_rs.exe") + - BoostBuild.List("bin/$toolset/debug/link-static*/a_dt.exe") + - BoostBuild.List("bin/$toolset/debug/link-static*/b_dt.lib") + + BoostBuild.List("bin/$toolset/debug*/a_dt.exe") + + BoostBuild.List("bin/$toolset/debug*/b_dt.lib") + BoostBuild.List("c/a_dt.exe") + - BoostBuild.List("bin/$toolset/release/link-static*/a_rt.exe") + - BoostBuild.List("bin/$toolset/release/link-static*/b_rt.lib") + + BoostBuild.List("bin/$toolset/release*/a_rt.exe") + + BoostBuild.List("bin/$toolset/release*/b_rt.lib") + BoostBuild.List("c/a_rt.exe")) variants = ["debug", "release", "link=static,shared"] diff --git a/test/test_all.py b/test/test_all.py index 591b11aae..d443ef207 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -222,6 +222,7 @@ tests = ["absolute_sources", "expansion", "explicit", "feature_cxxflags", + "feature_relevant", "generator_selection", "generators_test", "implicit_dependency", From 02359cb669b88f9f347a145d5c267042414c1a72 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 13 Jan 2018 13:36:45 -0700 Subject: [PATCH 69/72] Add missed file that is necessary for building Boost.Dll on windows. --- src/tools/generators/lib-generator.jam | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/generators/lib-generator.jam b/src/tools/generators/lib-generator.jam index e4ba23e2c..079a8db17 100644 --- a/src/tools/generators/lib-generator.jam +++ b/src/tools/generators/lib-generator.jam @@ -52,7 +52,7 @@ class lib-generator : generator { actual-type = STATIC_LIB ; } - property-set = [ $(property-set).add-raw LIB ] ; + property-set = [ $(property-set).add-raw LIB link ] ; # Construct the target. local result = [ generators.construct $(project) $(name) : $(actual-type) : $(property-set) : $(sources) ] ; From 5cefb83f5cb5413296f95cc2c932336a3a98f666 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 13 Jan 2018 13:39:16 -0700 Subject: [PATCH 70/72] Always use a full three digit version for gcc. --- src/tools/gcc.jam | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/tools/gcc.jam b/src/tools/gcc.jam index e9e40aa5a..d62868003 100644 --- a/src/tools/gcc.jam +++ b/src/tools/gcc.jam @@ -101,8 +101,8 @@ rule init ( version ? : command * : options * : requirement * ) { local tool-command-string = \"$(tool-command)\" ; tool-command-string = $(tool-command-string:J=" ") ; - local tool-version = [ MATCH "^([0-9.]+)" : - [ SHELL "$(tool-command-string) -dumpversion" ] ] ; + local tool-version = [ dump-full-version + $(tool-command-string) ] ; if $(tool-version) != $(version) { # Permit a match betwen a two-digit version specified by the @@ -184,8 +184,7 @@ rule init ( version ? : command * : options * : requirement * ) { local machine = [ MATCH "^([^ ]+)" : [ SHELL "$(command-string) -dumpmachine" ] ] ; - version ?= [ MATCH "^([0-9.]+)" : - [ SHELL "$(command-string) -dumpversion" ] ] ; + version ?= [ dump-full-version $(command-string) ] ; switch $(machine:L) { case *mingw* : flavor ?= mingw ; @@ -275,6 +274,15 @@ if [ os.name ] = NT JAMSHELL = % ; } +local rule dump-full-version ( command-string ) +{ + # -dumpfullversion is only supported for gcc 7+. + # Passing both options works, as the first one that's + # recognized will be used. + return [ MATCH "^([0-9.]+)" : + [ SHELL "$(command-string) -dumpfullversion -dumpversion" ] ] ; +} + # Uses -print-prog-name to get the name of the tool. # Converts the path to native form if using cygwin. rule .get-prog-name ( command-string : tool : flavor ? ) From 94d2cfcdb7c9ff620d1afc065b1466640150bb86 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 13 Jan 2018 14:43:54 -0700 Subject: [PATCH 71/72] Rename zlib.py to avoid conflict with the builtin zlib module in python 2.7.14. --- test/{zlib.py => lib_zlib.py} | 0 test/test_all.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename test/{zlib.py => lib_zlib.py} (100%) diff --git a/test/zlib.py b/test/lib_zlib.py similarity index 100% rename from test/zlib.py rename to test/lib_zlib.py diff --git a/test/test_all.py b/test/test_all.py index d443ef207..cfb4c30c9 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -232,6 +232,7 @@ tests = ["absolute_sources", "inline", "libjpeg", "lib_source_property", + "lib_zlib", "library_chain", "library_property", "link", @@ -288,7 +289,6 @@ tests = ["absolute_sources", "using", "wrapper", "wrong_project", - "zlib" ] if os.name == "posix": From f5b5cace60f9232d80be0442c7c702a694297e40 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 13 Jan 2018 16:25:00 -0700 Subject: [PATCH 72/72] linking-generator and archive-generator always consider to be relevant. --- src/tools/generators/archive-generator.jam | 4 +++- src/tools/generators/linking-generator.jam | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/tools/generators/archive-generator.jam b/src/tools/generators/archive-generator.jam index 57a46bf92..1b8721802 100644 --- a/src/tools/generators/archive-generator.jam +++ b/src/tools/generators/archive-generator.jam @@ -26,6 +26,8 @@ class archive-generator : generator { sources += [ $(property-set).get ] ; + property-set = [ $(property-set).add-raw link ] ; + local result = [ generator.run $(project) $(name) : $(property-set) : $(sources) ] ; @@ -45,7 +47,7 @@ class archive-generator : generator # will link to the library, but it should not cause any harm. So, return # all LIB sources together with created targets, so that dependants link # to them. - local usage-requirements ; + local usage-requirements = link ; if [ $(property-set).get ] = static { for local t in $(sources) diff --git a/src/tools/generators/linking-generator.jam b/src/tools/generators/linking-generator.jam index 2d905faf6..23d0c1e8c 100644 --- a/src/tools/generators/linking-generator.jam +++ b/src/tools/generators/linking-generator.jam @@ -35,7 +35,7 @@ class linking-generator : generator sources += [ $(property-set).get ] ; # Add properties for all searched libraries. - local extra ; + local extra = link ; for local s in $(sources) { if [ $(s).type ] = SEARCHED_LIB @@ -84,8 +84,8 @@ class linking-generator : generator if $(result) { ur = [ extra-usage-requirements $(result[2-]) : $(property-set) ] ; - ur = [ $(ur).add - [ property-set.create $(extra-xdll-paths) ] ] ; + ur = [ $(ur).add-raw + link $(extra-xdll-paths) ] ; ur = [ $(ur).add $(result[1]) ] ; } return $(ur) $(result[2-]) ;