mirror of
https://github.com/boostorg/build.git
synced 2026-02-16 01:12:13 +00:00
Improve shared/static linking interface and
introduce separate <link-runtime> feature. Allow to use the 'lib' rule to declare libraries that should be searched for. * builtin.jam: Remove 'shared' features. Introduce 'link' and 'link-runtime'. (searched-lib-target): New class (searched-lib-generator): New generator. (lib-action): New class, derived from 'action'. Handles instances of 'searched-lib-target' in sources. Also, moves all libraries from sources to property value, so that we can repeat them twice in command line. (lib-generator): Generator which uses 'lib-action'. * generators.jam: Allow empty list of sources everywhere. * virtual-target.jam (file-target): Split into 'abstract-file-target' and 'file-target'. (abstra (action.actualize-sources): New rule. Allows to handle the fact that some sources are special, and should not become $(>) in action body. [SVN r16573]
This commit is contained in:
170
new/builtin.jam
170
new/builtin.jam
@@ -21,7 +21,10 @@ import errors : error ;
|
||||
import symlink ;
|
||||
|
||||
feature toolset : : implicit propagated link-incompatible symmetric ;
|
||||
feature shared : false true : propagated ;
|
||||
feature link : shared static : propagated ;
|
||||
feature link-runtime : shared static : propagated ;
|
||||
|
||||
|
||||
feature optimization : off on : propagated ;
|
||||
feature threading : single multi : link-incompatible propagated ;
|
||||
feature rtti : on off : link-incompatible propagated ;
|
||||
@@ -33,10 +36,14 @@ feature version : : free ;
|
||||
|
||||
feature dependency : : free dependency ;
|
||||
feature library : : free dependency ;
|
||||
feature find-library : : free ;
|
||||
feature find-shared-library : : free ;
|
||||
feature find-static-library : : free ;
|
||||
feature library-path : : free path ;
|
||||
feature library-file : : free path ;
|
||||
|
||||
feature name : : free ;
|
||||
feature search : : free path ;
|
||||
|
||||
feature variant : : implicit composite propagated symmetric ;
|
||||
|
||||
# Declares a new variant.
|
||||
@@ -121,6 +128,45 @@ IMPORT $(__name__) : variant : : variant ;
|
||||
variant debug : <optimization>off <debug-symbols>on ;
|
||||
variant release : <optimization>on <debug-symbols>off ;
|
||||
|
||||
rule searched-lib-target ( name
|
||||
: project
|
||||
: shared ?
|
||||
: real-name ?
|
||||
: search *
|
||||
)
|
||||
{
|
||||
abstract-file-target.__init__ $(name) : SEARCHED_LIB : $(project) ;
|
||||
|
||||
self.shared = $(shared) ;
|
||||
self.real-name = $(real-name) ;
|
||||
self.real-name ?= $(name) ;
|
||||
self.search = $(search) ;
|
||||
|
||||
rule shared ( )
|
||||
{
|
||||
return $(self.shared) ;
|
||||
}
|
||||
|
||||
rule real-name ( )
|
||||
{
|
||||
return $(self.real-name) ;
|
||||
}
|
||||
|
||||
rule search ( )
|
||||
{
|
||||
return $(self.search) ;
|
||||
}
|
||||
|
||||
rule actualize-location ( target )
|
||||
{
|
||||
NOTFILE $(target) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class searched-lib-target : abstract-file-target ;
|
||||
|
||||
|
||||
type.register LIB : : : main ;
|
||||
|
||||
# register the given type on the specified OSes, or on remaining OSes
|
||||
@@ -146,6 +192,8 @@ declare-type : STATIC_LIB : a : LIB : main ;
|
||||
declare-type NT : SHARED_LIB : dll : LIB : main ;
|
||||
declare-type : SHARED_LIB : so : LIB : main ;
|
||||
|
||||
declare-type : SEARCHED_LIB : : LIB : main ;
|
||||
|
||||
declare-type NT CYGWIN : EXE : exe : : main ;
|
||||
declare-type : EXE : : : main ;
|
||||
|
||||
@@ -238,11 +286,15 @@ rule lib-generator ( )
|
||||
{
|
||||
composing-generator.__init__ lib-generator : unknown-source-type : LIB : <main-target-type>LIB ;
|
||||
|
||||
rule run ( project name ? : properties * : sources + )
|
||||
rule run ( project name ? : properties * : sources * )
|
||||
{
|
||||
# Determine the needed target type
|
||||
local actual-type ;
|
||||
if <shared>true in $(properties)
|
||||
if <search> in $(properties:G) || <name> in $(properties:G)
|
||||
{
|
||||
actual-type = SEARCHED_LIB ;
|
||||
}
|
||||
else if <link>shared in $(properties)
|
||||
{
|
||||
actual-type = SHARED_LIB ;
|
||||
}
|
||||
@@ -261,6 +313,30 @@ class lib-generator : composing-generator ;
|
||||
|
||||
generators.register [ new lib-generator ] ;
|
||||
|
||||
rule searched-lib-generator ( )
|
||||
{
|
||||
generator.__init__ searched-lib-generator : : SEARCHED_LIB ;
|
||||
|
||||
rule run ( project name ? : properties * : sources * )
|
||||
{
|
||||
local shared ;
|
||||
if <link>shared in $(properties)
|
||||
{
|
||||
shared = true ;
|
||||
}
|
||||
return [ new searched-lib-target $(name) : $(project) : $(shared)
|
||||
: [ feature.get-values <name> : $(properties) ]
|
||||
: [ feature.get-values <search> : $(properties) ]
|
||||
] ;
|
||||
}
|
||||
}
|
||||
|
||||
class searched-lib-generator : generator ;
|
||||
|
||||
generators.register [ new searched-lib-generator ] ;
|
||||
|
||||
|
||||
|
||||
rule compile-action ( targets + : sources * : action-name : properties * )
|
||||
{
|
||||
action.__init__ $(targets) : $(sources) : $(action-name) : $(properties) ;
|
||||
@@ -305,6 +381,92 @@ rule register-c-compiler ( id : source-types + : target-types + :
|
||||
# register all generators as "generator.some-rule", not with "some-module.some-rule".)
|
||||
IMPORT $(__name__) : register-c-compiler : : generators.register-c-compiler ;
|
||||
|
||||
rule link-action ( targets + : sources * : action-name : properties * )
|
||||
{
|
||||
action.__init__ $(targets) : $(sources) : $(action-name) : $(properties) ;
|
||||
|
||||
rule adjust-properties ( properties * )
|
||||
{
|
||||
local extra ;
|
||||
for local s in $(self.sources)
|
||||
{
|
||||
if [ class.is-a $(s) : searched-lib-target ]
|
||||
{
|
||||
local name = [ $(s).real-name ] ;
|
||||
if [ $(s).shared ]
|
||||
{
|
||||
extra += <find-shared-library>$(name) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
extra += <find-static-library>$(name) ;
|
||||
}
|
||||
local search = [ $(s).search ] ;
|
||||
extra += <library-path>$(search) ;
|
||||
}
|
||||
# We also move orginary libs form sources to
|
||||
# "library" property. This allows us to
|
||||
# easily repeat all the list of libs on
|
||||
# command line, when it's needed.
|
||||
else if [ type.is-derived [ $(s).type ] LIB ]
|
||||
{
|
||||
extra += <library>$(s) ;
|
||||
}
|
||||
}
|
||||
ECHO "EXtra is " $(extra) ;
|
||||
return $(properties) $(extra) ;
|
||||
}
|
||||
|
||||
|
||||
rule actualize-sources ( sources * )
|
||||
{
|
||||
local real-sources ;
|
||||
for local s in $(sources)
|
||||
{
|
||||
if ! [ type.is-derived [ $(s).type ] LIB ]
|
||||
{
|
||||
real-sources += $(s) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.dependency-only-sources += [ $(s).actualize ] ;
|
||||
}
|
||||
}
|
||||
|
||||
action.actualize-sources $(real-sources) ;
|
||||
}
|
||||
}
|
||||
|
||||
class link-action : action ;
|
||||
|
||||
|
||||
rule linking-generator ( id : source-types + : target-types + :
|
||||
requirements * )
|
||||
{
|
||||
composing-generator.__init__ $(id) : $(source-types) : $(target-types) :
|
||||
$(requirements) ;
|
||||
|
||||
rule action-class ( )
|
||||
{
|
||||
return link-action ;
|
||||
}
|
||||
}
|
||||
|
||||
class linking-generator : composing-generator ;
|
||||
|
||||
|
||||
rule register-linker ( id : source-types + : target-types + :
|
||||
requirements * )
|
||||
{
|
||||
local g = [ new linking-generator $(id) : $(source-types)
|
||||
: $(target-types) : $(requirements) ] ;
|
||||
generators.register $(g) ;
|
||||
}
|
||||
|
||||
IMPORT $(__name__) : register-linker : : generators.register-linker ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
29
new/gcc.jam
29
new/gcc.jam
@@ -33,9 +33,9 @@ rule init ( a1 * : a2 * : a3 * )
|
||||
}
|
||||
|
||||
# Declare generators
|
||||
generators.register-composing gcc.link : LIB OBJ : EXE : <toolset>gcc ;
|
||||
generators.register-linker gcc.link : LIB OBJ : EXE : <toolset>gcc ;
|
||||
generators.register-composing gcc.archive : OBJ : STATIC_LIB : <toolset>gcc ;
|
||||
generators.register-composing gcc.link-dll : OBJ : SHARED_LIB : <toolset>gcc ;
|
||||
generators.register-linker gcc.link-dll : OBJ : SHARED_LIB : <toolset>gcc ;
|
||||
generators.register-c-compiler gcc.compile : CPP : OBJ : <toolset>gcc ;
|
||||
generators.register-c-compiler gcc.compile : C : OBJ : <toolset>gcc ;
|
||||
|
||||
@@ -55,13 +55,21 @@ actions compile
|
||||
# Declare flags and action for linking
|
||||
toolset.flags gcc.link OPTIONS <debug-symbols>on : -g ;
|
||||
toolset.flags gcc.link LINKPATH <library-path> ;
|
||||
toolset.flags gcc.link FINDLIBS <find-library> ;
|
||||
toolset.flags gcc.link LIBRARIES <library-file> ;
|
||||
toolset.flags gcc.link FINDLIBS-ST <find-static-library> ;
|
||||
toolset.flags gcc.link FINDLIBS-SA <find-shared-library> ;
|
||||
toolset.flags gcc.link LIBRARIES <library> ;
|
||||
toolset.flags gcc.link LINK-RUNTIME <link-runtime>static : static ;
|
||||
toolset.flags gcc.link LINK-RUNTIME <link-runtime>shared : dynamic ;
|
||||
|
||||
|
||||
rule link ( targets * : sources * : properties * )
|
||||
{
|
||||
ECHO "PROPS = " $(properties) ;
|
||||
}
|
||||
|
||||
actions link bind LIBRARIES
|
||||
{
|
||||
$(NAME:E=g++) $(OPTIONS) -L$(LINKPATH) -o $(<) $(>) $(LIBRARIES) -l$(FINDLIBS)
|
||||
$(NAME:E=g++) $(OPTIONS) -L$(LINKPATH) -o $(<) $(>) $(LIBRARIES) -Wl,-Bdynamic -l$(FINDLIBS-SA) -Wl,-Bstatic -l$(FINDLIBS-ST) $(LIBRARIES) -Wl,-Bdynamic -l$(FINDLIBS-SA) -Wl,-Bstatic -l$(FINDLIBS-ST) -Wl,-B$(LINK-RUNTIME)
|
||||
}
|
||||
|
||||
# Declare action for creating static libraries
|
||||
@@ -73,11 +81,14 @@ actions archive
|
||||
# Declare flags and action for linking shared libraries
|
||||
toolset.flags gcc.link-dll OPTIONS <debug-symbols>on : -g ;
|
||||
toolset.flags gcc.link-dll LINKPATH <library-path> ;
|
||||
toolset.flags gcc.link-dll FINDLIBS <find-library> ;
|
||||
toolset.flags gcc.link-dll LIBRARIES <library-file> ;
|
||||
toolset.flags gcc.link-dll FINDLIBS-ST <find-static-library> ;
|
||||
toolset.flags gcc.link-dll FINDLIBS-SA <find-shared-library> ;
|
||||
toolset.flags gcc.link-dll LIBRARIES <library> ;
|
||||
toolset.flags gcc.link-dll LINK-RUNTIME <link-runtime>static : static ;
|
||||
toolset.flags gcc.link-dll LINK-RUNTIME <link-runtime>shared : dynamic ;
|
||||
|
||||
actions link-dll bind LIBS
|
||||
|
||||
actions link-dll bind LIBRARIES
|
||||
{
|
||||
$(NAME:E=g++) $(OPTIONS) -o $(<) -Wl,-soname,$(<[1]:D=) -shared $(>) $(LIBS) $(FINDLIBS)
|
||||
$(NAME:E=g++) $(OPTIONS) -o $(<) -Wl,-soname,$(<[1]:D=) -shared $(>) $(LIBRARIES) -Wl,-Bdynamic -l$(FINDLIBS-SA) -Wl,-Bstatic -l$(FINDLIBS-ST) $(LIBRARIES) -Wl,-Bdynamic -l$(FINDLIBS-SA) -Wl,-Bstatic -l$(FINDLIBS-ST) -Wl,-B$(LINK-RUNTIME)
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ rule generator (
|
||||
id # identifies the generator - should be name of the rule which
|
||||
# sets up build actions
|
||||
|
||||
: source-types + # types that this generator can handle
|
||||
: source-types * # types that this generator can handle
|
||||
|
||||
: target-types-and-names +
|
||||
# types the generator will create and, optionally, names for
|
||||
@@ -457,6 +457,7 @@ rule register ( g )
|
||||
{
|
||||
.generators.$(t) += $(g) ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -486,7 +487,7 @@ rule register-composing ( id : source-types + : target-types + : requirements *
|
||||
|
||||
|
||||
rule try-one-generator ( project name ? : generator multiple ? :
|
||||
target-types + : properties * : sources + )
|
||||
target-types + : properties * : sources * )
|
||||
{
|
||||
generators.dout [ indent ] " trying generator" [ $(generator).id ]
|
||||
"for" $(target-types:J=" ") "(" $(multiple) ")" ;
|
||||
@@ -752,7 +753,7 @@ local rule select-dependency-graph ( options )
|
||||
# 'construct' in stack, returns only targets of requested 'target-type',
|
||||
# otherwise, returns also unused sources and additionally generated
|
||||
# targets.
|
||||
rule construct ( project name ? : target-type multiple ? : properties * : sources +
|
||||
rule construct ( project name ? : target-type multiple ? : properties * : sources *
|
||||
: allow-composing ? # Allows to use composing generators for constructing this
|
||||
# target. This will be typically set when creating main targets,
|
||||
# and unset when called recursively from 'run' method of
|
||||
|
||||
@@ -137,7 +137,9 @@ rule virtual-target ( name # Name of this target -- specifies the name of
|
||||
class virtual-target ;
|
||||
|
||||
|
||||
# Target which correspond to a file.
|
||||
# Target which correspond to a file. The exact mapping for file
|
||||
# is not yet specified in this class. (TODO: Actually, the class name
|
||||
# could be better...)
|
||||
#
|
||||
# May be a source file (when no action is specified), or
|
||||
# derived file (otherwise).
|
||||
@@ -146,19 +148,7 @@ class virtual-target ;
|
||||
# properties of action (for derived files), and the value
|
||||
# passed to 'extra-grist'.
|
||||
#
|
||||
# The file path is determined as
|
||||
# - value passed to the 'set-path' method, if any
|
||||
# - for derived files, project's build dir, joined with components
|
||||
# that describe action's properties. If the free properties
|
||||
# are not equal to the project's reference properties
|
||||
# an element with name of main target is added.
|
||||
# - for source files, project's source dir
|
||||
#
|
||||
# The file suffix is
|
||||
# - the value passed to the 'suffix' method, if any, or
|
||||
# - the suffix which correspond to the target's type.
|
||||
#
|
||||
rule file-target ( name
|
||||
rule abstract-file-target ( name
|
||||
: type ? # Optional type for this target
|
||||
: project
|
||||
)
|
||||
@@ -258,43 +248,7 @@ rule file-target ( name
|
||||
common.Clean clean : $(name) ;
|
||||
}
|
||||
}
|
||||
|
||||
rule actualize-location ( target )
|
||||
{
|
||||
compute-extra-path ;
|
||||
if $(self.path)
|
||||
{
|
||||
LOCATE on $(target) = $(self.path) ;
|
||||
# Make sure the path exists. Do this only
|
||||
# for derived files.
|
||||
if $(self.action)
|
||||
{
|
||||
DEPENDS $(target) : $(self.path) ;
|
||||
common.MkDir $(self.path) ;
|
||||
}
|
||||
}
|
||||
else if $(self.action)
|
||||
{
|
||||
# This is a derived file.
|
||||
local path = [ path.native [ path.join
|
||||
[ project.attribute $(self.project) location ]
|
||||
[ $(self.action).path ]
|
||||
$(self.extra-path)
|
||||
] ] ;
|
||||
LOCATE on $(target) = $(path) ;
|
||||
|
||||
# Make sure the path exists.
|
||||
DEPENDS $(target) : $(path) ;
|
||||
common.MkDir $(path) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
# This is a source file.
|
||||
SEARCH on $(target) =
|
||||
[ path.native [ project.attribute $(self.project) source-location ] ] ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rule str ( )
|
||||
{
|
||||
local action = [ action ] ;
|
||||
@@ -377,6 +331,92 @@ rule file-target ( name
|
||||
return $(self.actual-name) ;
|
||||
}
|
||||
|
||||
}
|
||||
class abstract-file-target : virtual-target ;
|
||||
|
||||
# File target with explicitly known location.
|
||||
#
|
||||
# The file path is determined as
|
||||
# - value passed to the 'set-path' method, if any
|
||||
# - for derived files, project's build dir, joined with components
|
||||
# that describe action's properties. If the free properties
|
||||
# are not equal to the project's reference properties
|
||||
# an element with name of main target is added.
|
||||
# - for source files, project's source dir
|
||||
#
|
||||
# The file suffix is
|
||||
# - the value passed to the 'suffix' method, if any, or
|
||||
# - the suffix which correspond to the target's type.
|
||||
#
|
||||
rule file-target (
|
||||
name
|
||||
: type ? # Optional type for this target
|
||||
: project
|
||||
)
|
||||
{
|
||||
abstract-file-target.__init__ $(name) : $(type) : $(project) ;
|
||||
|
||||
rule actualize-location ( target )
|
||||
{
|
||||
compute-extra-path ;
|
||||
if $(self.path)
|
||||
{
|
||||
LOCATE on $(target) = $(self.path) ;
|
||||
# Make sure the path exists. Do this only
|
||||
# for derived files.
|
||||
if $(self.action)
|
||||
{
|
||||
DEPENDS $(target) : $(self.path) ;
|
||||
common.MkDir $(self.path) ;
|
||||
}
|
||||
}
|
||||
else if $(self.action)
|
||||
{
|
||||
# This is a derived file.
|
||||
local path = [ path.native [ path.join
|
||||
[ project.attribute $(self.project) location ]
|
||||
[ $(self.action).path ]
|
||||
$(self.extra-path)
|
||||
] ] ;
|
||||
LOCATE on $(target) = $(path) ;
|
||||
|
||||
# Make sure the path exists.
|
||||
DEPENDS $(target) : $(path) ;
|
||||
common.MkDir $(path) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
# This is a source file.
|
||||
SEARCH on $(target) =
|
||||
[ path.native [ project.attribute $(self.project) source-location ] ] ;
|
||||
}
|
||||
}
|
||||
|
||||
rule compute-extra-path ( )
|
||||
{
|
||||
if $(self.action)
|
||||
{
|
||||
local properties = [ property.take free : [ property.remove incidental :
|
||||
[ $(self.action).properties ] ] ] ;
|
||||
|
||||
local main-target = [ $(self.dg).main-target ] ;
|
||||
local project = [ $(main-target).project ] ;
|
||||
local plocation = [ project.attribute $(project) location ] ;
|
||||
local ptarget = [ project.target $(plocation) ] ;
|
||||
local ref = [ $(ptarget).reference-properties [ $(self.dg).properties ] ] ;
|
||||
|
||||
properties = [ sequence.insertion-sort
|
||||
[ sequence.unique $(properties) ] ] ;
|
||||
ref = [ sequence.insertion-sort
|
||||
[ sequence.unique $(ref) ] ] ;
|
||||
|
||||
if $(properties) != $(ref)
|
||||
{
|
||||
self.extra-path = [ sequence.join main-target- [ $(main-target).name ] ] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Returns the directory for this target
|
||||
# ### This partly DUPLICATES functionality of actualize-location
|
||||
# above. Seems like subvariant-dg.all-target-paths is the only method
|
||||
@@ -398,30 +438,13 @@ rule file-target ( name
|
||||
|
||||
return [ path.native $(path) ] ;
|
||||
}
|
||||
}
|
||||
|
||||
rule compute-extra-path ( )
|
||||
{
|
||||
if $(self.action)
|
||||
{
|
||||
local properties = [ property.take free : [ property.remove incidental :
|
||||
[ $(self.action).properties ] ] ] ;
|
||||
|
||||
local main-target = [ $(self.dg).main-target ] ;
|
||||
local project = [ $(main-target).project ] ;
|
||||
local plocation = [ project.attribute $(project) location ] ;
|
||||
local ptarget = [ project.target $(plocation) ] ;
|
||||
local ref = [ $(ptarget).reference-properties [ $(self.dg).properties ] ] ;
|
||||
|
||||
if $(properties) != $(ref)
|
||||
{
|
||||
self.extra-path = [ sequence.join main-target- [ $(main-target).name ] ] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
class file-target : virtual-target ;
|
||||
|
||||
class file-target : abstract-file-target ;
|
||||
|
||||
|
||||
|
||||
# Returns the binding for the given actual target.
|
||||
# CONSIDER: not sure this rule belongs here.
|
||||
@@ -479,34 +502,47 @@ rule action ( targets + : sources * : action-name : properties * )
|
||||
|
||||
local properties = [ adjust-properties [ properties ] ] ;
|
||||
|
||||
|
||||
local actual-targets ;
|
||||
for local i in [ targets ]
|
||||
{
|
||||
actual-targets += [ $(i).actualize ] ;
|
||||
}
|
||||
|
||||
actualize-sources [ sources ] ;
|
||||
|
||||
DEPENDS $(actual-targets) : $(self.actual-sources) $(self.dependency-only-sources) ;
|
||||
|
||||
local actual-sources ;
|
||||
for local i in [ sources ]
|
||||
{
|
||||
local scanner ;
|
||||
if [ $(i).type ]
|
||||
{
|
||||
scanner =
|
||||
[ type.get-scanner [ $(i).type ] : $(properties) ] ;
|
||||
}
|
||||
actual-sources += [ $(i).actualize $(scanner) ] ;
|
||||
}
|
||||
|
||||
DEPENDS $(actual-targets) : $(actual-sources) ;
|
||||
|
||||
toolset.set-target-variables $(self.action-name) $(actual-targets[0]) :
|
||||
$(properties) ;
|
||||
toolset.set-target-variables $(self.action-name) $(actual-targets[0]) :
|
||||
$(properties) ;
|
||||
|
||||
$(self.action-name)
|
||||
$(actual-targets) : $(actual-sources) : $(properties) ;
|
||||
$(actual-targets) : $(self.actual-sources) : $(properties) ;
|
||||
}
|
||||
}
|
||||
|
||||
# Creates actual jam targets for sources. Initialized two member
|
||||
# variables:.
|
||||
# 'self.actual-sources' -- sources which are passed to updating action
|
||||
# 'self.dependency-only-sources' -- sources which are made dependencies, but
|
||||
# are not used otherwise.
|
||||
#
|
||||
# New values will be *appended* to the variables. They may be non-empty,
|
||||
# if caller wants it.
|
||||
rule actualize-sources ( sources * )
|
||||
{
|
||||
for local i in $(sources)
|
||||
{
|
||||
local scanner ;
|
||||
if [ $(i).type ]
|
||||
{
|
||||
scanner =
|
||||
[ type.get-scanner [ $(i).type ] : $(properties) ] ;
|
||||
}
|
||||
self.actual-sources += [ $(i).actualize $(scanner) ] ;
|
||||
}
|
||||
}
|
||||
|
||||
rule path ( )
|
||||
{
|
||||
local subvariant = [ property.remove free incidental : $(self.properties) ] ;
|
||||
|
||||
@@ -10,19 +10,19 @@ t = Tester()
|
||||
|
||||
t.write("project-root.jam", "import gcc ;")
|
||||
t.write("a.cpp", """
|
||||
#ifdef SHARED
|
||||
#ifdef STATIC
|
||||
int main() {}
|
||||
#endif
|
||||
""")
|
||||
t.write("Jamfile", "exe a : a.cpp : <shared>true:<define>SHARED ;")
|
||||
t.run_build_system("shared=true")
|
||||
t.expect_addition("bin/gcc/debug/shared-true/main-target-a/a")
|
||||
t.write("Jamfile", "exe a : a.cpp : <link>static:<define>STATIC ;")
|
||||
t.run_build_system("link=static")
|
||||
t.expect_addition("bin/gcc/debug/link-static/main-target-a/a")
|
||||
|
||||
t.write("Jamfile", """
|
||||
project : requirements <shared>true:<define>SHARED ;
|
||||
project : requirements <link>static:<define>STATIC ;
|
||||
exe a : a.cpp ;
|
||||
""")
|
||||
t.run_build_system("shared=true")
|
||||
t.expect_addition("bin/gcc/debug/shared-true/a")
|
||||
t.run_build_system("link=static")
|
||||
t.expect_addition("bin/gcc/debug/link-static/a")
|
||||
|
||||
t.cleanup()
|
||||
|
||||
@@ -10,6 +10,6 @@ t = Tester()
|
||||
t.set_tree("direct-request-test")
|
||||
t.run_build_system(extra_args="define=MACROS")
|
||||
|
||||
t.expect_addition("bin/gcc/debug/" * List("a.o b.o b.a a"))
|
||||
t.expect_addition("bin/gcc/debug/" * List("a.o b.o b.so a"))
|
||||
|
||||
t.cleanup()
|
||||
|
||||
@@ -19,10 +19,10 @@ t.expect_addition(["lib/bin/gcc/debug/c.o",
|
||||
|
||||
t.run_build_system(subdir='lib')
|
||||
|
||||
t.expect_addition(["lib/bin/gcc/debug/auxilliary2.a"])
|
||||
t.expect_addition(["lib/bin/gcc/debug/auxilliary2.so"])
|
||||
|
||||
t.run_build_system(subdir='lib', extra_args="shared=true")
|
||||
t.run_build_system(subdir='lib', extra_args="link=static")
|
||||
|
||||
t.expect_addition(["lib/bin/gcc/debug/shared-true/auxilliary2.so"])
|
||||
t.expect_addition(["lib/bin/gcc/debug/link-static/auxilliary2.a"])
|
||||
|
||||
t.cleanup()
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
project ext ;
|
||||
|
||||
prebuilt LIB a
|
||||
: bin/gcc/debug/a.a
|
||||
: bin/gcc/debug/a.so
|
||||
: <variant>debug
|
||||
: <include>debug
|
||||
;
|
||||
|
||||
prebuilt LIB a
|
||||
: bin/gcc/release/a.a
|
||||
: bin/gcc/release/a.so
|
||||
: <variant>release
|
||||
: <include>release
|
||||
;
|
||||
|
||||
@@ -45,9 +45,9 @@ t.run_build_system("--no-error-backtrace", stdout=expected, status=None)
|
||||
|
||||
t.copy("lib/Jamfile3", "lib/Jamfile")
|
||||
|
||||
expected="""warning: skipped build of lib/b.obj with properties <toolset>gcc
|
||||
<shared>false <optimization>on <threading>single <rtti>on <debug-symbols>on
|
||||
<variant>debug
|
||||
expected="""warning: skipped build of lib/b.obj with properties <toolset>gcc <link>shared
|
||||
<link-runtime>shared <optimization>on <threading>single <rtti>on
|
||||
<debug-symbols>on <variant>debug
|
||||
don't know how to make <.>lib/b.obj/<optimization>on
|
||||
...skipped <./gcc/debug>a.exe for lack of <.>lib/b.obj/<optimization>on...
|
||||
"""
|
||||
|
||||
@@ -14,6 +14,6 @@ t.write("a.cpp", "")
|
||||
t.write("a.h", "")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition(["dist/a.a", "dist/a.h"])
|
||||
t.expect_addition(["dist/a.so", "dist/a.h"])
|
||||
|
||||
t.cleanup()
|
||||
|
||||
@@ -92,7 +92,7 @@ rule generator (
|
||||
id # identifies the generator - should be name of the rule which
|
||||
# sets up build actions
|
||||
|
||||
: source-types + # types that this generator can handle
|
||||
: source-types * # types that this generator can handle
|
||||
|
||||
: target-types-and-names +
|
||||
# types the generator will create and, optionally, names for
|
||||
@@ -457,6 +457,7 @@ rule register ( g )
|
||||
{
|
||||
.generators.$(t) += $(g) ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -486,7 +487,7 @@ rule register-composing ( id : source-types + : target-types + : requirements *
|
||||
|
||||
|
||||
rule try-one-generator ( project name ? : generator multiple ? :
|
||||
target-types + : properties * : sources + )
|
||||
target-types + : properties * : sources * )
|
||||
{
|
||||
generators.dout [ indent ] " trying generator" [ $(generator).id ]
|
||||
"for" $(target-types:J=" ") "(" $(multiple) ")" ;
|
||||
@@ -752,7 +753,7 @@ local rule select-dependency-graph ( options )
|
||||
# 'construct' in stack, returns only targets of requested 'target-type',
|
||||
# otherwise, returns also unused sources and additionally generated
|
||||
# targets.
|
||||
rule construct ( project name ? : target-type multiple ? : properties * : sources +
|
||||
rule construct ( project name ? : target-type multiple ? : properties * : sources *
|
||||
: allow-composing ? # Allows to use composing generators for constructing this
|
||||
# target. This will be typically set when creating main targets,
|
||||
# and unset when called recursively from 'run' method of
|
||||
|
||||
@@ -137,7 +137,9 @@ rule virtual-target ( name # Name of this target -- specifies the name of
|
||||
class virtual-target ;
|
||||
|
||||
|
||||
# Target which correspond to a file.
|
||||
# Target which correspond to a file. The exact mapping for file
|
||||
# is not yet specified in this class. (TODO: Actually, the class name
|
||||
# could be better...)
|
||||
#
|
||||
# May be a source file (when no action is specified), or
|
||||
# derived file (otherwise).
|
||||
@@ -146,19 +148,7 @@ class virtual-target ;
|
||||
# properties of action (for derived files), and the value
|
||||
# passed to 'extra-grist'.
|
||||
#
|
||||
# The file path is determined as
|
||||
# - value passed to the 'set-path' method, if any
|
||||
# - for derived files, project's build dir, joined with components
|
||||
# that describe action's properties. If the free properties
|
||||
# are not equal to the project's reference properties
|
||||
# an element with name of main target is added.
|
||||
# - for source files, project's source dir
|
||||
#
|
||||
# The file suffix is
|
||||
# - the value passed to the 'suffix' method, if any, or
|
||||
# - the suffix which correspond to the target's type.
|
||||
#
|
||||
rule file-target ( name
|
||||
rule abstract-file-target ( name
|
||||
: type ? # Optional type for this target
|
||||
: project
|
||||
)
|
||||
@@ -258,43 +248,7 @@ rule file-target ( name
|
||||
common.Clean clean : $(name) ;
|
||||
}
|
||||
}
|
||||
|
||||
rule actualize-location ( target )
|
||||
{
|
||||
compute-extra-path ;
|
||||
if $(self.path)
|
||||
{
|
||||
LOCATE on $(target) = $(self.path) ;
|
||||
# Make sure the path exists. Do this only
|
||||
# for derived files.
|
||||
if $(self.action)
|
||||
{
|
||||
DEPENDS $(target) : $(self.path) ;
|
||||
common.MkDir $(self.path) ;
|
||||
}
|
||||
}
|
||||
else if $(self.action)
|
||||
{
|
||||
# This is a derived file.
|
||||
local path = [ path.native [ path.join
|
||||
[ project.attribute $(self.project) location ]
|
||||
[ $(self.action).path ]
|
||||
$(self.extra-path)
|
||||
] ] ;
|
||||
LOCATE on $(target) = $(path) ;
|
||||
|
||||
# Make sure the path exists.
|
||||
DEPENDS $(target) : $(path) ;
|
||||
common.MkDir $(path) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
# This is a source file.
|
||||
SEARCH on $(target) =
|
||||
[ path.native [ project.attribute $(self.project) source-location ] ] ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rule str ( )
|
||||
{
|
||||
local action = [ action ] ;
|
||||
@@ -377,6 +331,92 @@ rule file-target ( name
|
||||
return $(self.actual-name) ;
|
||||
}
|
||||
|
||||
}
|
||||
class abstract-file-target : virtual-target ;
|
||||
|
||||
# File target with explicitly known location.
|
||||
#
|
||||
# The file path is determined as
|
||||
# - value passed to the 'set-path' method, if any
|
||||
# - for derived files, project's build dir, joined with components
|
||||
# that describe action's properties. If the free properties
|
||||
# are not equal to the project's reference properties
|
||||
# an element with name of main target is added.
|
||||
# - for source files, project's source dir
|
||||
#
|
||||
# The file suffix is
|
||||
# - the value passed to the 'suffix' method, if any, or
|
||||
# - the suffix which correspond to the target's type.
|
||||
#
|
||||
rule file-target (
|
||||
name
|
||||
: type ? # Optional type for this target
|
||||
: project
|
||||
)
|
||||
{
|
||||
abstract-file-target.__init__ $(name) : $(type) : $(project) ;
|
||||
|
||||
rule actualize-location ( target )
|
||||
{
|
||||
compute-extra-path ;
|
||||
if $(self.path)
|
||||
{
|
||||
LOCATE on $(target) = $(self.path) ;
|
||||
# Make sure the path exists. Do this only
|
||||
# for derived files.
|
||||
if $(self.action)
|
||||
{
|
||||
DEPENDS $(target) : $(self.path) ;
|
||||
common.MkDir $(self.path) ;
|
||||
}
|
||||
}
|
||||
else if $(self.action)
|
||||
{
|
||||
# This is a derived file.
|
||||
local path = [ path.native [ path.join
|
||||
[ project.attribute $(self.project) location ]
|
||||
[ $(self.action).path ]
|
||||
$(self.extra-path)
|
||||
] ] ;
|
||||
LOCATE on $(target) = $(path) ;
|
||||
|
||||
# Make sure the path exists.
|
||||
DEPENDS $(target) : $(path) ;
|
||||
common.MkDir $(path) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
# This is a source file.
|
||||
SEARCH on $(target) =
|
||||
[ path.native [ project.attribute $(self.project) source-location ] ] ;
|
||||
}
|
||||
}
|
||||
|
||||
rule compute-extra-path ( )
|
||||
{
|
||||
if $(self.action)
|
||||
{
|
||||
local properties = [ property.take free : [ property.remove incidental :
|
||||
[ $(self.action).properties ] ] ] ;
|
||||
|
||||
local main-target = [ $(self.dg).main-target ] ;
|
||||
local project = [ $(main-target).project ] ;
|
||||
local plocation = [ project.attribute $(project) location ] ;
|
||||
local ptarget = [ project.target $(plocation) ] ;
|
||||
local ref = [ $(ptarget).reference-properties [ $(self.dg).properties ] ] ;
|
||||
|
||||
properties = [ sequence.insertion-sort
|
||||
[ sequence.unique $(properties) ] ] ;
|
||||
ref = [ sequence.insertion-sort
|
||||
[ sequence.unique $(ref) ] ] ;
|
||||
|
||||
if $(properties) != $(ref)
|
||||
{
|
||||
self.extra-path = [ sequence.join main-target- [ $(main-target).name ] ] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Returns the directory for this target
|
||||
# ### This partly DUPLICATES functionality of actualize-location
|
||||
# above. Seems like subvariant-dg.all-target-paths is the only method
|
||||
@@ -398,30 +438,13 @@ rule file-target ( name
|
||||
|
||||
return [ path.native $(path) ] ;
|
||||
}
|
||||
}
|
||||
|
||||
rule compute-extra-path ( )
|
||||
{
|
||||
if $(self.action)
|
||||
{
|
||||
local properties = [ property.take free : [ property.remove incidental :
|
||||
[ $(self.action).properties ] ] ] ;
|
||||
|
||||
local main-target = [ $(self.dg).main-target ] ;
|
||||
local project = [ $(main-target).project ] ;
|
||||
local plocation = [ project.attribute $(project) location ] ;
|
||||
local ptarget = [ project.target $(plocation) ] ;
|
||||
local ref = [ $(ptarget).reference-properties [ $(self.dg).properties ] ] ;
|
||||
|
||||
if $(properties) != $(ref)
|
||||
{
|
||||
self.extra-path = [ sequence.join main-target- [ $(main-target).name ] ] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
class file-target : virtual-target ;
|
||||
|
||||
class file-target : abstract-file-target ;
|
||||
|
||||
|
||||
|
||||
# Returns the binding for the given actual target.
|
||||
# CONSIDER: not sure this rule belongs here.
|
||||
@@ -479,34 +502,47 @@ rule action ( targets + : sources * : action-name : properties * )
|
||||
|
||||
local properties = [ adjust-properties [ properties ] ] ;
|
||||
|
||||
|
||||
local actual-targets ;
|
||||
for local i in [ targets ]
|
||||
{
|
||||
actual-targets += [ $(i).actualize ] ;
|
||||
}
|
||||
|
||||
actualize-sources [ sources ] ;
|
||||
|
||||
DEPENDS $(actual-targets) : $(self.actual-sources) $(self.dependency-only-sources) ;
|
||||
|
||||
local actual-sources ;
|
||||
for local i in [ sources ]
|
||||
{
|
||||
local scanner ;
|
||||
if [ $(i).type ]
|
||||
{
|
||||
scanner =
|
||||
[ type.get-scanner [ $(i).type ] : $(properties) ] ;
|
||||
}
|
||||
actual-sources += [ $(i).actualize $(scanner) ] ;
|
||||
}
|
||||
|
||||
DEPENDS $(actual-targets) : $(actual-sources) ;
|
||||
|
||||
toolset.set-target-variables $(self.action-name) $(actual-targets[0]) :
|
||||
$(properties) ;
|
||||
toolset.set-target-variables $(self.action-name) $(actual-targets[0]) :
|
||||
$(properties) ;
|
||||
|
||||
$(self.action-name)
|
||||
$(actual-targets) : $(actual-sources) : $(properties) ;
|
||||
$(actual-targets) : $(self.actual-sources) : $(properties) ;
|
||||
}
|
||||
}
|
||||
|
||||
# Creates actual jam targets for sources. Initialized two member
|
||||
# variables:.
|
||||
# 'self.actual-sources' -- sources which are passed to updating action
|
||||
# 'self.dependency-only-sources' -- sources which are made dependencies, but
|
||||
# are not used otherwise.
|
||||
#
|
||||
# New values will be *appended* to the variables. They may be non-empty,
|
||||
# if caller wants it.
|
||||
rule actualize-sources ( sources * )
|
||||
{
|
||||
for local i in $(sources)
|
||||
{
|
||||
local scanner ;
|
||||
if [ $(i).type ]
|
||||
{
|
||||
scanner =
|
||||
[ type.get-scanner [ $(i).type ] : $(properties) ] ;
|
||||
}
|
||||
self.actual-sources += [ $(i).actualize $(scanner) ] ;
|
||||
}
|
||||
}
|
||||
|
||||
rule path ( )
|
||||
{
|
||||
local subvariant = [ property.remove free incidental : $(self.properties) ] ;
|
||||
|
||||
29
v2/gcc.jam
29
v2/gcc.jam
@@ -33,9 +33,9 @@ rule init ( a1 * : a2 * : a3 * )
|
||||
}
|
||||
|
||||
# Declare generators
|
||||
generators.register-composing gcc.link : LIB OBJ : EXE : <toolset>gcc ;
|
||||
generators.register-linker gcc.link : LIB OBJ : EXE : <toolset>gcc ;
|
||||
generators.register-composing gcc.archive : OBJ : STATIC_LIB : <toolset>gcc ;
|
||||
generators.register-composing gcc.link-dll : OBJ : SHARED_LIB : <toolset>gcc ;
|
||||
generators.register-linker gcc.link-dll : OBJ : SHARED_LIB : <toolset>gcc ;
|
||||
generators.register-c-compiler gcc.compile : CPP : OBJ : <toolset>gcc ;
|
||||
generators.register-c-compiler gcc.compile : C : OBJ : <toolset>gcc ;
|
||||
|
||||
@@ -55,13 +55,21 @@ actions compile
|
||||
# Declare flags and action for linking
|
||||
toolset.flags gcc.link OPTIONS <debug-symbols>on : -g ;
|
||||
toolset.flags gcc.link LINKPATH <library-path> ;
|
||||
toolset.flags gcc.link FINDLIBS <find-library> ;
|
||||
toolset.flags gcc.link LIBRARIES <library-file> ;
|
||||
toolset.flags gcc.link FINDLIBS-ST <find-static-library> ;
|
||||
toolset.flags gcc.link FINDLIBS-SA <find-shared-library> ;
|
||||
toolset.flags gcc.link LIBRARIES <library> ;
|
||||
toolset.flags gcc.link LINK-RUNTIME <link-runtime>static : static ;
|
||||
toolset.flags gcc.link LINK-RUNTIME <link-runtime>shared : dynamic ;
|
||||
|
||||
|
||||
rule link ( targets * : sources * : properties * )
|
||||
{
|
||||
ECHO "PROPS = " $(properties) ;
|
||||
}
|
||||
|
||||
actions link bind LIBRARIES
|
||||
{
|
||||
$(NAME:E=g++) $(OPTIONS) -L$(LINKPATH) -o $(<) $(>) $(LIBRARIES) -l$(FINDLIBS)
|
||||
$(NAME:E=g++) $(OPTIONS) -L$(LINKPATH) -o $(<) $(>) $(LIBRARIES) -Wl,-Bdynamic -l$(FINDLIBS-SA) -Wl,-Bstatic -l$(FINDLIBS-ST) $(LIBRARIES) -Wl,-Bdynamic -l$(FINDLIBS-SA) -Wl,-Bstatic -l$(FINDLIBS-ST) -Wl,-B$(LINK-RUNTIME)
|
||||
}
|
||||
|
||||
# Declare action for creating static libraries
|
||||
@@ -73,11 +81,14 @@ actions archive
|
||||
# Declare flags and action for linking shared libraries
|
||||
toolset.flags gcc.link-dll OPTIONS <debug-symbols>on : -g ;
|
||||
toolset.flags gcc.link-dll LINKPATH <library-path> ;
|
||||
toolset.flags gcc.link-dll FINDLIBS <find-library> ;
|
||||
toolset.flags gcc.link-dll LIBRARIES <library-file> ;
|
||||
toolset.flags gcc.link-dll FINDLIBS-ST <find-static-library> ;
|
||||
toolset.flags gcc.link-dll FINDLIBS-SA <find-shared-library> ;
|
||||
toolset.flags gcc.link-dll LIBRARIES <library> ;
|
||||
toolset.flags gcc.link-dll LINK-RUNTIME <link-runtime>static : static ;
|
||||
toolset.flags gcc.link-dll LINK-RUNTIME <link-runtime>shared : dynamic ;
|
||||
|
||||
actions link-dll bind LIBS
|
||||
|
||||
actions link-dll bind LIBRARIES
|
||||
{
|
||||
$(NAME:E=g++) $(OPTIONS) -o $(<) -Wl,-soname,$(<[1]:D=) -shared $(>) $(LIBS) $(FINDLIBS)
|
||||
$(NAME:E=g++) $(OPTIONS) -o $(<) -Wl,-soname,$(<[1]:D=) -shared $(>) $(LIBRARIES) -Wl,-Bdynamic -l$(FINDLIBS-SA) -Wl,-Bstatic -l$(FINDLIBS-ST) $(LIBRARIES) -Wl,-Bdynamic -l$(FINDLIBS-SA) -Wl,-Bstatic -l$(FINDLIBS-ST) -Wl,-B$(LINK-RUNTIME)
|
||||
}
|
||||
|
||||
@@ -10,19 +10,19 @@ t = Tester()
|
||||
|
||||
t.write("project-root.jam", "import gcc ;")
|
||||
t.write("a.cpp", """
|
||||
#ifdef SHARED
|
||||
#ifdef STATIC
|
||||
int main() {}
|
||||
#endif
|
||||
""")
|
||||
t.write("Jamfile", "exe a : a.cpp : <shared>true:<define>SHARED ;")
|
||||
t.run_build_system("shared=true")
|
||||
t.expect_addition("bin/gcc/debug/shared-true/main-target-a/a")
|
||||
t.write("Jamfile", "exe a : a.cpp : <link>static:<define>STATIC ;")
|
||||
t.run_build_system("link=static")
|
||||
t.expect_addition("bin/gcc/debug/link-static/main-target-a/a")
|
||||
|
||||
t.write("Jamfile", """
|
||||
project : requirements <shared>true:<define>SHARED ;
|
||||
project : requirements <link>static:<define>STATIC ;
|
||||
exe a : a.cpp ;
|
||||
""")
|
||||
t.run_build_system("shared=true")
|
||||
t.expect_addition("bin/gcc/debug/shared-true/a")
|
||||
t.run_build_system("link=static")
|
||||
t.expect_addition("bin/gcc/debug/link-static/a")
|
||||
|
||||
t.cleanup()
|
||||
|
||||
@@ -10,6 +10,6 @@ t = Tester()
|
||||
t.set_tree("direct-request-test")
|
||||
t.run_build_system(extra_args="define=MACROS")
|
||||
|
||||
t.expect_addition("bin/gcc/debug/" * List("a.o b.o b.a a"))
|
||||
t.expect_addition("bin/gcc/debug/" * List("a.o b.o b.so a"))
|
||||
|
||||
t.cleanup()
|
||||
|
||||
@@ -19,10 +19,10 @@ t.expect_addition(["lib/bin/gcc/debug/c.o",
|
||||
|
||||
t.run_build_system(subdir='lib')
|
||||
|
||||
t.expect_addition(["lib/bin/gcc/debug/auxilliary2.a"])
|
||||
t.expect_addition(["lib/bin/gcc/debug/auxilliary2.so"])
|
||||
|
||||
t.run_build_system(subdir='lib', extra_args="shared=true")
|
||||
t.run_build_system(subdir='lib', extra_args="link=static")
|
||||
|
||||
t.expect_addition(["lib/bin/gcc/debug/shared-true/auxilliary2.so"])
|
||||
t.expect_addition(["lib/bin/gcc/debug/link-static/auxilliary2.a"])
|
||||
|
||||
t.cleanup()
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
project ext ;
|
||||
|
||||
prebuilt LIB a
|
||||
: bin/gcc/debug/a.a
|
||||
: bin/gcc/debug/a.so
|
||||
: <variant>debug
|
||||
: <include>debug
|
||||
;
|
||||
|
||||
prebuilt LIB a
|
||||
: bin/gcc/release/a.a
|
||||
: bin/gcc/release/a.so
|
||||
: <variant>release
|
||||
: <include>release
|
||||
;
|
||||
|
||||
@@ -45,9 +45,9 @@ t.run_build_system("--no-error-backtrace", stdout=expected, status=None)
|
||||
|
||||
t.copy("lib/Jamfile3", "lib/Jamfile")
|
||||
|
||||
expected="""warning: skipped build of lib/b.obj with properties <toolset>gcc
|
||||
<shared>false <optimization>on <threading>single <rtti>on <debug-symbols>on
|
||||
<variant>debug
|
||||
expected="""warning: skipped build of lib/b.obj with properties <toolset>gcc <link>shared
|
||||
<link-runtime>shared <optimization>on <threading>single <rtti>on
|
||||
<debug-symbols>on <variant>debug
|
||||
don't know how to make <.>lib/b.obj/<optimization>on
|
||||
...skipped <./gcc/debug>a.exe for lack of <.>lib/b.obj/<optimization>on...
|
||||
"""
|
||||
|
||||
@@ -14,6 +14,6 @@ t.write("a.cpp", "")
|
||||
t.write("a.h", "")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition(["dist/a.a", "dist/a.h"])
|
||||
t.expect_addition(["dist/a.so", "dist/a.h"])
|
||||
|
||||
t.cleanup()
|
||||
|
||||
@@ -21,7 +21,10 @@ import errors : error ;
|
||||
import symlink ;
|
||||
|
||||
feature toolset : : implicit propagated link-incompatible symmetric ;
|
||||
feature shared : false true : propagated ;
|
||||
feature link : shared static : propagated ;
|
||||
feature link-runtime : shared static : propagated ;
|
||||
|
||||
|
||||
feature optimization : off on : propagated ;
|
||||
feature threading : single multi : link-incompatible propagated ;
|
||||
feature rtti : on off : link-incompatible propagated ;
|
||||
@@ -33,10 +36,14 @@ feature version : : free ;
|
||||
|
||||
feature dependency : : free dependency ;
|
||||
feature library : : free dependency ;
|
||||
feature find-library : : free ;
|
||||
feature find-shared-library : : free ;
|
||||
feature find-static-library : : free ;
|
||||
feature library-path : : free path ;
|
||||
feature library-file : : free path ;
|
||||
|
||||
feature name : : free ;
|
||||
feature search : : free path ;
|
||||
|
||||
feature variant : : implicit composite propagated symmetric ;
|
||||
|
||||
# Declares a new variant.
|
||||
@@ -121,6 +128,45 @@ IMPORT $(__name__) : variant : : variant ;
|
||||
variant debug : <optimization>off <debug-symbols>on ;
|
||||
variant release : <optimization>on <debug-symbols>off ;
|
||||
|
||||
rule searched-lib-target ( name
|
||||
: project
|
||||
: shared ?
|
||||
: real-name ?
|
||||
: search *
|
||||
)
|
||||
{
|
||||
abstract-file-target.__init__ $(name) : SEARCHED_LIB : $(project) ;
|
||||
|
||||
self.shared = $(shared) ;
|
||||
self.real-name = $(real-name) ;
|
||||
self.real-name ?= $(name) ;
|
||||
self.search = $(search) ;
|
||||
|
||||
rule shared ( )
|
||||
{
|
||||
return $(self.shared) ;
|
||||
}
|
||||
|
||||
rule real-name ( )
|
||||
{
|
||||
return $(self.real-name) ;
|
||||
}
|
||||
|
||||
rule search ( )
|
||||
{
|
||||
return $(self.search) ;
|
||||
}
|
||||
|
||||
rule actualize-location ( target )
|
||||
{
|
||||
NOTFILE $(target) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class searched-lib-target : abstract-file-target ;
|
||||
|
||||
|
||||
type.register LIB : : : main ;
|
||||
|
||||
# register the given type on the specified OSes, or on remaining OSes
|
||||
@@ -146,6 +192,8 @@ declare-type : STATIC_LIB : a : LIB : main ;
|
||||
declare-type NT : SHARED_LIB : dll : LIB : main ;
|
||||
declare-type : SHARED_LIB : so : LIB : main ;
|
||||
|
||||
declare-type : SEARCHED_LIB : : LIB : main ;
|
||||
|
||||
declare-type NT CYGWIN : EXE : exe : : main ;
|
||||
declare-type : EXE : : : main ;
|
||||
|
||||
@@ -238,11 +286,15 @@ rule lib-generator ( )
|
||||
{
|
||||
composing-generator.__init__ lib-generator : unknown-source-type : LIB : <main-target-type>LIB ;
|
||||
|
||||
rule run ( project name ? : properties * : sources + )
|
||||
rule run ( project name ? : properties * : sources * )
|
||||
{
|
||||
# Determine the needed target type
|
||||
local actual-type ;
|
||||
if <shared>true in $(properties)
|
||||
if <search> in $(properties:G) || <name> in $(properties:G)
|
||||
{
|
||||
actual-type = SEARCHED_LIB ;
|
||||
}
|
||||
else if <link>shared in $(properties)
|
||||
{
|
||||
actual-type = SHARED_LIB ;
|
||||
}
|
||||
@@ -261,6 +313,30 @@ class lib-generator : composing-generator ;
|
||||
|
||||
generators.register [ new lib-generator ] ;
|
||||
|
||||
rule searched-lib-generator ( )
|
||||
{
|
||||
generator.__init__ searched-lib-generator : : SEARCHED_LIB ;
|
||||
|
||||
rule run ( project name ? : properties * : sources * )
|
||||
{
|
||||
local shared ;
|
||||
if <link>shared in $(properties)
|
||||
{
|
||||
shared = true ;
|
||||
}
|
||||
return [ new searched-lib-target $(name) : $(project) : $(shared)
|
||||
: [ feature.get-values <name> : $(properties) ]
|
||||
: [ feature.get-values <search> : $(properties) ]
|
||||
] ;
|
||||
}
|
||||
}
|
||||
|
||||
class searched-lib-generator : generator ;
|
||||
|
||||
generators.register [ new searched-lib-generator ] ;
|
||||
|
||||
|
||||
|
||||
rule compile-action ( targets + : sources * : action-name : properties * )
|
||||
{
|
||||
action.__init__ $(targets) : $(sources) : $(action-name) : $(properties) ;
|
||||
@@ -305,6 +381,92 @@ rule register-c-compiler ( id : source-types + : target-types + :
|
||||
# register all generators as "generator.some-rule", not with "some-module.some-rule".)
|
||||
IMPORT $(__name__) : register-c-compiler : : generators.register-c-compiler ;
|
||||
|
||||
rule link-action ( targets + : sources * : action-name : properties * )
|
||||
{
|
||||
action.__init__ $(targets) : $(sources) : $(action-name) : $(properties) ;
|
||||
|
||||
rule adjust-properties ( properties * )
|
||||
{
|
||||
local extra ;
|
||||
for local s in $(self.sources)
|
||||
{
|
||||
if [ class.is-a $(s) : searched-lib-target ]
|
||||
{
|
||||
local name = [ $(s).real-name ] ;
|
||||
if [ $(s).shared ]
|
||||
{
|
||||
extra += <find-shared-library>$(name) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
extra += <find-static-library>$(name) ;
|
||||
}
|
||||
local search = [ $(s).search ] ;
|
||||
extra += <library-path>$(search) ;
|
||||
}
|
||||
# We also move orginary libs form sources to
|
||||
# "library" property. This allows us to
|
||||
# easily repeat all the list of libs on
|
||||
# command line, when it's needed.
|
||||
else if [ type.is-derived [ $(s).type ] LIB ]
|
||||
{
|
||||
extra += <library>$(s) ;
|
||||
}
|
||||
}
|
||||
ECHO "EXtra is " $(extra) ;
|
||||
return $(properties) $(extra) ;
|
||||
}
|
||||
|
||||
|
||||
rule actualize-sources ( sources * )
|
||||
{
|
||||
local real-sources ;
|
||||
for local s in $(sources)
|
||||
{
|
||||
if ! [ type.is-derived [ $(s).type ] LIB ]
|
||||
{
|
||||
real-sources += $(s) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.dependency-only-sources += [ $(s).actualize ] ;
|
||||
}
|
||||
}
|
||||
|
||||
action.actualize-sources $(real-sources) ;
|
||||
}
|
||||
}
|
||||
|
||||
class link-action : action ;
|
||||
|
||||
|
||||
rule linking-generator ( id : source-types + : target-types + :
|
||||
requirements * )
|
||||
{
|
||||
composing-generator.__init__ $(id) : $(source-types) : $(target-types) :
|
||||
$(requirements) ;
|
||||
|
||||
rule action-class ( )
|
||||
{
|
||||
return link-action ;
|
||||
}
|
||||
}
|
||||
|
||||
class linking-generator : composing-generator ;
|
||||
|
||||
|
||||
rule register-linker ( id : source-types + : target-types + :
|
||||
requirements * )
|
||||
{
|
||||
local g = [ new linking-generator $(id) : $(source-types)
|
||||
: $(target-types) : $(requirements) ] ;
|
||||
generators.register $(g) ;
|
||||
}
|
||||
|
||||
IMPORT $(__name__) : register-linker : : generators.register-linker ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user