mirror of
https://github.com/boostorg/build.git
synced 2026-02-20 14:42:14 +00:00
Attempt to handle derived target types
[SVN r16213]
This commit is contained in:
@@ -17,6 +17,7 @@ import os ;
|
||||
import stage ;
|
||||
import prebuilt ;
|
||||
import toolset ;
|
||||
import errors : error ;
|
||||
|
||||
feature toolset : gcc : implicit propagated link-incompatible ;
|
||||
feature shared : false true : propagated ;
|
||||
@@ -60,8 +61,7 @@ rule variant ( name : parents-or-properties * : tool-properties * )
|
||||
# between base variants.
|
||||
if $(parents[2])
|
||||
{
|
||||
print.wrapped-text "error: multiple base variants are not yet supported" ;
|
||||
EXIT ;
|
||||
error "multiple base variants are not yet supported" ;
|
||||
}
|
||||
|
||||
# Record explicitly specified properties for this variant
|
||||
@@ -107,26 +107,30 @@ variant release : <optimization>on <debug-symbols>off ;
|
||||
|
||||
type.register LIB : : : main ;
|
||||
|
||||
if [ os.name ] in NT CYGWIN
|
||||
# register the given type on the specified OSes, or on remaining OSes
|
||||
# if os is not specified.
|
||||
local rule declare-type ( os * : type : suffixes * : base-type ? : main ? )
|
||||
{
|
||||
type.register EXE : exe : : main ;
|
||||
type.register SHARED-LIB : dll : LIB : main ;
|
||||
|
||||
if [ os.name ] = CYGWIN
|
||||
if ! [ type.registered $(type) ]
|
||||
{
|
||||
type.register STATIC-LIB : a : LIB : main ;
|
||||
}
|
||||
else
|
||||
{
|
||||
type.register STATIC-LIB : lib : LIB : main ;
|
||||
if ( ! $(os) ) || [ os.name ] in $(os)
|
||||
{
|
||||
type.register $(type) : $(suffixes) : $(base-type) : $(main) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
type.register EXE : : : main ;
|
||||
type.register SHARED-LIB : so : LIB : main ;
|
||||
type.register STATIC-LIB : a : LIB : main ;
|
||||
}
|
||||
|
||||
declare-type NT : STATIC_LIB : a : LIB : main ;
|
||||
declare-type : STATIC_LIB : a : LIB : main ;
|
||||
|
||||
declare-type NT : SHARED_LIB : dll : LIB : main ;
|
||||
declare-type : SHARED_LIB : so : LIB : main ;
|
||||
|
||||
declare-type NT CYGWIN : EXE : exe : : main ;
|
||||
declare-type : EXE : : : main ;
|
||||
|
||||
declare-type NT CYGWIN : PYTHON_EXTENSION : dll : SHARED_LIB : main ;
|
||||
declare-type : PYTHON_EXTENSION : so : SHARED_LIB : main ;
|
||||
|
||||
type.register CPP : cpp cxx ;
|
||||
|
||||
@@ -209,18 +213,18 @@ type.register OBJ : o : : main ;
|
||||
|
||||
rule lib-generator ( )
|
||||
{
|
||||
composing-generator.__init__ lib-generator : unknown-source-type : LIB ;
|
||||
composing-generator.__init__ lib-generator : unknown-source-type : LIB : <main-target-type>LIB ;
|
||||
|
||||
rule run ( project name ? : properties * : sources + )
|
||||
{
|
||||
local actual-type ;
|
||||
if <shared>true in $(properties)
|
||||
{
|
||||
actual-type = SHARED-LIB ;
|
||||
actual-type = SHARED_LIB ;
|
||||
}
|
||||
else
|
||||
{
|
||||
actual-type = STATIC-LIB ;
|
||||
actual-type = STATIC_LIB ;
|
||||
}
|
||||
return [ generators.construct $(project) $(name) : $(actual-type) : $(properties)
|
||||
: $(sources) : allow-composing-generators ] ;
|
||||
|
||||
@@ -4,8 +4,8 @@ import generators ;
|
||||
import os ;
|
||||
|
||||
generators.register-composing 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-composing gcc.archive : OBJ : STATIC_LIB : <toolset>gcc ;
|
||||
generators.register-composing 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 ;
|
||||
|
||||
|
||||
@@ -124,6 +124,10 @@ rule generator (
|
||||
self.name-pre-post.$(m[1]) = $(m[3]) $(m[4]) ;
|
||||
}
|
||||
|
||||
self.optional-properties
|
||||
= [ feature.expand <base-target-type>$(self.target-types) ]
|
||||
;
|
||||
|
||||
rule id ( )
|
||||
{
|
||||
return $(self.id) ;
|
||||
@@ -154,6 +158,7 @@ rule generator (
|
||||
# TODO: comment is out of date.
|
||||
rule optional-properties ( )
|
||||
{
|
||||
return $(self.optional-properties) ;
|
||||
}
|
||||
|
||||
# Tries to invoke this generator on the given sources. Returns a
|
||||
@@ -558,24 +563,79 @@ local rule find-viable-generators ( target-type : properties * )
|
||||
# Select generators that can create the required target type.
|
||||
local viable-generators = ;
|
||||
local generator-rank = ;
|
||||
# TODO: rank generators by optional properties.
|
||||
for local g in $(.generators.$(target-type))
|
||||
|
||||
import type ;
|
||||
local t = [ type.all-bases $(target-type) ] ;
|
||||
|
||||
while $(t[1])
|
||||
{
|
||||
# Avoid trying the same generator twice on different levels.
|
||||
if ! $(g) in $(.active-generators)
|
||||
&& ! ( [ is-a $(g) : composing-generator ] && $(.had-composing-generator) )
|
||||
{
|
||||
if [ $(g).requirements ] in $(properties)
|
||||
{
|
||||
viable-generators += $(g) ;
|
||||
generator-rank += [ sequence.length [ set.intersection
|
||||
[ $(g).optional-properties ] : $(properties) ] ] ;
|
||||
for local g in $(.generators.$(t))
|
||||
{
|
||||
# Avoid trying the same generator twice on different levels.
|
||||
if ! $(g) in $(.active-generators)
|
||||
&& ! ( [ is-a $(g) : composing-generator ] && $(.had-composing-generator) )
|
||||
{
|
||||
if [ $(g).requirements ] in $(properties)
|
||||
{
|
||||
viable-generators += $(g) ;
|
||||
generator-rank += [ sequence.length [ set.intersection
|
||||
[ $(g).optional-properties ] : $(properties) ] ] ;
|
||||
t = ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
t = $(t[2-]) ;
|
||||
}
|
||||
|
||||
return [ sequence.select-highest-ranked $(viable-generators) : $(generator-rank) ] ;
|
||||
}
|
||||
|
||||
# currently unused. Sorry for the cruft. Delete at will
|
||||
local rule find-viable-generators.new ( target-type : properties * )
|
||||
{
|
||||
# Select generators that can create the required target type.
|
||||
local viable-generators = ;
|
||||
local generator-rank = ;
|
||||
|
||||
import type ;
|
||||
local t = [ type.all-bases $(target-type) ] ;
|
||||
|
||||
while $(t[1])
|
||||
{
|
||||
generators.dout [ indent ] " ...checking type" [ $(t[1]) ] ;
|
||||
|
||||
for local g in $(.generators.$(t[1]))
|
||||
{
|
||||
generators.dout [ indent ] " ...checking" [ $(g).id ] ;
|
||||
# Avoid trying the same generator twice on different levels.
|
||||
if ! $(g) in $(.active-generators)
|
||||
&& ! ( [ is-a $(g) : composing-generator ] && $(.had-composing-generator) )
|
||||
{
|
||||
local requirements = [ $(g).requirements ] ;
|
||||
generators.dout [ indent ] " ...requirements:" $(requirements) ;
|
||||
|
||||
if $(requirements) in $(properties)
|
||||
{
|
||||
local optional = [ $(g).optional-properties ] ;
|
||||
local match = $(requirements) [ set.intersection $(optional) : $(properties) ] ;
|
||||
|
||||
if $(match)
|
||||
{
|
||||
viable-generators += $(g) ;
|
||||
generator-rank += [ sequence.length $(match) ] ;
|
||||
generators.dout [ indent ] " ...matched" [ $(g).id ]
|
||||
"with rank $(generator-rank[-1]) :" $(match) ;
|
||||
t = ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
t = $(t[2-]) ;
|
||||
}
|
||||
|
||||
|
||||
return [ sequence.select-highest-ranked $(viable-generators) : $(generator-rank) ] ;
|
||||
}
|
||||
|
||||
# Given a vector of vectors, of of them represents results of running some
|
||||
# generator, returns the 'best' result, it it exists. Otherwise, exit with
|
||||
@@ -669,7 +729,7 @@ rule construct ( project name ? : target-type multiple ? : properties * : source
|
||||
generators.dout [ indent ] " from" [ $(s).str ] ;
|
||||
}
|
||||
generators.dout [ indent ] " properties:" $(properties) ;
|
||||
|
||||
|
||||
local .had-composing-generator = $(.had-composing-generator) ;
|
||||
if $(allow-composing-generators)
|
||||
{
|
||||
@@ -728,7 +788,7 @@ rule construct ( project name ? : target-type multiple ? : properties * : source
|
||||
local results = [ new vector ] ;
|
||||
|
||||
generators.dout [ indent ] "*** " [ sequence.length $(viable-generators) ]
|
||||
" viable generators " ;
|
||||
" viable generators" ;
|
||||
|
||||
for local g in $(viable-generators)
|
||||
{
|
||||
@@ -785,8 +845,8 @@ rule construct ( project name ? : target-type multiple ? : properties * : source
|
||||
}
|
||||
else
|
||||
{
|
||||
error [ $(results).size ] "possible generations for "
|
||||
$(target-types) "Can't handle this now." ;
|
||||
error [ $(results).size ] "possible generations for " $(target-types)
|
||||
: "generations:" [ $(results).str ] ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ import regex ;
|
||||
import property ;
|
||||
import errors ;
|
||||
import common ;
|
||||
import errors ;
|
||||
|
||||
|
||||
# Base class for all abstract targets.
|
||||
@@ -337,9 +336,7 @@ rule basic-target ( name : project
|
||||
|
||||
if $(sources:G)
|
||||
{
|
||||
print.wrapped-text "error: gristed element in sources for "
|
||||
[ full-name ] ;
|
||||
EXIT ;
|
||||
errors.error "gristed element in sources for" [ full-name ] ;
|
||||
}
|
||||
|
||||
|
||||
@@ -495,7 +492,6 @@ rule basic-target ( name : project
|
||||
{
|
||||
return $(self.requirements) ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class basic-target : abstract-target ;
|
||||
@@ -577,11 +573,13 @@ rule typed-target ( name : project : type
|
||||
rule construct ( source-targets * : properties * )
|
||||
{
|
||||
local r = [ generators.construct $(self.project) $(self.name) : $(self.type)
|
||||
: $(properties) <main-target-type>$(self.type) : $(source-targets) ] ;
|
||||
: $(properties) # [ feature.expand
|
||||
<main-target-type>$(self.type)
|
||||
# ]
|
||||
: $(source-targets) ] ;
|
||||
if ! $(r)
|
||||
{
|
||||
print.wrapped-text "error: unable to construct" [ full-name ] ;
|
||||
EXIT ;
|
||||
errors.error "unable to construct" [ full-name ] ;
|
||||
}
|
||||
|
||||
return $(r) ;
|
||||
|
||||
81
new/type.jam
81
new/type.jam
@@ -9,11 +9,14 @@
|
||||
import feature ;
|
||||
import generators : * ;
|
||||
import class : class new ;
|
||||
|
||||
import errors ;
|
||||
|
||||
feature.feature target-type : : composite optional ;
|
||||
feature.feature base-target-type : : composite optional ;
|
||||
|
||||
# feature.feature base-target-type : : composite optional ;
|
||||
feature.feature main-target-type : : optional incidental ;
|
||||
feature.feature base-target-type : : composite optional free ;
|
||||
# feature.feature main-target-type : : composite optional incidental ;
|
||||
|
||||
# Registers a target type, possible derived from a 'base-type'.
|
||||
# If 'suffixes' are provided, they given all the suffixes that mean a file is of 'type'.
|
||||
@@ -25,9 +28,17 @@ feature.feature main-target-type : : optional incidental ;
|
||||
# will be added to the global scope.
|
||||
rule register ( type : suffixes * : base-type ? : main ? )
|
||||
{
|
||||
# Type names cannot contain hyphens, because when used as
|
||||
# feature-values they will be interpreted as composite features
|
||||
# which need to be decomposed.
|
||||
switch $(type)
|
||||
{
|
||||
case *-* : errors.error "type name \"$(type)\" contains a hyphen" ;
|
||||
}
|
||||
|
||||
if $(type) in $(.types)
|
||||
{
|
||||
error "Type $(type) is already registered." ;
|
||||
errors.error "Type $(type) is already registered." ;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -36,16 +47,36 @@ rule register ( type : suffixes * : base-type ? : main ? )
|
||||
.suffix.$(type) = $(suffixes[1]) ;
|
||||
.type.$(suffixes) = $(type) ;
|
||||
feature.extend target-type : $(type) ;
|
||||
feature.compose <target-type>$(type) : $(base-type:G=<base-target-type>) ;
|
||||
feature.compose <base-target-type>$(type) : $(base-type:G=<base-target-type>) ;
|
||||
|
||||
feature.compose <target-type>$(type) : $(base-type:G=<base-target-type>) ;
|
||||
feature.extend base-target-type : $(type) ;
|
||||
# feature.compose <target-type>$(type) : <base-target-type>$(type) ;
|
||||
feature.compose <base-target-type>$(type) : <base-target-type>$(base-type) ;
|
||||
|
||||
if $(main)
|
||||
{
|
||||
IMPORT $(__name__) : main-target-rule : : $(type:L) ;
|
||||
{
|
||||
# Convert the type name to lowercase and convert all
|
||||
# underscores to hyphens to get the main target rule name.
|
||||
import regex ;
|
||||
local n = [ regex.split $(type:L) "_" ] ;
|
||||
n = $(n:J=-) ;
|
||||
.main-target-type.$(n) = $(type) ;
|
||||
|
||||
IMPORT $(__name__) : main-target-rule : : $(n) ;
|
||||
# feature.compose <main-target-type>$(type) : <base-target-type>$(type) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Returns true iff type has been registered.
|
||||
rule registered ( type )
|
||||
{
|
||||
if $(type) in $(.types)
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
# Sets a scanner class that will be used for this 'type'.
|
||||
rule set-scanner ( type : scanner )
|
||||
{
|
||||
@@ -64,30 +95,28 @@ rule get-scanner ( type : properties * )
|
||||
}
|
||||
}
|
||||
|
||||
# returns type and all of its bases in order of their distance from type.
|
||||
rule all-bases ( type )
|
||||
{
|
||||
local result = $(type) ;
|
||||
while $(type)
|
||||
{
|
||||
type = $(.bases.$(type)) ;
|
||||
result += $(type) ;
|
||||
}
|
||||
return $(result) ;
|
||||
}
|
||||
|
||||
# Returns true if 'type' has 'base' as its direct or
|
||||
# indirect base.
|
||||
rule is-derived ( type base )
|
||||
{
|
||||
if $(base) in $(.bases.$(type))
|
||||
if $(base) in [ all-bases $(type) ]
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
else
|
||||
{
|
||||
# CONSIDER: maybe break when 'found' is true
|
||||
local found ;
|
||||
for local e in $(.bases.$(type))
|
||||
{
|
||||
if [ is-derived $(e) $(base) ]
|
||||
{
|
||||
found = true ;
|
||||
}
|
||||
}
|
||||
return $(found) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns suffix that should be used when generating target of 'type'.
|
||||
rule generated-target-suffix ( type )
|
||||
{
|
||||
@@ -105,13 +134,13 @@ rule type ( suffix )
|
||||
rule main-target-rule ( name : sources * : requirements * : default-build *
|
||||
: use-requirements * )
|
||||
{
|
||||
# First find requuired target type, which is equal to the name used to
|
||||
# invoke us.
|
||||
# First find required target type, which is equal to the name used
|
||||
# to invoke us.
|
||||
local bt = [ BACKTRACE 1 ] ;
|
||||
local type = $(bt[4]) ;
|
||||
local rulename = $(bt[4]) ;
|
||||
|
||||
targets.main-target-alternative $(name) [ CALLER_MODULE ] typed-target : 3 : 5 : 4
|
||||
: $(type:U) : $(sources) : $(requirements) : $(default-build) : $(use-requirements)
|
||||
: $(.main-target-type.$(rulename)) : $(sources) : $(requirements) : $(default-build) : $(use-requirements)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -124,6 +124,10 @@ rule generator (
|
||||
self.name-pre-post.$(m[1]) = $(m[3]) $(m[4]) ;
|
||||
}
|
||||
|
||||
self.optional-properties
|
||||
= [ feature.expand <base-target-type>$(self.target-types) ]
|
||||
;
|
||||
|
||||
rule id ( )
|
||||
{
|
||||
return $(self.id) ;
|
||||
@@ -154,6 +158,7 @@ rule generator (
|
||||
# TODO: comment is out of date.
|
||||
rule optional-properties ( )
|
||||
{
|
||||
return $(self.optional-properties) ;
|
||||
}
|
||||
|
||||
# Tries to invoke this generator on the given sources. Returns a
|
||||
@@ -558,24 +563,79 @@ local rule find-viable-generators ( target-type : properties * )
|
||||
# Select generators that can create the required target type.
|
||||
local viable-generators = ;
|
||||
local generator-rank = ;
|
||||
# TODO: rank generators by optional properties.
|
||||
for local g in $(.generators.$(target-type))
|
||||
|
||||
import type ;
|
||||
local t = [ type.all-bases $(target-type) ] ;
|
||||
|
||||
while $(t[1])
|
||||
{
|
||||
# Avoid trying the same generator twice on different levels.
|
||||
if ! $(g) in $(.active-generators)
|
||||
&& ! ( [ is-a $(g) : composing-generator ] && $(.had-composing-generator) )
|
||||
{
|
||||
if [ $(g).requirements ] in $(properties)
|
||||
{
|
||||
viable-generators += $(g) ;
|
||||
generator-rank += [ sequence.length [ set.intersection
|
||||
[ $(g).optional-properties ] : $(properties) ] ] ;
|
||||
for local g in $(.generators.$(t))
|
||||
{
|
||||
# Avoid trying the same generator twice on different levels.
|
||||
if ! $(g) in $(.active-generators)
|
||||
&& ! ( [ is-a $(g) : composing-generator ] && $(.had-composing-generator) )
|
||||
{
|
||||
if [ $(g).requirements ] in $(properties)
|
||||
{
|
||||
viable-generators += $(g) ;
|
||||
generator-rank += [ sequence.length [ set.intersection
|
||||
[ $(g).optional-properties ] : $(properties) ] ] ;
|
||||
t = ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
t = $(t[2-]) ;
|
||||
}
|
||||
|
||||
return [ sequence.select-highest-ranked $(viable-generators) : $(generator-rank) ] ;
|
||||
}
|
||||
|
||||
# currently unused. Sorry for the cruft. Delete at will
|
||||
local rule find-viable-generators.new ( target-type : properties * )
|
||||
{
|
||||
# Select generators that can create the required target type.
|
||||
local viable-generators = ;
|
||||
local generator-rank = ;
|
||||
|
||||
import type ;
|
||||
local t = [ type.all-bases $(target-type) ] ;
|
||||
|
||||
while $(t[1])
|
||||
{
|
||||
generators.dout [ indent ] " ...checking type" [ $(t[1]) ] ;
|
||||
|
||||
for local g in $(.generators.$(t[1]))
|
||||
{
|
||||
generators.dout [ indent ] " ...checking" [ $(g).id ] ;
|
||||
# Avoid trying the same generator twice on different levels.
|
||||
if ! $(g) in $(.active-generators)
|
||||
&& ! ( [ is-a $(g) : composing-generator ] && $(.had-composing-generator) )
|
||||
{
|
||||
local requirements = [ $(g).requirements ] ;
|
||||
generators.dout [ indent ] " ...requirements:" $(requirements) ;
|
||||
|
||||
if $(requirements) in $(properties)
|
||||
{
|
||||
local optional = [ $(g).optional-properties ] ;
|
||||
local match = $(requirements) [ set.intersection $(optional) : $(properties) ] ;
|
||||
|
||||
if $(match)
|
||||
{
|
||||
viable-generators += $(g) ;
|
||||
generator-rank += [ sequence.length $(match) ] ;
|
||||
generators.dout [ indent ] " ...matched" [ $(g).id ]
|
||||
"with rank $(generator-rank[-1]) :" $(match) ;
|
||||
t = ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
t = $(t[2-]) ;
|
||||
}
|
||||
|
||||
|
||||
return [ sequence.select-highest-ranked $(viable-generators) : $(generator-rank) ] ;
|
||||
}
|
||||
|
||||
# Given a vector of vectors, of of them represents results of running some
|
||||
# generator, returns the 'best' result, it it exists. Otherwise, exit with
|
||||
@@ -669,7 +729,7 @@ rule construct ( project name ? : target-type multiple ? : properties * : source
|
||||
generators.dout [ indent ] " from" [ $(s).str ] ;
|
||||
}
|
||||
generators.dout [ indent ] " properties:" $(properties) ;
|
||||
|
||||
|
||||
local .had-composing-generator = $(.had-composing-generator) ;
|
||||
if $(allow-composing-generators)
|
||||
{
|
||||
@@ -728,7 +788,7 @@ rule construct ( project name ? : target-type multiple ? : properties * : source
|
||||
local results = [ new vector ] ;
|
||||
|
||||
generators.dout [ indent ] "*** " [ sequence.length $(viable-generators) ]
|
||||
" viable generators " ;
|
||||
" viable generators" ;
|
||||
|
||||
for local g in $(viable-generators)
|
||||
{
|
||||
@@ -785,8 +845,8 @@ rule construct ( project name ? : target-type multiple ? : properties * : source
|
||||
}
|
||||
else
|
||||
{
|
||||
error [ $(results).size ] "possible generations for "
|
||||
$(target-types) "Can't handle this now." ;
|
||||
error [ $(results).size ] "possible generations for " $(target-types)
|
||||
: "generations:" [ $(results).str ] ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ import regex ;
|
||||
import property ;
|
||||
import errors ;
|
||||
import common ;
|
||||
import errors ;
|
||||
|
||||
|
||||
# Base class for all abstract targets.
|
||||
@@ -337,9 +336,7 @@ rule basic-target ( name : project
|
||||
|
||||
if $(sources:G)
|
||||
{
|
||||
print.wrapped-text "error: gristed element in sources for "
|
||||
[ full-name ] ;
|
||||
EXIT ;
|
||||
errors.error "gristed element in sources for" [ full-name ] ;
|
||||
}
|
||||
|
||||
|
||||
@@ -495,7 +492,6 @@ rule basic-target ( name : project
|
||||
{
|
||||
return $(self.requirements) ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class basic-target : abstract-target ;
|
||||
@@ -577,11 +573,13 @@ rule typed-target ( name : project : type
|
||||
rule construct ( source-targets * : properties * )
|
||||
{
|
||||
local r = [ generators.construct $(self.project) $(self.name) : $(self.type)
|
||||
: $(properties) <main-target-type>$(self.type) : $(source-targets) ] ;
|
||||
: $(properties) # [ feature.expand
|
||||
<main-target-type>$(self.type)
|
||||
# ]
|
||||
: $(source-targets) ] ;
|
||||
if ! $(r)
|
||||
{
|
||||
print.wrapped-text "error: unable to construct" [ full-name ] ;
|
||||
EXIT ;
|
||||
errors.error "unable to construct" [ full-name ] ;
|
||||
}
|
||||
|
||||
return $(r) ;
|
||||
|
||||
@@ -9,11 +9,14 @@
|
||||
import feature ;
|
||||
import generators : * ;
|
||||
import class : class new ;
|
||||
|
||||
import errors ;
|
||||
|
||||
feature.feature target-type : : composite optional ;
|
||||
feature.feature base-target-type : : composite optional ;
|
||||
|
||||
# feature.feature base-target-type : : composite optional ;
|
||||
feature.feature main-target-type : : optional incidental ;
|
||||
feature.feature base-target-type : : composite optional free ;
|
||||
# feature.feature main-target-type : : composite optional incidental ;
|
||||
|
||||
# Registers a target type, possible derived from a 'base-type'.
|
||||
# If 'suffixes' are provided, they given all the suffixes that mean a file is of 'type'.
|
||||
@@ -25,9 +28,17 @@ feature.feature main-target-type : : optional incidental ;
|
||||
# will be added to the global scope.
|
||||
rule register ( type : suffixes * : base-type ? : main ? )
|
||||
{
|
||||
# Type names cannot contain hyphens, because when used as
|
||||
# feature-values they will be interpreted as composite features
|
||||
# which need to be decomposed.
|
||||
switch $(type)
|
||||
{
|
||||
case *-* : errors.error "type name \"$(type)\" contains a hyphen" ;
|
||||
}
|
||||
|
||||
if $(type) in $(.types)
|
||||
{
|
||||
error "Type $(type) is already registered." ;
|
||||
errors.error "Type $(type) is already registered." ;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -36,16 +47,36 @@ rule register ( type : suffixes * : base-type ? : main ? )
|
||||
.suffix.$(type) = $(suffixes[1]) ;
|
||||
.type.$(suffixes) = $(type) ;
|
||||
feature.extend target-type : $(type) ;
|
||||
feature.compose <target-type>$(type) : $(base-type:G=<base-target-type>) ;
|
||||
feature.compose <base-target-type>$(type) : $(base-type:G=<base-target-type>) ;
|
||||
|
||||
feature.compose <target-type>$(type) : $(base-type:G=<base-target-type>) ;
|
||||
feature.extend base-target-type : $(type) ;
|
||||
# feature.compose <target-type>$(type) : <base-target-type>$(type) ;
|
||||
feature.compose <base-target-type>$(type) : <base-target-type>$(base-type) ;
|
||||
|
||||
if $(main)
|
||||
{
|
||||
IMPORT $(__name__) : main-target-rule : : $(type:L) ;
|
||||
{
|
||||
# Convert the type name to lowercase and convert all
|
||||
# underscores to hyphens to get the main target rule name.
|
||||
import regex ;
|
||||
local n = [ regex.split $(type:L) "_" ] ;
|
||||
n = $(n:J=-) ;
|
||||
.main-target-type.$(n) = $(type) ;
|
||||
|
||||
IMPORT $(__name__) : main-target-rule : : $(n) ;
|
||||
# feature.compose <main-target-type>$(type) : <base-target-type>$(type) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Returns true iff type has been registered.
|
||||
rule registered ( type )
|
||||
{
|
||||
if $(type) in $(.types)
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
# Sets a scanner class that will be used for this 'type'.
|
||||
rule set-scanner ( type : scanner )
|
||||
{
|
||||
@@ -64,30 +95,28 @@ rule get-scanner ( type : properties * )
|
||||
}
|
||||
}
|
||||
|
||||
# returns type and all of its bases in order of their distance from type.
|
||||
rule all-bases ( type )
|
||||
{
|
||||
local result = $(type) ;
|
||||
while $(type)
|
||||
{
|
||||
type = $(.bases.$(type)) ;
|
||||
result += $(type) ;
|
||||
}
|
||||
return $(result) ;
|
||||
}
|
||||
|
||||
# Returns true if 'type' has 'base' as its direct or
|
||||
# indirect base.
|
||||
rule is-derived ( type base )
|
||||
{
|
||||
if $(base) in $(.bases.$(type))
|
||||
if $(base) in [ all-bases $(type) ]
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
else
|
||||
{
|
||||
# CONSIDER: maybe break when 'found' is true
|
||||
local found ;
|
||||
for local e in $(.bases.$(type))
|
||||
{
|
||||
if [ is-derived $(e) $(base) ]
|
||||
{
|
||||
found = true ;
|
||||
}
|
||||
}
|
||||
return $(found) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns suffix that should be used when generating target of 'type'.
|
||||
rule generated-target-suffix ( type )
|
||||
{
|
||||
@@ -105,13 +134,13 @@ rule type ( suffix )
|
||||
rule main-target-rule ( name : sources * : requirements * : default-build *
|
||||
: use-requirements * )
|
||||
{
|
||||
# First find requuired target type, which is equal to the name used to
|
||||
# invoke us.
|
||||
# First find required target type, which is equal to the name used
|
||||
# to invoke us.
|
||||
local bt = [ BACKTRACE 1 ] ;
|
||||
local type = $(bt[4]) ;
|
||||
local rulename = $(bt[4]) ;
|
||||
|
||||
targets.main-target-alternative $(name) [ CALLER_MODULE ] typed-target : 3 : 5 : 4
|
||||
: $(type:U) : $(sources) : $(requirements) : $(default-build) : $(use-requirements)
|
||||
: $(.main-target-type.$(rulename)) : $(sources) : $(requirements) : $(default-build) : $(use-requirements)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ import generators ;
|
||||
import os ;
|
||||
|
||||
generators.register-composing 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-composing gcc.archive : OBJ : STATIC_LIB : <toolset>gcc ;
|
||||
generators.register-composing 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 ;
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import os ;
|
||||
import stage ;
|
||||
import prebuilt ;
|
||||
import toolset ;
|
||||
import errors : error ;
|
||||
|
||||
feature toolset : gcc : implicit propagated link-incompatible ;
|
||||
feature shared : false true : propagated ;
|
||||
@@ -60,8 +61,7 @@ rule variant ( name : parents-or-properties * : tool-properties * )
|
||||
# between base variants.
|
||||
if $(parents[2])
|
||||
{
|
||||
print.wrapped-text "error: multiple base variants are not yet supported" ;
|
||||
EXIT ;
|
||||
error "multiple base variants are not yet supported" ;
|
||||
}
|
||||
|
||||
# Record explicitly specified properties for this variant
|
||||
@@ -107,26 +107,30 @@ variant release : <optimization>on <debug-symbols>off ;
|
||||
|
||||
type.register LIB : : : main ;
|
||||
|
||||
if [ os.name ] in NT CYGWIN
|
||||
# register the given type on the specified OSes, or on remaining OSes
|
||||
# if os is not specified.
|
||||
local rule declare-type ( os * : type : suffixes * : base-type ? : main ? )
|
||||
{
|
||||
type.register EXE : exe : : main ;
|
||||
type.register SHARED-LIB : dll : LIB : main ;
|
||||
|
||||
if [ os.name ] = CYGWIN
|
||||
if ! [ type.registered $(type) ]
|
||||
{
|
||||
type.register STATIC-LIB : a : LIB : main ;
|
||||
}
|
||||
else
|
||||
{
|
||||
type.register STATIC-LIB : lib : LIB : main ;
|
||||
if ( ! $(os) ) || [ os.name ] in $(os)
|
||||
{
|
||||
type.register $(type) : $(suffixes) : $(base-type) : $(main) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
type.register EXE : : : main ;
|
||||
type.register SHARED-LIB : so : LIB : main ;
|
||||
type.register STATIC-LIB : a : LIB : main ;
|
||||
}
|
||||
|
||||
declare-type NT : STATIC_LIB : a : LIB : main ;
|
||||
declare-type : STATIC_LIB : a : LIB : main ;
|
||||
|
||||
declare-type NT : SHARED_LIB : dll : LIB : main ;
|
||||
declare-type : SHARED_LIB : so : LIB : main ;
|
||||
|
||||
declare-type NT CYGWIN : EXE : exe : : main ;
|
||||
declare-type : EXE : : : main ;
|
||||
|
||||
declare-type NT CYGWIN : PYTHON_EXTENSION : dll : SHARED_LIB : main ;
|
||||
declare-type : PYTHON_EXTENSION : so : SHARED_LIB : main ;
|
||||
|
||||
type.register CPP : cpp cxx ;
|
||||
|
||||
@@ -209,18 +213,18 @@ type.register OBJ : o : : main ;
|
||||
|
||||
rule lib-generator ( )
|
||||
{
|
||||
composing-generator.__init__ lib-generator : unknown-source-type : LIB ;
|
||||
composing-generator.__init__ lib-generator : unknown-source-type : LIB : <main-target-type>LIB ;
|
||||
|
||||
rule run ( project name ? : properties * : sources + )
|
||||
{
|
||||
local actual-type ;
|
||||
if <shared>true in $(properties)
|
||||
{
|
||||
actual-type = SHARED-LIB ;
|
||||
actual-type = SHARED_LIB ;
|
||||
}
|
||||
else
|
||||
{
|
||||
actual-type = STATIC-LIB ;
|
||||
actual-type = STATIC_LIB ;
|
||||
}
|
||||
return [ generators.construct $(project) $(name) : $(actual-type) : $(properties)
|
||||
: $(sources) : allow-composing-generators ] ;
|
||||
|
||||
Reference in New Issue
Block a user