def test_alias_rule(t): """Basic alias rule test.""" t.write( "jamroot.jam", """\ exe a : a.cpp ; exe b : b.cpp ; exe c : c.cpp ; alias bin1 : a ; alias bin2 : a b ; alias src : s.cpp ; exe hello : hello.cpp src ; """) t.write("a.cpp", "int main() {}\n") t.copy("a.cpp", "b.cpp") t.copy("a.cpp", "c.cpp") t.copy("a.cpp", "hello.cpp") t.write("s.cpp", "") # Check that targets to which "bin1" refers are updated, and only those. t.run_build_system(["bin1"]) t.expect_addition(BoostBuild.List("bin/$toolset/debug*/") * "a.exe a.obj") t.ignore_addition('bin/*/a.rsp') t.ignore_addition('bin/*/a.*.rsp') t.expect_nothing_more() # Try again with "bin2" t.run_build_system(["bin2"]) t.expect_addition(BoostBuild.List("bin/$toolset/debug*/") * "b.exe b.obj") t.ignore_addition('bin/*/b.rsp') t.ignore_addition('bin/*/b.*.rsp') t.expect_nothing_more() # Try building everything, making sure 'hello' target is created. t.run_build_system() t.expect_addition(BoostBuild.List("bin/$toolset/debug*/") * \ "hello.exe hello.obj") t.ignore_addition('bin/*/hello.rsp') t.ignore_addition('bin/*/hello.*.rsp') t.expect_addition("bin/$toolset/debug*/s.obj") t.ignore_addition('bin/*/s.*.rsp') t.expect_addition(BoostBuild.List("bin/$toolset/debug*/") * "c.exe c.obj") t.ignore_addition('bin/*/c.rsp') t.ignore_addition('bin/*/c.*.rsp') t.expect_nothing_more()
t.run_build_system(["lib//b.obj"]) t.expect_addition("lib/bin/$toolset/debug/b.obj") t.expect_nothing_more() t.run_build_system(["--clean", "lib//b.obj"]) t.expect_removal("lib/bin/$toolset/debug/b.obj") t.expect_nothing_more() t.run_build_system(["lib//b.obj"]) t.expect_addition("lib/bin/$toolset/debug/b.obj") t.expect_nothing_more() t.run_build_system(["release", "lib2/helper//e.obj", "/lib3//f.obj"]) t.expect_addition("lib2/helper/bin/$toolset/release/e.obj") t.expect_addition("lib3/bin/$toolset/release/f.obj") t.expect_nothing_more() # Test project ids in command line work as well. t.set_tree("project-test3") t.run_build_system(["/lib2"]) t.expect_addition("lib2/bin/$toolset/debug/" * BoostBuild.List("c.obj d.obj l.exe")) t.expect_addition("bin/$toolset/debug/a.obj") t.expect_nothing_more() t.run_build_system(["lib"]) t.expect_addition("lib/bin/$toolset/debug/" * BoostBuild.List("b.obj m.exe")) t.expect_nothing_more() t.cleanup()
# Create a temporary working directory. t = BoostBuild.Tester() # Create the needed files. t.write("jamroot.jam", """ exe hello : hello.cpp ; """) t.write("hello.cpp", """ int main() {} """ # Run the build. t.run_build_system() # First, create a list of three pathnames. file_list = BoostBuild.List("bin/$toolset/debug/") * \ BoostBuild.List("hello.exe hello.obj") # Second, assert that those files were added as result of the last build system # invocation. t.expect_addition(file_list) # Invoke the build system once again. t.run_build_system("clean") # Check if the files added previously were removed. t.expect_removal(file_list) # Remove temporary directories. t.cleanup()
""") t.run_build_system('hardcode-dll-paths=false') t.expect_content("bin/r.test/$toolset/debug/r.output", "test input\nEXIT STATUS: 0\n") 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()
def test_tag_property(t): """Basic tag property test.""" t.write( "jamroot.jam", """\ import virtual-target ; rule tag ( name : type ? : property-set ) { local tags ; switch [ $(property-set).get <variant> ] { case debug : tags += d ; case release : tags += r ; } switch [ $(property-set).get <link> ] { case shared : tags += s ; case static : tags += t ; } if $(tags) { return [ virtual-target.add-prefix-and-suffix $(name)_$(tags:J="") : $(type) : $(property-set) ] ; } } # Test both fully-qualified and local name of the rule exe a : a.cpp : <tag>@$(__name__).tag ; lib b : a.cpp : <tag>@tag ; stage c : a ; """) t.write( "a.cpp", """\ int main() {} #ifdef _MSC_VER __declspec (dllexport) void x () {} #endif """) file_list = (BoostBuild.List("bin/$toolset/debug/a_ds.exe") + BoostBuild.List("bin/$toolset/debug/b_ds.dll") + BoostBuild.List("c/a_ds.exe") + 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("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("c/a_rt.exe")) variants = ["debug", "release", "link=static,shared"] t.run_build_system(variants) t.expect_addition(file_list) t.run_build_system(variants + ["clean"]) t.expect_removal(file_list)
def test_basic(): t = BoostBuild.Tester(pass_d0=False) __write_appender(t, "appender.jam") t.write("a.cpp", "") t.write("b.cxx", "") t.write("c.tui", "") t.write("d.wd", "") t.write("e.cpp", "") t.write("x.l", "") t.write("y.x_pro", "") t.write("z.cpp", "") t.write("lib/c.cpp", "int bar() { return 0; }\n") t.write("lib/jamfile.jam", "my-lib auxilliary : c.cpp ;") t.write( "jamroot.jam", r"""import appender ; import "class" : new ; import generators ; import type ; ################################################################################ # # We use our own custom EXE, LIB & OBJ target generators as using the regular # ones would force us to have to deal with different compiler/linker specific # 'features' that really have nothing to do with this test. For example, IBM XL # C/C++ for AIX, V12.1 (Version: 12.01.0000.0000) compiler exits with a non-zero # exit code and thus fails our build when run with a source file using an # unknown suffix like '.marked_cpp'. # ################################################################################ type.register MY_EXE : my_exe ; type.register MY_LIB : my_lib ; type.register MY_OBJ : my_obj ; appender.register compile-c : C : MY_OBJ ; appender.register compile-cpp : CPP : MY_OBJ ; appender.register link-lib composing : MY_OBJ : MY_LIB ; appender.register link-exe composing : MY_OBJ MY_LIB : MY_EXE ; ################################################################################ # # LEX --> C # ################################################################################ type.register LEX : l ; appender.register lex-to-c : LEX : C ; ################################################################################ # # /--> tUI_H --\ # tUI --< >--> CPP # \------------/ # ################################################################################ type.register tUI : tui ; type.register tUI_H : tui_h ; appender.register ui-to-cpp : tUI tUI_H : CPP ; appender.register ui-to-h : tUI : tUI_H ; ################################################################################ # # /--> X1 --\ # X_PRO --< >--> CPP # \--> X2 --/ # ################################################################################ type.register X1 : x1 ; type.register X2 : x2 ; type.register X_PRO : x_pro ; appender.register x1-x2-to-cpp : X1 X2 : CPP ; appender.register x-pro-to-x1-x2 : X_PRO : X1 X2 ; ################################################################################ # # When the main target type is NM_EXE, build OBJ from CPP-MARKED and not from # anything else, e.g. directly from CPP. # ################################################################################ type.register CPP_MARKED : marked_cpp : CPP ; type.register POSITIONS : positions ; type.register NM.TARGET.CPP : target_cpp : CPP ; type.register NM_EXE : : MY_EXE ; appender.register marked-to-target-cpp : CPP_MARKED : NM.TARGET.CPP ; appender.register cpp-to-marked-positions : CPP : CPP_MARKED POSITIONS ; class nm::target::cpp-obj-generator : generator { rule __init__ ( id ) { generator.__init__ $(id) : NM.TARGET.CPP : MY_OBJ ; generator.set-rule-name appender.appender ; } rule requirements ( ) { return <main-target-type>NM_EXE ; } rule run ( project name ? : properties * : source : multiple ? ) { if [ $(source).type ] = CPP { local converted = [ generators.construct $(project) : NM.TARGET.CPP : $(properties) : $(source) ] ; if $(converted) { return [ generators.construct $(project) : MY_OBJ : $(properties) : $(converted[2]) ] ; } } } } generators.register [ new nm::target::cpp-obj-generator target-obj ] ; generators.override target-obj : all ; ################################################################################ # # A more complex test case scenario with the following generators: # 1. WHL --> CPP, WHL_LR0, H, H(%_symbols) # 2. DLP --> CPP # 3. WD --> WHL(%_parser) DLP(%_lexer) # 4. A custom generator of higher priority than generators 1. & 2. that helps # disambiguate between them when generating CPP files from WHL and DLP # sources. # ################################################################################ type.register WHL : whl ; type.register DLP : dlp ; type.register WHL_LR0 : lr0 ; type.register WD : wd ; local whale-generator-id = [ appender.register whale : WHL : CPP WHL_LR0 H H(%_symbols) ] ; local dolphin-generator-id = [ appender.register dolphin : DLP : CPP ] ; appender.register wd : WD : WHL(%_parser) DLP(%_lexer) ; class wd-to-cpp : generator { rule __init__ ( id : sources * : targets * ) { generator.__init__ $(id) : $(sources) : $(targets) ; } rule run ( project name ? : property-set : source ) { local new-sources = $(source) ; if ! [ $(source).type ] in WHL DLP { local r1 = [ generators.construct $(project) $(name) : WHL : $(property-set) : $(source) ] ; local r2 = [ generators.construct $(project) $(name) : DLP : $(property-set) : $(source) ] ; new-sources = [ sequence.unique $(r1[2-]) $(r2[2-]) ] ; } local result ; for local i in $(new-sources) { local t = [ generators.construct $(project) $(name) : CPP : $(property-set) : $(i) ] ; result += $(t[2-]) ; } return $(result) ; } } generators.override $(__name__).wd-to-cpp : $(whale-generator-id) ; generators.override $(__name__).wd-to-cpp : $(dolphin-generator-id) ; generators.register [ new wd-to-cpp $(__name__).wd-to-cpp : : CPP ] ; ################################################################################ # # Declare build targets. # ################################################################################ # This should not cause two CPP --> MY_OBJ constructions for a.cpp or b.cpp. my-exe a : a.cpp b.cxx obj_1 obj_2 c.tui d.wd x.l y.x_pro lib//auxilliary ; my-exe f : a.cpp b.cxx obj_1 obj_2 lib//auxilliary ; # This should cause two CPP --> MY_OBJ constructions for z.cpp. my-obj obj_1 : z.cpp ; my-obj obj_2 : z.cpp ; nm-exe e : e.cpp ; """) t.run_build_system() t.expect_addition("bin/$toolset/debug/" * 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 " "auxilliary.my_lib")) t.expect_nothing_more() folder = "bin/$toolset/debug" 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'") lines = t.stdout().splitlines() source_lines = [x for x in lines if re.match("^ Sources: '", x)] if not __match_count_is(source_lines, "'z.cpp'", 2): BoostBuild.annotation("failure", "z.cpp must be compiled exactly " "twice.") t.fail_test(1) if not __match_count_is(source_lines, "'a.cpp'", 1): BoostBuild.annotation("failure", "a.cpp must be compiled exactly " "once.") t.fail_test(1) t.cleanup()
import BoostBuild t = BoostBuild.Tester(use_test_config=False) t.write( "jamroot.jam", """\ exe hello : hello.cpp ; exe hello2 : hello.cpp ; explicit hello2 ; """) t.write("hello.cpp", "int main() {}\n") t.run_build_system() t.ignore("*.tds") t.expect_addition(BoostBuild.List("bin/$toolset/debug*/hello") * \ [".exe", ".obj"]) t.ignore_addition("bin/*/hello.rsp") t.expect_nothing_more() t.run_build_system(["hello2"]) t.expect_addition("bin/$toolset/debug*/hello2.exe") t.rm(".") # Test that 'explicit' used in a helper rule applies to the current project, and # not to the Jamfile where the helper rule is defined. t.write( "jamroot.jam", """\ rule myinstall ( name : target ) {
t.expect_addition("lib/bin/$toolset/debug/b.obj") t.expect_nothing_more() t.run_build_system(["--clean", "lib//b.obj"]) t.expect_removal("lib/bin/$toolset/debug/b.obj") t.expect_nothing_more() t.run_build_system(["lib//b.obj"]) t.expect_addition("lib/bin/$toolset/debug/b.obj") t.expect_nothing_more() t.run_build_system(["release", "lib2/helper//e.obj", "/lib3//f.obj"]) t.expect_addition("lib2/helper/bin/$toolset/release/e.obj") t.expect_addition("lib3/bin/$toolset/release/f.obj") t.expect_nothing_more() # Test project ids in command line work as well. t.set_tree("project-test3") t.run_build_system(["/lib2"]) t.expect_addition("lib2/bin/$toolset/debug/" * BoostBuild.List("c.obj d.obj l.exe")) t.expect_addition("bin/$toolset/debug/a.obj") t.expect_nothing_more() t.run_build_system(["lib"]) t.expect_addition("lib/bin/$toolset/debug/" * BoostBuild.List("b.obj m.exe")) t.expect_nothing_more() t.cleanup()
t = BoostBuild.Tester() t.write("jamroot.jam", "") t.write("lib/c.cpp", "int bar() { return 0; }\n") t.write("lib/jamfile.jam", """\ static-lib auxilliary1 : c.cpp ; lib auxilliary2 : c.cpp ; """) def reset(): t.rm("lib/bin") t.run_build_system(subdir='lib') t.expect_addition("lib/bin/$toolset/debug/" * BoostBuild.List("c.obj " "auxilliary1.lib auxilliary2.dll")) t.expect_nothing_more() reset() t.run_build_system(["link=shared"], subdir="lib") t.expect_addition("lib/bin/$toolset/debug/" * BoostBuild.List("c.obj " "auxilliary1.lib auxilliary2.dll")) t.expect_nothing_more() reset() t.run_build_system(["link=static"], subdir="lib") t.expect_addition("lib/bin/$toolset/debug/link-static/" * BoostBuild.List("c.obj auxilliary1.lib auxilliary2.lib")) t.expect_nothing_more()
#!/usr/bin/python # Copyright 2002, 2003 Dave Abrahams # Copyright 2002, 2003 Vladimir Prus # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE.txt or https://www.bfgroup.xyz/b2/LICENSE.txt) import BoostBuild t = BoostBuild.Tester() t.set_tree("test2") file_list = 'bin/$toolset/debug*/' * \ BoostBuild.List("foo foo.o") t.run_build_system("-sBOOST_BUILD_PATH=" + t.original_workdir + "/..") t.expect_addition(file_list) t.write("foo.cpp", "int main() {}\n") t.run_build_system("-d2 -sBOOST_BUILD_PATH=" + t.original_workdir + "/..") t.expect_touch(file_list) t.cleanup()
import BoostBuild t = BoostBuild.Tester(use_test_config=False) t.write("jamroot.jam", "") t.write("jamfile.jam", "exe a : a.cpp : : debug release ;") t.write("a.cpp", "int main() {}\n") t.run_build_system() t.expect_addition("bin/$toolset/debug*/a.exe") t.expect_addition("bin/$toolset/release*/a.exe") # Check that explictly-specified build variant suppresses default-build. t.rm("bin") t.run_build_system(["release"]) t.expect_addition(BoostBuild.List("bin/$toolset/release*/") * "a.exe a.obj") t.ignore_addition('bin/*/a.rsp') t.expect_nothing_more() # Now check that we can specify explicit build request and default-build will be # combined with it. t.run_build_system(["optimization=space"]) t.expect_addition("bin/$toolset/debug/optimization-space*/a.exe") t.expect_addition("bin/$toolset/release/optimization-space*/a.exe") # Test that default-build must be identical in all alternatives. Error case. t.write("jamfile.jam", """\ exe a : a.cpp : : debug ; exe a : b.cpp : : ; """) t.run_build_system(["-n", "--no-error-backtrace"], status=1)
#ifdef MACROS void # ifdef _WIN32 __declspec(dllexport) # endif foo() {} #endif # ifdef _WIN32 int __declspec(dllexport) force_implib_creation; # endif """) t.run_build_system(extra_args="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(extra_args="debug define=MACROS") t.expect_addition("bin/$toolset/debug/" * (BoostBuild.List("a.obj b.obj b.dll a.exe"))) # When building release version, the 'define' still applies. t.write("jamfile.jam", """ exe a : a.cpp b : <variant>debug ; lib b : b.cpp ; """) t.rm("bin") t.run_build_system(extra_args="release define=MACROS")
# Copyright 2003 Dave Abrahams # Copyright 2002, 2003, 2005 Vladimir Prus # 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 t = BoostBuild.Tester() t.set_tree("generators-test") t.run_build_system() t.expect_addition("bin/$toolset/debug/" * BoostBuild.List( "a.obj b.obj c.h " + "c.cpp c.obj d_parser.whl d_lexer.dlp d_parser.cpp d_lexer.cpp " + "d_parser.lr0 d_parser.h d_parser_symbols.h x.c x.obj y.x1 y.x2 y.cpp " + "y.obj e.marked_cpp e.positions e.target_cpp e.obj")) t.expect_addition("bin/$toolset/debug/a.exe") t.expect_addition( ["lib/bin/$toolset/debug/c.obj", "lib/bin/$toolset/debug/auxilliary.lib"]) t.run_build_system(subdir='lib') t.expect_addition(["lib/bin/$toolset/debug/auxilliary2.dll"]) t.run_build_system(subdir='lib', extra_args="link=static") t.expect_addition(["lib/bin/$toolset/debug/link-static/auxilliary2.lib"]) t.cleanup()
import BoostBuild t = BoostBuild.Tester(use_test_config=False) t.write("jamroot.jam", "") t.write("lib/c.cpp", "int bar() { return 0; }\n") t.write("lib/jamfile.jam", """\ static-lib auxilliary1 : c.cpp ; lib auxilliary2 : c.cpp ; """) def reset(): t.rm("lib/bin") t.run_build_system(subdir='lib') t.expect_addition("lib/bin/$toolset/debug/" * BoostBuild.List("c.obj " "auxilliary1.lib auxilliary2.dll")) t.expect_nothing_more() reset() t.run_build_system(["link=shared"], subdir="lib") t.expect_addition("lib/bin/$toolset/debug/" * BoostBuild.List("c.obj " "auxilliary1.lib auxilliary2.dll")) t.expect_nothing_more() reset() t.run_build_system(["link=static"], subdir="lib") t.expect_addition("lib/bin/$toolset/debug/link-static/" * BoostBuild.List( "c.obj auxilliary1.lib auxilliary2.lib")) t.expect_nothing_more() t.cleanup()
#!/usr/bin/python # Copyright 2002, 2003 Dave Abrahams # Copyright 2002, 2003 Vladimir Prus # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE.txt or https://www.bfgroup.xyz/b2/LICENSE.txt) import BoostBuild t = BoostBuild.Tester() t.set_tree("test2") file_list = 'bin/$toolset/debug*/' * \ BoostBuild.List("foo.exe foo.obj") t.run_build_system(["-sBOOST_BUILD_PATH=" + t.original_workdir + "/.."]) t.expect_addition(file_list) t.write("foo.cpp", "int main() {}\n") t.run_build_system(["-d2", "-sBOOST_BUILD_PATH=" + t.original_workdir + "/.."]) t.expect_touch(file_list) t.cleanup()