mirror of
https://github.com/boostorg/build.git
synced 2026-02-13 00:12:11 +00:00
Some cleanups. At the same time, allowed several suffixes to target types
(e.g. "cpp" and "cxx"). [SVN r15262]
This commit is contained in:
@@ -4,12 +4,7 @@
|
||||
# warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
|
||||
# There are three kinds of targets: "abstract", which correspond to
|
||||
# targets explicitly defined in Jamfile; "virtual", which correspond
|
||||
# to possible build product with defined properties and "actual", which
|
||||
# are targets in Jam sense. The "virtual" targets are generated during
|
||||
# search for the best transformation sequence, and some of them can be
|
||||
# later 'actualized'.
|
||||
# Supports 'abstact' targets, which are targets explicitly defined in Jamfile.
|
||||
#
|
||||
# Abstract targets are represented by classes derived from 'abstract-target' class.
|
||||
# The first abstract target is 'project-target', which is created for each
|
||||
@@ -252,6 +247,7 @@ rule basic-target ( name : project
|
||||
: sources * : requirements * : default-build * )
|
||||
{
|
||||
import build-request ;
|
||||
import virtual-target ;
|
||||
|
||||
abstract-target.__init__ $(name) : $(project) ;
|
||||
|
||||
@@ -309,9 +305,7 @@ rule basic-target ( name : project
|
||||
else
|
||||
{
|
||||
# Just a source file
|
||||
# FIXME: break an import cycle in a rude way
|
||||
import type ;
|
||||
source-targets += [ type.from-file $(s) : $(self.project) ] ;
|
||||
source-targets += [ virtual-target.from-file $(s) : $(self.project) ] ;
|
||||
}
|
||||
}
|
||||
self.generated.$(property-path) =
|
||||
@@ -426,231 +420,22 @@ rule main-target-alternative ( target-name project class-name
|
||||
: $(a4) : $(a5) : $(a6) : $(a7) : $(a8) : $(a9) ] ;
|
||||
}
|
||||
|
||||
# Class which represents a virtual target
|
||||
rule virtual-target ( name : type ? : project
|
||||
: subvariant * # Property sets which define this subvariant
|
||||
)
|
||||
|
||||
rule typed-target ( name : project : type
|
||||
: sources * : requirements * : default-build * )
|
||||
{
|
||||
self.name = $(name) ;
|
||||
ECHO "Typed target: type is " $(type) ;
|
||||
basic-target.__init__ $(name) : $(project)
|
||||
: $(sources) : $(requirements) : $(defailt-build) ;
|
||||
|
||||
self.type = $(type) ;
|
||||
self.subvariant = $(subvariant) ;
|
||||
self.project = $(project) ;
|
||||
|
||||
self.includes = ;
|
||||
self.dependencies = ;
|
||||
self.action = ;
|
||||
|
||||
self.actual-name = ;
|
||||
|
||||
|
||||
# Name of the target
|
||||
rule name ( ) { return $(self.name) ; }
|
||||
|
||||
rule type ( ) { return $(self.type) ; }
|
||||
|
||||
|
||||
# Property set that distinguished different variants of a target.
|
||||
# May be a subset of the property set that is used for building.
|
||||
# Determines the location of target, in an unspecified way.
|
||||
rule subvariant ( ) { return $(self.subvariant) ; }
|
||||
|
||||
# Project where this target was declared
|
||||
rule project ( ) { return $(self.project) ; }
|
||||
|
||||
rule includes ( ) { return $(self.includes) ; }
|
||||
rule add_includes ( i + )
|
||||
rule construct ( source-targets * : properties * )
|
||||
{
|
||||
self.includes = [ sequence.merge $(self.includes)
|
||||
: [ sequence.insertion-sort $(i) ] ] ;
|
||||
}
|
||||
|
||||
rule dependencies ( ) { return $(self.dependencies) ; }
|
||||
rule depends ( d + )
|
||||
{
|
||||
self.dependencies = [ sequence.merge $(self.dependencies)
|
||||
: [ sequence.insertion-sort $(d) ] ] ;
|
||||
}
|
||||
|
||||
# If 'a' is supplied, sets action to 'a'.
|
||||
# Returns the action currently set.
|
||||
rule action ( a ? )
|
||||
{
|
||||
if $(a) {
|
||||
self.action = $(a) ;
|
||||
}
|
||||
return $(self.action) ;
|
||||
}
|
||||
|
||||
# Specified an extra element to be added to the target path.
|
||||
rule extra-path ( p )
|
||||
{
|
||||
self.extra-path = $(p) ;
|
||||
}
|
||||
|
||||
# Generates all the actual targets and build instructions needed to build
|
||||
# this target. Returns the actual target name. Can be called several times.
|
||||
# Does no processing for other targets that 'action' will generate.
|
||||
# Rationale: we might need only one file from the set created by an
|
||||
# action, and there's no need to run the action if the file is up-to-date,
|
||||
# only because some other file in set is out-of-date.
|
||||
rule actualize ( )
|
||||
{
|
||||
if ! $(self.actual-name) {
|
||||
|
||||
self.actual-name = [ actual-name ] ;
|
||||
for local i in $(dependencies) {
|
||||
DEPENDS $(name) : [ $(i).actualize ] ;
|
||||
}
|
||||
for local i in $(includes) {
|
||||
INCLUDES $(name) : [ $(i).actualize ] ;
|
||||
}
|
||||
local a = [ action ] ;
|
||||
if $(a) {
|
||||
$(a).actualize ;
|
||||
local path = [ path.join [ project.attribute $(self.project) location ]
|
||||
"bin" [ property.as-path [ subvariant ] ]
|
||||
$(self.extra-path) ] ;
|
||||
path = [ path.native $(path) ] ;
|
||||
LOCATE on $(self.actual-name) = $(path) ;
|
||||
DEPENDS $(self.actual-name) : $(path) ;
|
||||
common.MkDir $(path) ;
|
||||
common.Clean clean : $(self.actual-name) ;
|
||||
} else {
|
||||
SEARCH on $(self.actual-name) =
|
||||
[ path.native [ project.attribute $(self.project) source-location ] ] ;
|
||||
}
|
||||
}
|
||||
return $(self.actual-name) ;
|
||||
}
|
||||
|
||||
rule str ( )
|
||||
{
|
||||
local action = [ action ] ;
|
||||
local filename = [ sequence.join $(self.name) "." $(self.type) ] ;
|
||||
if $(action)
|
||||
{
|
||||
local sources = [ $(action).sources ] ;
|
||||
|
||||
local ss ;
|
||||
for local s in $(sources)
|
||||
{
|
||||
ss += [ $(s).str ] ;
|
||||
}
|
||||
|
||||
local name = [ $(action).action_name ] ;
|
||||
return "{" $(name)-$(filename) $(ss) "}" ;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "{" $(filename) "}" ;
|
||||
}
|
||||
}
|
||||
|
||||
rule less ( a )
|
||||
{
|
||||
if [ str ] < [ $(a).str ]
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
rule equal ( a )
|
||||
{
|
||||
if [ str ] = [ $(a).str ]
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
# private:
|
||||
rule actual-name ( )
|
||||
{
|
||||
if ! $(self.actual-name)
|
||||
{
|
||||
local project-location = [ project.attribute $(self.project) location ] ;
|
||||
local location-grist =
|
||||
[ sequence.join [ regex.split $(project-location) "/" ] : "!" ] ;
|
||||
local property-grist =
|
||||
[ property.as-path $(self.subvariant) ] ;
|
||||
# Set empty value to avoid eating adjacent text
|
||||
local grist = $(location-grist)/$(property-grist) ;
|
||||
if ! $(self.subvariant) {
|
||||
grist = $(location-grist) ;
|
||||
}
|
||||
if $(self.type)
|
||||
{
|
||||
self.actual-name = [ sequence.join <$(grist)>$(self.name) [ type.suffix $(self.type) ] : "." ] ;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.actual-name = <$(grist)>$(self.name) ;
|
||||
}
|
||||
}
|
||||
return $(self.actual-name) ;
|
||||
}
|
||||
local r = [ generators.construct-dbg $(self.project) $(self.name) : $(self.type)
|
||||
: $(properties) <main-target-type>$(self.type) : $(source-targets) ] ;
|
||||
return [ $(r).get-at 1 ] [ $(r).get-at 2 ] ;
|
||||
}
|
||||
}
|
||||
class virtual-target ;
|
||||
|
||||
# Class which represents an action.
|
||||
# Both 'targets' and 'sources' should list instances of 'virtual-target'.
|
||||
# Action name should name a rule with this prototype
|
||||
# rule action_name ( targets + : sources * : properties * )
|
||||
# Targets and sources are passed as actual jam targets. The rule may
|
||||
# not establish dependency relationship, but should do everything else.
|
||||
rule action ( targets + : sources * : action_name : properties * )
|
||||
{
|
||||
self.targets = $(targets) ;
|
||||
self.sources = $(sources) ;
|
||||
self.action_name = $(action_name) ;
|
||||
self.properties = $(properties) ;
|
||||
|
||||
rule targets ( )
|
||||
{
|
||||
return $(self.targets) ;
|
||||
}
|
||||
|
||||
rule sources ( )
|
||||
{
|
||||
return $(self.sources) ;
|
||||
}
|
||||
|
||||
rule action_name ( )
|
||||
{
|
||||
return $(self.action_name) ;
|
||||
}
|
||||
|
||||
rule properties ( )
|
||||
{
|
||||
return $(self.properties) ;
|
||||
}
|
||||
|
||||
# Generates actual build instructions.
|
||||
rule actualize ( )
|
||||
{
|
||||
if ! $(self.actualized)
|
||||
{
|
||||
self.actualized = true ;
|
||||
|
||||
local actual_targets ;
|
||||
for local i in [ targets ]
|
||||
{
|
||||
actual_targets += [ $(i).actualize ] ;
|
||||
}
|
||||
|
||||
local actual_sources ;
|
||||
for local i in [ sources ]
|
||||
{
|
||||
actual_sources += [ $(i).actualize ] ;
|
||||
}
|
||||
|
||||
DEPENDS $(actual_targets) : $(actual_sources) ;
|
||||
|
||||
$(self.action_name)
|
||||
$(actual_targets) : $(actual_sources) : [ properties ] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
class action ;
|
||||
|
||||
|
||||
|
||||
|
||||
class typed-target : basic-target ;
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
# typed targets.
|
||||
|
||||
import feature ;
|
||||
import targets ;
|
||||
import generators : * ;
|
||||
import class : class new ;
|
||||
|
||||
@@ -17,12 +16,14 @@ feature.feature base-target-type : : composite optional ;
|
||||
feature.feature main-target-type : : optional incidental ;
|
||||
|
||||
# Registers a target type, possible derived from a 'base-type'.
|
||||
# If 'suffix' is provided, it is associated with this target type.
|
||||
# If 'suffixes' are provided, they given all the suffixes that mean a file is of 'type'.
|
||||
# Also, the first element gives the suffix to be used when constructing and object of
|
||||
# 'type'.
|
||||
# If 'main' is given, a rule with the same name as the target type
|
||||
# and signature
|
||||
# rule target-type ( name : sources * : requirements * : default-build )
|
||||
# will be added to the global scope.
|
||||
rule register ( type : suffix ? : base-type ? : main ? )
|
||||
rule register ( type : suffixes * : base-type ? : main ? )
|
||||
{
|
||||
if $(type) in $(.types)
|
||||
{
|
||||
@@ -31,8 +32,8 @@ rule register ( type : suffix ? : base-type ? : main ? )
|
||||
else
|
||||
{
|
||||
.types += $(type) ;
|
||||
.suffix.$(type) = $(suffix) ;
|
||||
.type.$(suffix) = $(type) ;
|
||||
.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>) ;
|
||||
@@ -44,49 +45,19 @@ rule register ( type : suffix ? : base-type ? : main ? )
|
||||
}
|
||||
}
|
||||
|
||||
# Returns suffix to the 'type'.
|
||||
rule suffix ( type )
|
||||
# Returns suffix that should be used when generating target of 'type'.
|
||||
rule generated-target-suffix ( type )
|
||||
{
|
||||
return $(.suffix.$(type)) ;
|
||||
}
|
||||
|
||||
# Creates a virtual target with approariate name and type from 'file'.
|
||||
# TODO: passing project with all virtual targets starts to be annoying.
|
||||
rule from-file ( file : project )
|
||||
# Returns file type given its suffix.
|
||||
rule type ( suffix )
|
||||
{
|
||||
local name = $(file:S=) ;
|
||||
local type = $(.type$(file:S)) ;
|
||||
if ! $(type)
|
||||
{
|
||||
# warning "cannot determine type for file $(file)" ;
|
||||
return [ new virtual-target $(file) : : $(project) ] ;
|
||||
}
|
||||
else
|
||||
{
|
||||
return [ new virtual-target $(name) : $(type) : $(project) ] ;
|
||||
}
|
||||
return $(.type$(suffix)) ;
|
||||
}
|
||||
|
||||
|
||||
rule typed-target ( name : project : type
|
||||
: sources * : requirements * : default-build * )
|
||||
{
|
||||
ECHO "Typed target: type is " $(type) ;
|
||||
basic-target.__init__ $(name) : $(project)
|
||||
: $(sources) : $(requirements) : $(defailt-build) ;
|
||||
|
||||
self.type = $(type) ;
|
||||
|
||||
rule construct ( source-targets * : properties * )
|
||||
{
|
||||
local r = [ generators.construct-dbg $(self.project) $(self.name) : $(self.type)
|
||||
: $(properties) <main-target-type>$(self.type) : $(source-targets) ] ;
|
||||
return [ $(r).get-at 1 ] [ $(r).get-at 2 ] ;
|
||||
}
|
||||
}
|
||||
|
||||
class typed-target : basic-target ;
|
||||
|
||||
rule main-target-rule ( name : sources * : requirements * : default-build ? )
|
||||
{
|
||||
# First find requuired target type, which is equal to the name used to
|
||||
@@ -99,13 +70,3 @@ rule main-target-rule ( name : sources * : requirements * : default-build ? )
|
||||
;
|
||||
}
|
||||
|
||||
rule construct-dbg-x ( target-types + : properties * : source-files + )
|
||||
{
|
||||
local sources ;
|
||||
for local s in $(source-files)
|
||||
{
|
||||
sources += [ from-file $(s) : "some project" ] ;
|
||||
}
|
||||
return [ construct-dbg "result" : $(target-types) : $(properties) :
|
||||
$(sources) ] ;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
exe a : a.cpp b.cpp c.ui d.wd x.l y.x_pro lib/aux ;
|
||||
exe a : a.cpp b.cxx c.ui d.wd x.l y.x_pro lib/aux ;
|
||||
#exe a : a.cpp b.cpp c.ui d.wd x.l y.x_pro ;
|
||||
|
||||
nm_exe e : e.cpp ;
|
||||
|
||||
@@ -10,7 +10,7 @@ import type ;
|
||||
|
||||
type.register EXE : : : main ;
|
||||
type.register LIB : : : main ;
|
||||
type.register CPP : cpp ;
|
||||
type.register CPP : cpp cxx ;
|
||||
type.register C : c ;
|
||||
type.register OBJ : o ;
|
||||
type.register LEX : l ;
|
||||
|
||||
Reference in New Issue
Block a user