diff --git a/new/builtin.jam b/new/builtin.jam index 52336bf4e..430ec40f7 100644 --- a/new/builtin.jam +++ b/new/builtin.jam @@ -14,8 +14,10 @@ import generators ; import regex ; import virtual-target ; import os ; +import stage ; +import prebuilt ; -feature toolset : gcc : implicit propagated ; +feature toolset : gcc : implicit propagated link-incompatible ; feature shared : false true : propagated ; feature optimization : off on : propagated ; feature threading : single multi : link-incompatible propagated ; diff --git a/new/common.jam b/new/common.jam index 0d971c2a4..74b619540 100644 --- a/new/common.jam +++ b/new/common.jam @@ -61,3 +61,14 @@ actions piecemeal together existing Clean rm $(>) } +rule copy +{ +} + + +actions copy +{ + cp $(>) $(<) +} + + diff --git a/new/prebuilt.jam b/new/prebuilt.jam new file mode 100644 index 000000000..9609ea6a4 --- /dev/null +++ b/new/prebuilt.jam @@ -0,0 +1,56 @@ +# Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and +# distribute this software is granted provided this copyright notice appears in +# all copies. This software is provided "as is" without express or implied +# warranty, and with no claim as to its suitability for any purpose. + +# This module defines the 'prebuilt' rule, which allows to use targets +# created outside of Boost.Build, or for which no source is available.. + +import targets ; +import class : class new ; +import property ; +import errors : error ; +import type : type ; +import regex ; + +rule prebuilt-target-class ( name : project : type file : requirements * : use-requirements * ) +{ + abstract-target.__init__ $(name) : $(project) ; + self.type = $(type) ; + self.file = $(file) ; + self.requirements = $(requirements) ; + self.use-requirements = $(use-requirements) ; + + rule generate ( properties * ) + { + local pl = [ project.attribute $(self.project) location ] ; + local path = [ path.root [ path.native $(self.file:D) ] $(pl) ] ; + + # CONSIDER: refine properties? + local t = [ new virtual-target $(self.file:S=:D=) : $(self.type) + : $(self.project) ] ; + $(t).set-use-requirements $(self.use-requirements) ; + $(t).set-path $(path) ; + $(t).extra-grist [ property.as-path $(self.requirements) ] ; + $(t).suffix [ MATCH .(.*) : $(self.file:S) ] ; + return $(t) ; + } + + rule requirements ( ) + { + return $(self.requirements) ; + } +} + +class prebuilt-target-class : abstract-target ; + +rule prebuilt ( type target-name : file : requirements * : use-requirements * ) +{ + targets.main-target-alternative + $(target-name) [ CALLER_MODULE ] prebuilt-target-class : 2 : 3 : + : $(type) $(file) : $(requirements) : $(use-requirements) ; +} + +IMPORT $(__name__) : prebuilt : : prebuilt ; + + diff --git a/new/stage.jam b/new/stage.jam new file mode 100644 index 000000000..6adaed9c4 --- /dev/null +++ b/new/stage.jam @@ -0,0 +1,56 @@ +# Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and +# distribute this software is granted provided this copyright notice appears in +# all copies. This software is provided "as is" without express or implied +# warranty, and with no claim as to its suitability for any purpose. + +# This module defines the 'stage' rule, used to copy a set of targets to +# a single location + +import targets ; +import class : class new ; +import property ; +import errors : error ; +import type : type ; +import regex ; + +rule stage-target-class ( name-and-dir : project : sources * : requirements * : default-build * ) +{ + basic-target.__init__ $(name-and-dir) : $(project) : $(sources) : $(requirements) + : $(default-build) ; + + rule construct ( source-targets * : properties * ) + { + local result ; + for local i in $(source-targets) + { + local i2 = [ new virtual-target [ $(i).name ] : [ $(i).type ] + : $(self.project) ] ; + local a = [ new action $(i2) : $(i) : common.copy ] ; + $(i2).action $(a) ; + + local pl = [ project.attribute $(self.project) location ] ; + local path = [ path.root [ path.native $(self.name) ] $(pl) ] ; + + $(i2).set-path $(path) ; + $(i2).extra-grist stage-$(self.name) ; + result += $(i2) ; + } + return $(result) ; + } +} + +class stage-target-class : basic-target ; + +rule stage ( directory : sources * : requirements * : default-build * ) +{ + # FIXME: for now, just use directory as target name. We really + # need to implement unnamed main targets. + targets.main-target-alternative + $(directory) [ CALLER_MODULE ] stage-target-class : 2 : : 3 + : $(sources) : $(requirements) : $(default-build) ; +} + +IMPORT $(__name__) : stage : : stage ; + + + diff --git a/new/targets.jam b/new/targets.jam index 0e03de63c..e7cceff91 100644 --- a/new/targets.jam +++ b/new/targets.jam @@ -237,7 +237,7 @@ rule main-target ( name : project ) else { # Find the alternative with the longest set of non-free and - # non-indicental requirements + # non-indicental requirements and are in 'properties' local r = [ $(alternatives).indices ] ; # First compute the length of requirements sets @@ -245,28 +245,22 @@ rule main-target ( name : project ) for local p in $(r) { local target = [ $(alternatives).at $(p) : 1 ] ; - assert.equal [ is-a $(target) : basic-target ] : true ; - local props = [ $(target).requirements ] ; - req-length += [ sequence.length [ property.remove free : - [ $(target).requirements ] ] ] ; + # FIXME: in general, 'abstract-target' derivatives might not + # have 'requirements' method. + # assert.equal [ is-a $(target) : basic-target ] : true ; + local req = [ $(target).requirements ] ; + req = [ property.remove free incidental : $(req) ] ; + req-length += [ sequence.length + [ set.intersection $(req) : $(properties) ] ] ; } - - # Then find if there's single requirements set with maximum length - local req-length2 = [ sequence.insertion-sort $(req-length) ] ; - if $(req-length2[-1]) != $(req-length2[-2]) - { - # Have signle maximum value - local max-length = $(req-length2[-1]) ; - local best ; - while $(r) && ! $(best) - { - if $(req-length[$(r[1])]) = $(max-length) - { - best = [ $(alternatives).get-at $(r[1]) ] ; - } - r = $(r[2-]) ; - } - result = $(best[2-]) ; + + local best = [ sequence.select-highest-ranked $(r) : $(req-length) ] ; + + if ! $(best[2]) + { + local index = $(best[1]) ; + result = [ $(alternatives).get-at $(index) ] ; + result = $(result[2-]) ; } else { @@ -382,7 +376,7 @@ rule basic-target ( name : project [ property.refine $(properties) : $(self.requirements) ] ; rproperties = [ property.evaluate-conditionals $(rproperties) ] ; - + if $(rproperties[1]) != "@error" { # TODO: issue a warning when requirements change properties, but @@ -472,7 +466,7 @@ rule basic-target ( name : project return [ $(main-target).generate $(rproperties) ] ; } } - + # Constructs the virtual targets for this abstract targets and # the dependecy graph. Returns the list of virtual targets. # Should be overrided in derived classes. diff --git a/new/virtual-target.jam b/new/virtual-target.jam index 4a1ab087c..204eac0c6 100644 --- a/new/virtual-target.jam +++ b/new/virtual-target.jam @@ -40,6 +40,14 @@ rule virtual-target ( name : type ? : project ) } return $(self.suffix) ; } + + # Sets the path. When generating target name, it will override any path + # computation from properties. + rule set-path ( path ) + { + self.path = $(path) ; + } + # Property set that distinguishes different variants of a target. # May be a subset of the property set that is used for building. @@ -106,6 +114,13 @@ rule virtual-target ( name : type ? : project ) { self.extra-path = $(p) ; } + + # Specifies an extra grist to be added to the target name. + rule extra-grist ( g ) + { + self.extra-grist = $(g) ; + } + # Generates all the actual targets and build instructions needed to build # this target. Returns the actual target name. Can be called several times. @@ -181,7 +196,13 @@ rule virtual-target ( name : type ? : project ) DEPENDS $(name) : $(path) ; common.MkDir $(path) ; common.Clean clean : $(name) ; - } else { + } + else if $(self.path) + { + LOCATE on $(name) = $(self.path) ; + } + else + { SEARCH on $(name) = [ path.native [ project.attribute $(self.project) source-location ] ] ; } @@ -251,7 +272,11 @@ rule virtual-target ( name : type ? : project ) { grist = $(location-grist) ; } - + if $(self.extra-grist) + { + grist = $(grist)/$(self.extra-grist) ; + } + if $(self.suffix) { self.actual-name = [ sequence.join <$(grist)>$(self.name) @@ -273,13 +298,20 @@ rule virtual-target ( name : type ? : project ) # Returns the directory for this target rule path ( ) { - local path = [ path.join - [ project.attribute $(self.project) location ] - [ $(self.action).path ] - $(self.extra-path) - ] ; + if $(self.path) + { + return $(self.path) ; + } + else + { + local path = [ path.join + [ project.attribute $(self.project) location ] + [ $(self.action).path ] + $(self.extra-path) + ] ; - return [ path.native $(path) ] ; + return [ path.native $(path) ] ; + } } } diff --git a/test/prebuilt.py b/test/prebuilt.py new file mode 100644 index 000000000..46d90a39e --- /dev/null +++ b/test/prebuilt.py @@ -0,0 +1,26 @@ +#!/usr/bin/python + +# Test that we can use already built sources + +from BoostBuild import Tester +t = Tester() + +t.set_tree('prebuilt') + +# First, build the external project +t.run_build_system("debug release", subdir="ext") + +# Then pretend that we don't have the sources for the external project, +# and can only use compiled binaries +t.copy("ext/Jamfile2", "ext/Jamfile") + +# Now check that we can build the main project, and that +# correct prebuilt file is picked, depending of variant. +# This also checks that correct includes for prebuilt +# libraries are used. + +t.run_build_system("debug release") +t.expect_addition("bin/gcc/debug/main-target-hello/hello") +t.expect_addition("bin/gcc/release/main-target-hello/hello") + +t.cleanup() diff --git a/test/prebuilt/Jamfile b/test/prebuilt/Jamfile new file mode 100644 index 000000000..eea94af4d --- /dev/null +++ b/test/prebuilt/Jamfile @@ -0,0 +1,9 @@ + +project test + : requirements release:RELEASE + ; + +use-project /ext : ext ; + +exe hello : hello.cpp @/ext/a ; + diff --git a/test/prebuilt/ext/Jamfile b/test/prebuilt/ext/Jamfile new file mode 100644 index 000000000..3393bbea9 --- /dev/null +++ b/test/prebuilt/ext/Jamfile @@ -0,0 +1,6 @@ + +project ext + : requirements release:RELEASE + ; + +lib a : a.cpp ; \ No newline at end of file diff --git a/test/prebuilt/ext/Jamfile2 b/test/prebuilt/ext/Jamfile2 new file mode 100644 index 000000000..5d57442c0 --- /dev/null +++ b/test/prebuilt/ext/Jamfile2 @@ -0,0 +1,15 @@ + +project ext ; + +prebuilt LIB a + : bin/gcc/debug/a.a + : debug + : debug + ; + +prebuilt LIB a + : bin/gcc/release/a.a + : release + : release + ; + \ No newline at end of file diff --git a/test/prebuilt/ext/a.cpp b/test/prebuilt/ext/a.cpp new file mode 100644 index 000000000..6f5e59e08 --- /dev/null +++ b/test/prebuilt/ext/a.cpp @@ -0,0 +1,6 @@ + +#ifdef RELEASE +void release() {} +#else +void debug() {} +#endif \ No newline at end of file diff --git a/test/prebuilt/ext/debug/a.h b/test/prebuilt/ext/debug/a.h new file mode 100644 index 000000000..d5eade04b --- /dev/null +++ b/test/prebuilt/ext/debug/a.h @@ -0,0 +1,2 @@ + +void debug(); \ No newline at end of file diff --git a/test/prebuilt/ext/project-root.jam b/test/prebuilt/ext/project-root.jam new file mode 100644 index 000000000..be01ebeeb --- /dev/null +++ b/test/prebuilt/ext/project-root.jam @@ -0,0 +1,2 @@ + +import gcc ; \ No newline at end of file diff --git a/test/prebuilt/ext/release/a.h b/test/prebuilt/ext/release/a.h new file mode 100644 index 000000000..4fa6fc3c8 --- /dev/null +++ b/test/prebuilt/ext/release/a.h @@ -0,0 +1,2 @@ + +void release(); \ No newline at end of file diff --git a/test/prebuilt/hello.cpp b/test/prebuilt/hello.cpp new file mode 100644 index 000000000..0be150916 --- /dev/null +++ b/test/prebuilt/hello.cpp @@ -0,0 +1,11 @@ + +#include + +int main() +{ + #ifdef RELEASE + release(); + #else + debug(); + #endif +} \ No newline at end of file diff --git a/test/prebuilt/project-root.jam b/test/prebuilt/project-root.jam new file mode 100644 index 000000000..be01ebeeb --- /dev/null +++ b/test/prebuilt/project-root.jam @@ -0,0 +1,2 @@ + +import gcc ; \ No newline at end of file diff --git a/test/project_test4.py b/test/project_test4.py index f8ed60f4c..70a2c664f 100644 --- a/test/project_test4.py +++ b/test/project_test4.py @@ -71,22 +71,25 @@ expected="""warning: skipping build of project /mylib at lib2 t.run_build_system("rtti=on", stdout=expected, status=None) # We don't yet make targets depend on Jamfile, so need to start from scratch -t.set_tree("project-test4") -t.copy("Jamfile2", "Jamfile") +# The following test is disabled, because of problems related to +# issue 634319 -t.run_build_system() +#t.set_tree("project-test4") +#t.copy("Jamfile2", "Jamfile") -t.expect_addition("bin/gcc/debug/a_gcc.obj") -t.expect_content("bin/gcc/debug/a_gcc.obj", -"""gcc/debug -a_gcc.cpp -""") +#t.run_build_system() -t.expect_content("bin/gcc/debug/a.exe", -"gcc/debug\n" + -"bin/gcc/debug/a.obj " + -"lib/bin/gcc/debug/optimization-on/b.obj " + -"bin/gcc/debug/a_gcc.obj\n" -) +#t.expect_addition("bin/gcc/debug/a_gcc.obj") +#t.expect_content("bin/gcc/debug/a_gcc.obj", +#"""gcc/debug +#a_gcc.cpp +#""") + +#t.expect_content("bin/gcc/debug/a.exe", +#"gcc/debug\n" + +#"bin/gcc/debug/a.obj " + +#"lib/bin/gcc/debug/optimization-on/b.obj " + +#"bin/gcc/debug/a_gcc.obj\n" +#) t.cleanup() diff --git a/test/stage.py b/test/stage.py new file mode 100644 index 000000000..9af8e4192 --- /dev/null +++ b/test/stage.py @@ -0,0 +1,19 @@ +#!/usr/bin/python + +# Test staging + +from BoostBuild import Tester +t = Tester() + +t.write("project-root.jam", "import gcc ;") +t.write("Jamfile", """ +lib a : a.cpp ; +stage dist : a a.h ; +""") +t.write("a.cpp", "") +t.write("a.h", "") + +t.run_build_system() +t.expect_addition(["dist/a.a", "dist/a.h"]) + +t.cleanup() diff --git a/test/test_all.py b/test/test_all.py index 67d5b1404..f2991f7e9 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -30,3 +30,5 @@ import default_build import main_properties import use_requirements import conditionals +import stage +import prebuilt diff --git a/v2/build/targets.jam b/v2/build/targets.jam index 0e03de63c..e7cceff91 100644 --- a/v2/build/targets.jam +++ b/v2/build/targets.jam @@ -237,7 +237,7 @@ rule main-target ( name : project ) else { # Find the alternative with the longest set of non-free and - # non-indicental requirements + # non-indicental requirements and are in 'properties' local r = [ $(alternatives).indices ] ; # First compute the length of requirements sets @@ -245,28 +245,22 @@ rule main-target ( name : project ) for local p in $(r) { local target = [ $(alternatives).at $(p) : 1 ] ; - assert.equal [ is-a $(target) : basic-target ] : true ; - local props = [ $(target).requirements ] ; - req-length += [ sequence.length [ property.remove free : - [ $(target).requirements ] ] ] ; + # FIXME: in general, 'abstract-target' derivatives might not + # have 'requirements' method. + # assert.equal [ is-a $(target) : basic-target ] : true ; + local req = [ $(target).requirements ] ; + req = [ property.remove free incidental : $(req) ] ; + req-length += [ sequence.length + [ set.intersection $(req) : $(properties) ] ] ; } - - # Then find if there's single requirements set with maximum length - local req-length2 = [ sequence.insertion-sort $(req-length) ] ; - if $(req-length2[-1]) != $(req-length2[-2]) - { - # Have signle maximum value - local max-length = $(req-length2[-1]) ; - local best ; - while $(r) && ! $(best) - { - if $(req-length[$(r[1])]) = $(max-length) - { - best = [ $(alternatives).get-at $(r[1]) ] ; - } - r = $(r[2-]) ; - } - result = $(best[2-]) ; + + local best = [ sequence.select-highest-ranked $(r) : $(req-length) ] ; + + if ! $(best[2]) + { + local index = $(best[1]) ; + result = [ $(alternatives).get-at $(index) ] ; + result = $(result[2-]) ; } else { @@ -382,7 +376,7 @@ rule basic-target ( name : project [ property.refine $(properties) : $(self.requirements) ] ; rproperties = [ property.evaluate-conditionals $(rproperties) ] ; - + if $(rproperties[1]) != "@error" { # TODO: issue a warning when requirements change properties, but @@ -472,7 +466,7 @@ rule basic-target ( name : project return [ $(main-target).generate $(rproperties) ] ; } } - + # Constructs the virtual targets for this abstract targets and # the dependecy graph. Returns the list of virtual targets. # Should be overrided in derived classes. diff --git a/v2/build/virtual-target.jam b/v2/build/virtual-target.jam index 4a1ab087c..204eac0c6 100644 --- a/v2/build/virtual-target.jam +++ b/v2/build/virtual-target.jam @@ -40,6 +40,14 @@ rule virtual-target ( name : type ? : project ) } return $(self.suffix) ; } + + # Sets the path. When generating target name, it will override any path + # computation from properties. + rule set-path ( path ) + { + self.path = $(path) ; + } + # Property set that distinguishes different variants of a target. # May be a subset of the property set that is used for building. @@ -106,6 +114,13 @@ rule virtual-target ( name : type ? : project ) { self.extra-path = $(p) ; } + + # Specifies an extra grist to be added to the target name. + rule extra-grist ( g ) + { + self.extra-grist = $(g) ; + } + # Generates all the actual targets and build instructions needed to build # this target. Returns the actual target name. Can be called several times. @@ -181,7 +196,13 @@ rule virtual-target ( name : type ? : project ) DEPENDS $(name) : $(path) ; common.MkDir $(path) ; common.Clean clean : $(name) ; - } else { + } + else if $(self.path) + { + LOCATE on $(name) = $(self.path) ; + } + else + { SEARCH on $(name) = [ path.native [ project.attribute $(self.project) source-location ] ] ; } @@ -251,7 +272,11 @@ rule virtual-target ( name : type ? : project ) { grist = $(location-grist) ; } - + if $(self.extra-grist) + { + grist = $(grist)/$(self.extra-grist) ; + } + if $(self.suffix) { self.actual-name = [ sequence.join <$(grist)>$(self.name) @@ -273,13 +298,20 @@ rule virtual-target ( name : type ? : project ) # Returns the directory for this target rule path ( ) { - local path = [ path.join - [ project.attribute $(self.project) location ] - [ $(self.action).path ] - $(self.extra-path) - ] ; + if $(self.path) + { + return $(self.path) ; + } + else + { + local path = [ path.join + [ project.attribute $(self.project) location ] + [ $(self.action).path ] + $(self.extra-path) + ] ; - return [ path.native $(path) ] ; + return [ path.native $(path) ] ; + } } } diff --git a/v2/test/prebuilt.py b/v2/test/prebuilt.py new file mode 100644 index 000000000..46d90a39e --- /dev/null +++ b/v2/test/prebuilt.py @@ -0,0 +1,26 @@ +#!/usr/bin/python + +# Test that we can use already built sources + +from BoostBuild import Tester +t = Tester() + +t.set_tree('prebuilt') + +# First, build the external project +t.run_build_system("debug release", subdir="ext") + +# Then pretend that we don't have the sources for the external project, +# and can only use compiled binaries +t.copy("ext/Jamfile2", "ext/Jamfile") + +# Now check that we can build the main project, and that +# correct prebuilt file is picked, depending of variant. +# This also checks that correct includes for prebuilt +# libraries are used. + +t.run_build_system("debug release") +t.expect_addition("bin/gcc/debug/main-target-hello/hello") +t.expect_addition("bin/gcc/release/main-target-hello/hello") + +t.cleanup() diff --git a/v2/test/prebuilt/Jamfile b/v2/test/prebuilt/Jamfile new file mode 100644 index 000000000..eea94af4d --- /dev/null +++ b/v2/test/prebuilt/Jamfile @@ -0,0 +1,9 @@ + +project test + : requirements release:RELEASE + ; + +use-project /ext : ext ; + +exe hello : hello.cpp @/ext/a ; + diff --git a/v2/test/prebuilt/ext/Jamfile b/v2/test/prebuilt/ext/Jamfile new file mode 100644 index 000000000..3393bbea9 --- /dev/null +++ b/v2/test/prebuilt/ext/Jamfile @@ -0,0 +1,6 @@ + +project ext + : requirements release:RELEASE + ; + +lib a : a.cpp ; \ No newline at end of file diff --git a/v2/test/prebuilt/ext/Jamfile2 b/v2/test/prebuilt/ext/Jamfile2 new file mode 100644 index 000000000..5d57442c0 --- /dev/null +++ b/v2/test/prebuilt/ext/Jamfile2 @@ -0,0 +1,15 @@ + +project ext ; + +prebuilt LIB a + : bin/gcc/debug/a.a + : debug + : debug + ; + +prebuilt LIB a + : bin/gcc/release/a.a + : release + : release + ; + \ No newline at end of file diff --git a/v2/test/prebuilt/ext/a.cpp b/v2/test/prebuilt/ext/a.cpp new file mode 100644 index 000000000..6f5e59e08 --- /dev/null +++ b/v2/test/prebuilt/ext/a.cpp @@ -0,0 +1,6 @@ + +#ifdef RELEASE +void release() {} +#else +void debug() {} +#endif \ No newline at end of file diff --git a/v2/test/prebuilt/ext/debug/a.h b/v2/test/prebuilt/ext/debug/a.h new file mode 100644 index 000000000..d5eade04b --- /dev/null +++ b/v2/test/prebuilt/ext/debug/a.h @@ -0,0 +1,2 @@ + +void debug(); \ No newline at end of file diff --git a/v2/test/prebuilt/ext/project-root.jam b/v2/test/prebuilt/ext/project-root.jam new file mode 100644 index 000000000..be01ebeeb --- /dev/null +++ b/v2/test/prebuilt/ext/project-root.jam @@ -0,0 +1,2 @@ + +import gcc ; \ No newline at end of file diff --git a/v2/test/prebuilt/ext/release/a.h b/v2/test/prebuilt/ext/release/a.h new file mode 100644 index 000000000..4fa6fc3c8 --- /dev/null +++ b/v2/test/prebuilt/ext/release/a.h @@ -0,0 +1,2 @@ + +void release(); \ No newline at end of file diff --git a/v2/test/prebuilt/hello.cpp b/v2/test/prebuilt/hello.cpp new file mode 100644 index 000000000..0be150916 --- /dev/null +++ b/v2/test/prebuilt/hello.cpp @@ -0,0 +1,11 @@ + +#include + +int main() +{ + #ifdef RELEASE + release(); + #else + debug(); + #endif +} \ No newline at end of file diff --git a/v2/test/prebuilt/project-root.jam b/v2/test/prebuilt/project-root.jam new file mode 100644 index 000000000..be01ebeeb --- /dev/null +++ b/v2/test/prebuilt/project-root.jam @@ -0,0 +1,2 @@ + +import gcc ; \ No newline at end of file diff --git a/v2/test/project_test4.py b/v2/test/project_test4.py index f8ed60f4c..70a2c664f 100644 --- a/v2/test/project_test4.py +++ b/v2/test/project_test4.py @@ -71,22 +71,25 @@ expected="""warning: skipping build of project /mylib at lib2 t.run_build_system("rtti=on", stdout=expected, status=None) # We don't yet make targets depend on Jamfile, so need to start from scratch -t.set_tree("project-test4") -t.copy("Jamfile2", "Jamfile") +# The following test is disabled, because of problems related to +# issue 634319 -t.run_build_system() +#t.set_tree("project-test4") +#t.copy("Jamfile2", "Jamfile") -t.expect_addition("bin/gcc/debug/a_gcc.obj") -t.expect_content("bin/gcc/debug/a_gcc.obj", -"""gcc/debug -a_gcc.cpp -""") +#t.run_build_system() -t.expect_content("bin/gcc/debug/a.exe", -"gcc/debug\n" + -"bin/gcc/debug/a.obj " + -"lib/bin/gcc/debug/optimization-on/b.obj " + -"bin/gcc/debug/a_gcc.obj\n" -) +#t.expect_addition("bin/gcc/debug/a_gcc.obj") +#t.expect_content("bin/gcc/debug/a_gcc.obj", +#"""gcc/debug +#a_gcc.cpp +#""") + +#t.expect_content("bin/gcc/debug/a.exe", +#"gcc/debug\n" + +#"bin/gcc/debug/a.obj " + +#"lib/bin/gcc/debug/optimization-on/b.obj " + +#"bin/gcc/debug/a_gcc.obj\n" +#) t.cleanup() diff --git a/v2/test/stage.py b/v2/test/stage.py new file mode 100644 index 000000000..9af8e4192 --- /dev/null +++ b/v2/test/stage.py @@ -0,0 +1,19 @@ +#!/usr/bin/python + +# Test staging + +from BoostBuild import Tester +t = Tester() + +t.write("project-root.jam", "import gcc ;") +t.write("Jamfile", """ +lib a : a.cpp ; +stage dist : a a.h ; +""") +t.write("a.cpp", "") +t.write("a.h", "") + +t.run_build_system() +t.expect_addition(["dist/a.a", "dist/a.h"]) + +t.cleanup() diff --git a/v2/test/test_all.py b/v2/test/test_all.py index 67d5b1404..f2991f7e9 100644 --- a/v2/test/test_all.py +++ b/v2/test/test_all.py @@ -30,3 +30,5 @@ import default_build import main_properties import use_requirements import conditionals +import stage +import prebuilt diff --git a/v2/tools/builtin.jam b/v2/tools/builtin.jam index 52336bf4e..430ec40f7 100644 --- a/v2/tools/builtin.jam +++ b/v2/tools/builtin.jam @@ -14,8 +14,10 @@ import generators ; import regex ; import virtual-target ; import os ; +import stage ; +import prebuilt ; -feature toolset : gcc : implicit propagated ; +feature toolset : gcc : implicit propagated link-incompatible ; feature shared : false true : propagated ; feature optimization : off on : propagated ; feature threading : single multi : link-incompatible propagated ; diff --git a/v2/tools/common.jam b/v2/tools/common.jam index 0d971c2a4..74b619540 100644 --- a/v2/tools/common.jam +++ b/v2/tools/common.jam @@ -61,3 +61,14 @@ actions piecemeal together existing Clean rm $(>) } +rule copy +{ +} + + +actions copy +{ + cp $(>) $(<) +} + + diff --git a/v2/tools/prebuilt.jam b/v2/tools/prebuilt.jam new file mode 100644 index 000000000..9609ea6a4 --- /dev/null +++ b/v2/tools/prebuilt.jam @@ -0,0 +1,56 @@ +# Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and +# distribute this software is granted provided this copyright notice appears in +# all copies. This software is provided "as is" without express or implied +# warranty, and with no claim as to its suitability for any purpose. + +# This module defines the 'prebuilt' rule, which allows to use targets +# created outside of Boost.Build, or for which no source is available.. + +import targets ; +import class : class new ; +import property ; +import errors : error ; +import type : type ; +import regex ; + +rule prebuilt-target-class ( name : project : type file : requirements * : use-requirements * ) +{ + abstract-target.__init__ $(name) : $(project) ; + self.type = $(type) ; + self.file = $(file) ; + self.requirements = $(requirements) ; + self.use-requirements = $(use-requirements) ; + + rule generate ( properties * ) + { + local pl = [ project.attribute $(self.project) location ] ; + local path = [ path.root [ path.native $(self.file:D) ] $(pl) ] ; + + # CONSIDER: refine properties? + local t = [ new virtual-target $(self.file:S=:D=) : $(self.type) + : $(self.project) ] ; + $(t).set-use-requirements $(self.use-requirements) ; + $(t).set-path $(path) ; + $(t).extra-grist [ property.as-path $(self.requirements) ] ; + $(t).suffix [ MATCH .(.*) : $(self.file:S) ] ; + return $(t) ; + } + + rule requirements ( ) + { + return $(self.requirements) ; + } +} + +class prebuilt-target-class : abstract-target ; + +rule prebuilt ( type target-name : file : requirements * : use-requirements * ) +{ + targets.main-target-alternative + $(target-name) [ CALLER_MODULE ] prebuilt-target-class : 2 : 3 : + : $(type) $(file) : $(requirements) : $(use-requirements) ; +} + +IMPORT $(__name__) : prebuilt : : prebuilt ; + + diff --git a/v2/tools/stage.jam b/v2/tools/stage.jam new file mode 100644 index 000000000..6adaed9c4 --- /dev/null +++ b/v2/tools/stage.jam @@ -0,0 +1,56 @@ +# Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and +# distribute this software is granted provided this copyright notice appears in +# all copies. This software is provided "as is" without express or implied +# warranty, and with no claim as to its suitability for any purpose. + +# This module defines the 'stage' rule, used to copy a set of targets to +# a single location + +import targets ; +import class : class new ; +import property ; +import errors : error ; +import type : type ; +import regex ; + +rule stage-target-class ( name-and-dir : project : sources * : requirements * : default-build * ) +{ + basic-target.__init__ $(name-and-dir) : $(project) : $(sources) : $(requirements) + : $(default-build) ; + + rule construct ( source-targets * : properties * ) + { + local result ; + for local i in $(source-targets) + { + local i2 = [ new virtual-target [ $(i).name ] : [ $(i).type ] + : $(self.project) ] ; + local a = [ new action $(i2) : $(i) : common.copy ] ; + $(i2).action $(a) ; + + local pl = [ project.attribute $(self.project) location ] ; + local path = [ path.root [ path.native $(self.name) ] $(pl) ] ; + + $(i2).set-path $(path) ; + $(i2).extra-grist stage-$(self.name) ; + result += $(i2) ; + } + return $(result) ; + } +} + +class stage-target-class : basic-target ; + +rule stage ( directory : sources * : requirements * : default-build * ) +{ + # FIXME: for now, just use directory as target name. We really + # need to implement unnamed main targets. + targets.main-target-alternative + $(directory) [ CALLER_MODULE ] stage-target-class : 2 : : 3 + : $(sources) : $(requirements) : $(default-build) ; +} + +IMPORT $(__name__) : stage : : stage ; + + +