| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414 |
- #!/usr/bin/python
- # Copyright (C) 2012. Jurko Gospodnetic
- # Distributed under the Boost Software License, Version 1.0.
- # (See accompanying file LICENSE.txt or copy at
- # https://www.bfgroup.xyz/b2/LICENSE.txt)
- # Tests Boost Build's project-id handling.
- import BoostBuild
- import sys
- def test_assigning_project_ids():
- t = BoostBuild.Tester(pass_toolset=False)
- t.write("jamroot.jam", """\
- import assert ;
- import modules ;
- import notfile ;
- import project ;
- rule assert-project-id ( id ? : module-name ? )
- {
- module-name ?= [ CALLER_MODULE ] ;
- assert.result $(id) : project.attribute $(module-name) id ;
- }
- # Project rule modifies the main project id.
- assert-project-id ; # Initial project id is empty
- project foo ; assert-project-id /foo ;
- project ; assert-project-id /foo ;
- project foo ; assert-project-id /foo ;
- project bar ; assert-project-id /bar ;
- project /foo ; assert-project-id /foo ;
- project "" ; assert-project-id /foo ;
- # Calling the use-project rule does not modify the project's main id.
- use-project id1 : a ;
- # We need to load the 'a' Jamfile module manually as the use-project rule will
- # only schedule the load to be done after the current module load finishes.
- a-module = [ project.load a ] ;
- assert-project-id : $(a-module) ;
- use-project id2 : a ;
- assert-project-id : $(a-module) ;
- modules.call-in $(a-module) : project baz ;
- assert-project-id /baz : $(a-module) ;
- use-project id3 : a ;
- assert-project-id /baz : $(a-module) ;
- # Make sure the project id still holds after all the scheduled use-project loads
- # complete. We do this by scheduling the assert for the Jam action scheduling
- # phase.
- notfile x : @assert-a-rule ;
- rule assert-a-rule ( target : : properties * )
- {
- assert-project-id /baz : $(a-module) ;
- }
- """)
- t.write("a/jamfile.jam", """\
- # Initial project id for this module is empty.
- assert-project-id ;
- """)
- t.run_build_system()
- t.cleanup()
- def test_using_project_ids_in_target_references():
- t = BoostBuild.Tester()
- __write_appender(t, "appender.jam")
- t.write("jamroot.jam", """\
- import type ;
- type.register AAA : _a ;
- type.register BBB : _b ;
- import appender ;
- appender.register aaa-to-bbb : AAA : BBB ;
- use-project id1 : a ;
- use-project /id2 : a ;
- bbb b1 : /id1//target ;
- bbb b2 : /id2//target ;
- bbb b3 : /id3//target ;
- bbb b4 : a//target ;
- bbb b5 : /project-a1//target ;
- bbb b6 : /project-a2//target ;
- bbb b7 : /project-a3//target ;
- use-project id3 : a ;
- """)
- t.write("a/source._a", "")
- t.write("a/jamfile.jam", """\
- project project-a1 ;
- project /project-a2 ;
- import alias ;
- alias target : source._a ;
- project /project-a3 ;
- """)
- t.run_build_system()
- t.expect_addition("bin/b%d._b" % x for x in range(1, 8))
- t.expect_nothing_more()
- t.cleanup()
- def test_repeated_ids_for_different_projects():
- t = BoostBuild.Tester()
- t.write("a/jamfile.jam", "")
- t.write("jamroot.jam", "project foo ; use-project foo : a ;")
- t.run_build_system(status=1)
- t.expect_output_lines("""\
- error: Attempt to redeclare already registered project id '/foo'.
- error: Original project:
- error: Name: Jamfile<*>
- error: Module: Jamfile<*>
- error: Main id: /foo
- error: File: jamroot.jam
- error: Location: .
- error: New project:
- error: Module: Jamfile<*>
- error: File: a*jamfile.jam
- error: Location: a""")
- t.write("jamroot.jam", "use-project foo : a ; project foo ;")
- t.run_build_system(status=1)
- t.expect_output_lines("""\
- error: Attempt to redeclare already registered project id '/foo'.
- error: Original project:
- error: Name: Jamfile<*>
- error: Module: Jamfile<*>
- error: Main id: /foo
- error: File: jamroot.jam
- error: Location: .
- error: New project:
- error: Module: Jamfile<*>
- error: File: a*jamfile.jam
- error: Location: a""")
- t.write("jamroot.jam", """\
- import modules ;
- import project ;
- modules.call-in [ project.load a ] : project foo ;
- project foo ;
- """)
- t.run_build_system(status=1)
- t.expect_output_lines("""\
- error: at jamroot.jam:4
- error: Attempt to redeclare already registered project id '/foo'.
- error: Original project:
- error: Name: Jamfile<*>
- error: Module: Jamfile<*>
- error: Main id: /foo
- error: File: a*jamfile.jam
- error: Location: a
- error: New project:
- error: Module: Jamfile<*>
- error: File: jamroot.jam
- error: Location: .""")
- t.cleanup()
- def test_repeated_ids_for_same_project():
- t = BoostBuild.Tester()
- t.write("jamroot.jam", "project foo ; project foo ;")
- t.run_build_system()
- t.write("jamroot.jam", "project foo ; use-project foo : . ;")
- t.run_build_system()
- t.write("jamroot.jam", "project foo ; use-project foo : ./. ;")
- t.run_build_system()
- t.write("jamroot.jam", """\
- project foo ;
- use-project foo : . ;
- use-project foo : ./aaa/.. ;
- use-project foo : ./. ;
- """)
- t.run_build_system()
- # On Windows we have a case-insensitive file system and we can use
- # backslashes as path separators.
- # FIXME: Make a similar test pass on Cygwin.
- if sys.platform in ['win32']:
- t.write("a/fOo bAr/b/jamfile.jam", "")
- t.write("jamroot.jam", r"""
- use-project bar : "a/foo bar/b" ;
- use-project bar : "a/foO Bar/b" ;
- use-project bar : "a/foo BAR/b/" ;
- use-project bar : "a\\.\\FOO bar\\b\\" ;
- """)
- t.run_build_system()
- t.rm("a")
- t.write("bar/jamfile.jam", "")
- t.write("jamroot.jam", """\
- use-project bar : bar ;
- use-project bar : bar/ ;
- use-project bar : bar// ;
- use-project bar : bar/// ;
- use-project bar : bar//// ;
- use-project bar : bar/. ;
- use-project bar : bar/./ ;
- use-project bar : bar/////./ ;
- use-project bar : bar/../bar/xxx/.. ;
- use-project bar : bar/..///bar/xxx///////.. ;
- use-project bar : bar/./../bar/xxx/.. ;
- use-project bar : bar/.////../bar/xxx/.. ;
- use-project bar : bar/././../bar/xxx/.. ;
- use-project bar : bar/././//////////../bar/xxx/.. ;
- use-project bar : bar/.///.////../bar/xxx/.. ;
- use-project bar : bar/./././xxx/.. ;
- use-project bar : bar/xxx////.. ;
- use-project bar : bar/xxx/.. ;
- use-project bar : bar///////xxx/.. ;
- """)
- t.run_build_system()
- t.rm("bar")
- # On Windows we have a case-insensitive file system and we can use
- # backslashes as path separators.
- # FIXME: Make a similar test pass on Cygwin.
- if sys.platform in ['win32']:
- t.write("baR/jamfile.jam", "")
- t.write("jamroot.jam", r"""
- use-project bar : bar ;
- use-project bar : BAR ;
- use-project bar : bAr ;
- use-project bar : bAr/ ;
- use-project bar : bAr\\ ;
- use-project bar : bAr\\\\ ;
- use-project bar : bAr\\\\///// ;
- use-project bar : bAr/. ;
- use-project bar : bAr/./././ ;
- use-project bar : bAr\\.\\.\\.\\ ;
- use-project bar : bAr\\./\\/.\\.\\ ;
- use-project bar : bAr/.\\././ ;
- use-project bar : Bar ;
- use-project bar : BaR ;
- use-project bar : BaR/./../bAr/xxx/.. ;
- use-project bar : BaR/./..\\bAr\\xxx/.. ;
- use-project bar : BaR/xxx/.. ;
- use-project bar : BaR///\\\\\\//xxx/.. ;
- use-project bar : Bar\\xxx/.. ;
- use-project bar : BAR/xXx/.. ;
- use-project bar : BAR/xXx\\\\/\\/\\//\\.. ;
- """)
- t.run_build_system()
- t.rm("baR")
- t.cleanup()
- def test_unresolved_project_references():
- t = BoostBuild.Tester()
- __write_appender(t, "appender.jam")
- t.write("a/source._a", "")
- t.write("a/jamfile.jam", "import alias ; alias target : source._a ;")
- t.write("jamroot.jam", """\
- import type ;
- type.register AAA : _a ;
- type.register BBB : _b ;
- import appender ;
- appender.register aaa-to-bbb : AAA : BBB ;
- use-project foo : a ;
- bbb b1 : a//target ;
- bbb b2 : /foo//target ;
- bbb b-invalid : invalid//target ;
- bbb b-root-invalid : /invalid//target ;
- bbb b-missing-root : foo//target ;
- bbb b-invalid-target : /foo//invalid ;
- """)
- t.run_build_system(["b1", "b2"])
- 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)
- t.expect_output_lines("""\
- error: Unable to find file or target named
- error: 'invalid//target'
- error: referred to from project at
- error: '.'
- error: could not resolve project reference 'invalid'""")
- t.run_build_system(["b-root-invalid"], status=1)
- t.expect_output_lines("""\
- error: Unable to find file or target named
- error: '/invalid//target'
- error: referred to from project at
- error: '.'
- error: could not resolve project reference '/invalid'""")
- t.run_build_system(["b-missing-root"], status=1)
- t.expect_output_lines("""\
- error: Unable to find file or target named
- error: 'foo//target'
- error: referred to from project at
- error: '.'
- error: could not resolve project reference 'foo' - possibly missing a """
- "leading slash ('/') character.")
- t.run_build_system(["b-invalid-target"], status=1)
- t.expect_output_lines("""\
- error: Unable to find file or target named
- error: '/foo//invalid'
- error: referred to from project at
- error: '.'""")
- t.expect_output_lines("*could not resolve project reference*", False)
- t.cleanup()
- def __write_appender(t, name):
- t.write(name,
- r"""# Copyright 2012 Jurko Gospodnetic
- # Distributed under the Boost Software License, Version 1.0.
- # (See accompanying file LICENSE.txt or copy at
- # https://www.bfgroup.xyz/b2/LICENSE.txt)
- # Support for registering test generators that construct their targets by
- # simply appending their given input data, e.g. list of sources & targets.
- import "class" : new ;
- import generators ;
- import modules ;
- import sequence ;
- rule register ( id composing ? : source-types + : target-types + )
- {
- local caller-module = [ CALLER_MODULE ] ;
- id = $(caller-module).$(id) ;
- local g = [ new generator $(id) $(composing) : $(source-types) :
- $(target-types) ] ;
- $(g).set-rule-name $(__name__).appender ;
- generators.register $(g) ;
- return $(id) ;
- }
- if [ modules.peek : NT ]
- {
- X = ")" ;
- ECHO_CMD = (echo. ;
- }
- else
- {
- X = \" ;
- ECHO_CMD = "echo $(X)" ;
- }
- local appender-runs ;
- # We set up separate actions for building each target in order to avoid having
- # to iterate over them in action (i.e. shell) code. We have to be extra careful
- # though to achieve the exact same effect as if doing all the work in just one
- # action. Otherwise Boost Jam might, under some circumstances, run only some of
- # our actions. To achieve this we register a series of actions for all the
- # targets (since they all have the same target list - either all or none of them
- # get run independent of which target actually needs to get built), each
- # building only a single target. Since all our actions use the same targets, we
- # can not use 'on-target' parameters to pass data to a specific action so we
- # pass them using the second 'sources' parameter which our actions then know how
- # to interpret correctly. This works well since Boost Jam does not automatically
- # add dependency relations between specified action targets & sources and so the
- # second argument, even though most often used to pass in a list of sources, can
- # actually be used for passing in any type of information.
- rule appender ( targets + : sources + : properties * )
- {
- appender-runs = [ CALC $(appender-runs:E=0) + 1 ] ;
- local target-index = 0 ;
- local target-count = [ sequence.length $(targets) ] ;
- local original-targets ;
- for t in $(targets)
- {
- target-index = [ CALC $(target-index) + 1 ] ;
- local appender-run = $(appender-runs) ;
- if $(targets[2])-defined
- {
- appender-run += [$(target-index)/$(target-count)] ;
- }
- append $(targets) : $(appender-run:J=" ") $(t) $(sources) ;
- }
- }
- actions append
- {
- $(ECHO_CMD)-------------------------------------------------$(X)
- $(ECHO_CMD)Appender run: $(>[1])$(X)
- $(ECHO_CMD)Appender run: $(>[1])$(X)>> "$(>[2])"
- $(ECHO_CMD)Target group: $(<:J=' ')$(X)
- $(ECHO_CMD)Target group: $(<:J=' ')$(X)>> "$(>[2])"
- $(ECHO_CMD) Target: '$(>[2])'$(X)
- $(ECHO_CMD) Target: '$(>[2])'$(X)>> "$(>[2])"
- $(ECHO_CMD) Sources: '$(>[3-]:J=' ')'$(X)
- $(ECHO_CMD) Sources: '$(>[3-]:J=' ')'$(X)>> "$(>[2])"
- $(ECHO_CMD)=================================================$(X)
- $(ECHO_CMD)-------------------------------------------------$(X)>> "$(>[2])"
- }
- """)
- test_assigning_project_ids()
- test_using_project_ids_in_target_references()
- test_repeated_ids_for_same_project()
- test_repeated_ids_for_different_projects()
- test_unresolved_project_references()
|