#!/usr/bin/python # Copyright 2012 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) import BoostBuild import re def test( use_project, reverse_targets ): use_project_line_comment = "#" if use_project: use_project_line_comment = "" params = [] if reverse_targets: params.extend([ "ddd", "ccc" ]) t = BoostBuild.Tester(["--debug-building", "--debug-loading"], pass_d0=False) __write_appender(t, "appender.jam") t.write("jamroot.jam", """\ # Can b fixed by any of the following: # * Building ddd before ccc. # * Loading project 'a' at startup, e.g. by running 'use-project xxx : a ;'. %suse-project xxx : a ; import type ; type.register AAA : _a ; type.register BBB : _b ; type.register CCC : _c ; type.register DDD : _d ; import appender ; appender.register aaa-to-bbb : AAA : BBB ; appender.register bbb-to-ccc : BBB : CCC ; appender.register ccc-to-ddd : CCC : DDD ; ccc ccc : o//bbb ; ddd ddd : a//ccc ; """ % use_project_line_comment) t.write("a/jamfile.jam", """\ import feature ; feature.feature foo-bar : foo bar : propagated ; ccc ccc : ../o//bbb : foo ; """) t.write("o/jamfile.jam", "bbb bbb : aaa._a ;") t.write("o/aaa._a", "") t.run_build_system(params) t.expect_addition("bin/$toolset/debug/ccc._c") t.expect_addition("bin/$toolset/debug/ddd._d") t.expect_addition("a/bin/$toolset/debug/ccc._c") t.expect_addition("o/bin/$toolset/debug/bbb._b") t.expect_nothing_more() 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_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.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(use_project=True, reverse_targets=False) test(use_project=False, reverse_targets=True) test(use_project=True, reverse_targets=True) test(use_project=False, reverse_targets=False)