mirror of
https://github.com/boostorg/build.git
synced 2026-02-20 14:42:14 +00:00
First implementation of "stage" and "prebuilt" rule.
* new/common.jam (copy): New rule. * new/targets.jam (main-target.generate): Use a different algorith for selecting subvariant. Favour one with the longest intersection of requirements with build properties. * new/virtual-target.jam (virtual-target): Eliminate 'subvariant' attribute. Use properties of action to for the same purpose. New methods 'set-path' and 'extra-grist'. [SVN r16129]
This commit is contained in:
@@ -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 ;
|
||||
|
||||
@@ -61,3 +61,14 @@ actions piecemeal together existing Clean
|
||||
rm $(>)
|
||||
}
|
||||
|
||||
rule copy
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
actions copy
|
||||
{
|
||||
cp $(>) $(<)
|
||||
}
|
||||
|
||||
|
||||
|
||||
56
new/prebuilt.jam
Normal file
56
new/prebuilt.jam
Normal file
@@ -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 ;
|
||||
|
||||
|
||||
56
new/stage.jam
Normal file
56
new/stage.jam
Normal file
@@ -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 ;
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) ] ;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
26
test/prebuilt.py
Normal file
26
test/prebuilt.py
Normal file
@@ -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()
|
||||
9
test/prebuilt/Jamfile
Normal file
9
test/prebuilt/Jamfile
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
project test
|
||||
: requirements <variant>release:<define>RELEASE
|
||||
;
|
||||
|
||||
use-project /ext : ext ;
|
||||
|
||||
exe hello : hello.cpp @/ext/a ;
|
||||
|
||||
6
test/prebuilt/ext/Jamfile
Normal file
6
test/prebuilt/ext/Jamfile
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
project ext
|
||||
: requirements <variant>release:<define>RELEASE
|
||||
;
|
||||
|
||||
lib a : a.cpp ;
|
||||
15
test/prebuilt/ext/Jamfile2
Normal file
15
test/prebuilt/ext/Jamfile2
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
project ext ;
|
||||
|
||||
prebuilt LIB a
|
||||
: bin/gcc/debug/a.a
|
||||
: <variant>debug
|
||||
: <include>debug
|
||||
;
|
||||
|
||||
prebuilt LIB a
|
||||
: bin/gcc/release/a.a
|
||||
: <variant>release
|
||||
: <include>release
|
||||
;
|
||||
|
||||
6
test/prebuilt/ext/a.cpp
Normal file
6
test/prebuilt/ext/a.cpp
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
#ifdef RELEASE
|
||||
void release() {}
|
||||
#else
|
||||
void debug() {}
|
||||
#endif
|
||||
2
test/prebuilt/ext/debug/a.h
Normal file
2
test/prebuilt/ext/debug/a.h
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
void debug();
|
||||
2
test/prebuilt/ext/project-root.jam
Normal file
2
test/prebuilt/ext/project-root.jam
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
import gcc ;
|
||||
2
test/prebuilt/ext/release/a.h
Normal file
2
test/prebuilt/ext/release/a.h
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
void release();
|
||||
11
test/prebuilt/hello.cpp
Normal file
11
test/prebuilt/hello.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
#include <a.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef RELEASE
|
||||
release();
|
||||
#else
|
||||
debug();
|
||||
#endif
|
||||
}
|
||||
2
test/prebuilt/project-root.jam
Normal file
2
test/prebuilt/project-root.jam
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
import gcc ;
|
||||
@@ -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()
|
||||
|
||||
19
test/stage.py
Normal file
19
test/stage.py
Normal file
@@ -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()
|
||||
@@ -30,3 +30,5 @@ import default_build
|
||||
import main_properties
|
||||
import use_requirements
|
||||
import conditionals
|
||||
import stage
|
||||
import prebuilt
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) ] ;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
26
v2/test/prebuilt.py
Normal file
26
v2/test/prebuilt.py
Normal file
@@ -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()
|
||||
9
v2/test/prebuilt/Jamfile
Normal file
9
v2/test/prebuilt/Jamfile
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
project test
|
||||
: requirements <variant>release:<define>RELEASE
|
||||
;
|
||||
|
||||
use-project /ext : ext ;
|
||||
|
||||
exe hello : hello.cpp @/ext/a ;
|
||||
|
||||
6
v2/test/prebuilt/ext/Jamfile
Normal file
6
v2/test/prebuilt/ext/Jamfile
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
project ext
|
||||
: requirements <variant>release:<define>RELEASE
|
||||
;
|
||||
|
||||
lib a : a.cpp ;
|
||||
15
v2/test/prebuilt/ext/Jamfile2
Normal file
15
v2/test/prebuilt/ext/Jamfile2
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
project ext ;
|
||||
|
||||
prebuilt LIB a
|
||||
: bin/gcc/debug/a.a
|
||||
: <variant>debug
|
||||
: <include>debug
|
||||
;
|
||||
|
||||
prebuilt LIB a
|
||||
: bin/gcc/release/a.a
|
||||
: <variant>release
|
||||
: <include>release
|
||||
;
|
||||
|
||||
6
v2/test/prebuilt/ext/a.cpp
Normal file
6
v2/test/prebuilt/ext/a.cpp
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
#ifdef RELEASE
|
||||
void release() {}
|
||||
#else
|
||||
void debug() {}
|
||||
#endif
|
||||
2
v2/test/prebuilt/ext/debug/a.h
Normal file
2
v2/test/prebuilt/ext/debug/a.h
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
void debug();
|
||||
2
v2/test/prebuilt/ext/project-root.jam
Normal file
2
v2/test/prebuilt/ext/project-root.jam
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
import gcc ;
|
||||
2
v2/test/prebuilt/ext/release/a.h
Normal file
2
v2/test/prebuilt/ext/release/a.h
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
void release();
|
||||
11
v2/test/prebuilt/hello.cpp
Normal file
11
v2/test/prebuilt/hello.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
#include <a.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef RELEASE
|
||||
release();
|
||||
#else
|
||||
debug();
|
||||
#endif
|
||||
}
|
||||
2
v2/test/prebuilt/project-root.jam
Normal file
2
v2/test/prebuilt/project-root.jam
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
import gcc ;
|
||||
@@ -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()
|
||||
|
||||
19
v2/test/stage.py
Normal file
19
v2/test/stage.py
Normal file
@@ -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()
|
||||
@@ -30,3 +30,5 @@ import default_build
|
||||
import main_properties
|
||||
import use_requirements
|
||||
import conditionals
|
||||
import stage
|
||||
import prebuilt
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
@@ -61,3 +61,14 @@ actions piecemeal together existing Clean
|
||||
rm $(>)
|
||||
}
|
||||
|
||||
rule copy
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
actions copy
|
||||
{
|
||||
cp $(>) $(<)
|
||||
}
|
||||
|
||||
|
||||
|
||||
56
v2/tools/prebuilt.jam
Normal file
56
v2/tools/prebuilt.jam
Normal file
@@ -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 ;
|
||||
|
||||
|
||||
56
v2/tools/stage.jam
Normal file
56
v2/tools/stage.jam
Normal file
@@ -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 ;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user