mirror of
https://github.com/boostorg/build.git
synced 2026-02-12 12:02:24 +00:00
Forgotten file.
[SVN r15301]
This commit is contained in:
317
src/build/virtual-target.jam
Normal file
317
src/build/virtual-target.jam
Normal file
@@ -0,0 +1,317 @@
|
||||
# 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.
|
||||
|
||||
# Implements virtual targets, which correspond to actual files created during
|
||||
# build, but are not yet target in Jam sense. They are needed, for example,
|
||||
# when searching for possible transormation sequences, when it's not known
|
||||
# if particular target should be create at all.
|
||||
|
||||
import class : class new ;
|
||||
import type ;
|
||||
|
||||
# Class which represents a virtual target
|
||||
rule virtual-target ( name : type ? : project
|
||||
: subvariant * # Property sets which define this subvariant
|
||||
)
|
||||
{
|
||||
self.name = $(name) ;
|
||||
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) ; }
|
||||
|
||||
# Sets the suffix. When generating target name, it will be used in preference to
|
||||
# the suffix that is associated with 'type'
|
||||
rule suffix ( suffix )
|
||||
{
|
||||
self.suffix = $(suffix) ;
|
||||
}
|
||||
|
||||
# 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 + )
|
||||
{
|
||||
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.suffix)
|
||||
{
|
||||
self.actual-name = [ sequence.join <$(grist)>$(self.name)
|
||||
$(self.suffix) : "." ] ;
|
||||
}
|
||||
else if $(self.type)
|
||||
{
|
||||
self.actual-name = [ sequence.join <$(grist)>$(self.name)
|
||||
[ type.generated-target-suffix $(self.type) ] : "." ] ;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.actual-name = <$(grist)>$(self.name) ;
|
||||
}
|
||||
}
|
||||
return $(self.actual-name) ;
|
||||
}
|
||||
}
|
||||
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 ;
|
||||
|
||||
# Creates a virtual target with approariate name and type from 'file'.
|
||||
# If a target with that name in that project was already created, returns that already
|
||||
# created target.
|
||||
# FIXME: more correct way would be to compute path to the file, based on name and source location
|
||||
# for the project, and use that path to determine if the target was already created.
|
||||
# TODO: passing project with all virtual targets starts to be annoying.
|
||||
rule from-file ( file : project )
|
||||
{
|
||||
if $(.files.$(file).$(project))
|
||||
{
|
||||
return $(.files.$(file).$(project)) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
local name = $(file:S=) ;
|
||||
local type = [ type.type $(file:S) ] ;
|
||||
local result ;
|
||||
if ! $(type)
|
||||
{
|
||||
# warning "cannot determine type for file $(file)" ;
|
||||
result = [ new virtual-target $(file) : : $(project) ] ;
|
||||
}
|
||||
else
|
||||
{
|
||||
local v = [ new virtual-target $(name) : $(type) : $(project) ] ;
|
||||
$(v).suffix [ MATCH ^.(.*)$ : $(file:S) ] ;
|
||||
result = $(v) ;
|
||||
}
|
||||
.files.$(file).$(project) = $(result) ;
|
||||
return $(result) ;
|
||||
}
|
||||
}
|
||||
|
||||
# Registers a new virtual target. Checks if there's already registered target, with the same
|
||||
# name, type, project and subvariant properties, and also with the same sources
|
||||
# and equal action. If such target is found it is retured and 'target' is not registers.
|
||||
# Otherwise, 'target' is registered and returned.
|
||||
rule register ( target )
|
||||
{
|
||||
local signature = [ sequence.join
|
||||
[ $(target).project ] [ $(target).name ] [ $(target).type ] [ $(target).subvariant ] : - ] ;
|
||||
local result ;
|
||||
for local t in $(.cache.$(signature))
|
||||
{
|
||||
local a1 = [ $(t).action ] ;
|
||||
local a2 = [ $(target).action ] ;
|
||||
if ! $(result) && [ $(a1).action-name ] = [ $(a2).action-name ] && [ $(a1).properties ] = [ $(a2).properties ]
|
||||
&& [ $(a1).sources ] = [ $(a2).sources ]
|
||||
{
|
||||
result = $(t) ;
|
||||
}
|
||||
}
|
||||
if ! $(result)
|
||||
{
|
||||
.cache.$(signature) += $(target) ;
|
||||
result = $(target) ;
|
||||
}
|
||||
|
||||
return $(result) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user