mirror of
https://github.com/boostorg/build.git
synced 2026-02-16 01:12:13 +00:00
224 lines
8.2 KiB
Plaintext
224 lines
8.2 KiB
Plaintext
# Copyright (C) 2003, Rene Rivera. 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.
|
|
|
|
# Modifiers are generalized generators that mutate targets in specific ways.
|
|
# This structure allows for grouping a variety of functionality in an
|
|
# orthogonal way to the functionality in toolsets, and without specifying
|
|
# more target variations. In turn the modifiers can be used as building
|
|
# blocks to implement simple requests, like the <version> feature.
|
|
|
|
import modules ;
|
|
import feature ;
|
|
import errors ;
|
|
import type ;
|
|
import class : class new ;
|
|
import generators : generator ;
|
|
import property ;
|
|
import virtual-target ;
|
|
import numbers ;
|
|
import sequence ;
|
|
import symlink ;
|
|
import property-set ;
|
|
|
|
# Base generator for creating targets that are modifications of existing
|
|
# targets.
|
|
#
|
|
rule modifier (
|
|
id
|
|
composing ?
|
|
: source-types *
|
|
: target-types-and-names +
|
|
: requirements *
|
|
)
|
|
{
|
|
generator.__init__ $(id) $(composing) : $(source-types) : $(target-types-and-names) : $(requirements) ;
|
|
|
|
self.targets-in-progress = ;
|
|
|
|
# Wraps the generation of the target to call before and after rules to
|
|
# affect the real target.
|
|
#
|
|
rule run ( project name ? : property-set : sources + : multiple ? )
|
|
{
|
|
local result ;
|
|
local current-target = $(project)^$(name) ;
|
|
if ! $(current-target) in $(self.targets-in-progress)
|
|
{
|
|
# Before modifications...
|
|
local project_ = [ modify-project-before
|
|
$(project) $(name) : $(property-set) : $(sources) : $(multiple) ] ;
|
|
local name_ = [ modify-name-before
|
|
$(project) $(name) : $(property-set) : $(sources) : $(multiple) ] ;
|
|
local property-set_ = [ modify-properties-before
|
|
$(project) $(name) : $(property-set) : $(sources) : $(multiple) ] ;
|
|
local sources_ = [ modify-sources-before
|
|
$(project) $(name) : $(property-set) : $(sources) : $(multiple) ] ;
|
|
local multiple_ = [ modify-multiple-before
|
|
$(project) $(name) : $(property-set) : $(sources) : $(multiple) ] ;
|
|
project = $(project_) ;
|
|
name = $(name_) ;
|
|
property-set = $(property-set_) ;
|
|
sources = $(sources_) ;
|
|
multiple = $(multiple_) ;
|
|
|
|
# Generate the real target...
|
|
local target-type-p = [ property.select <main-target-type> : [ $(property-set).raw ] ] ;
|
|
self.targets-in-progress += $(current-target) ;
|
|
result =
|
|
[ generators.construct $(project) $(name) : $(target-type-p:G=) $(multiple) :
|
|
$(property-set) : $(sources) ] ;
|
|
self.targets-in-progress = $(self.targets-in-progress[1--2]) ;
|
|
|
|
# After modifications...
|
|
result = [ modify-target-after $(result) :
|
|
$(project) $(name) : $(property-set) : $(sources) : $(multiple) ] ;
|
|
}
|
|
return $(result) ;
|
|
}
|
|
|
|
rule modify-project-before ( project name ? : property-set : sources + : multiple ? )
|
|
{
|
|
return $(project) ;
|
|
}
|
|
|
|
rule modify-name-before ( project name ? : property-set : sources + : multiple ? )
|
|
{
|
|
return $(name) ;
|
|
}
|
|
|
|
rule modify-properties-before ( project name ? : property-set : sources + : multiple ? )
|
|
{
|
|
return $(property-set) ;
|
|
}
|
|
|
|
rule modify-sources-before ( project name ? : property-set : sources + : multiple ? )
|
|
{
|
|
return $(sources) ;
|
|
}
|
|
|
|
rule modify-multiple-before ( project name ? : property-set : sources + : multiple ? )
|
|
{
|
|
return $(multiple) ;
|
|
}
|
|
|
|
rule modify-target-after ( target : project name ? : property-set : sources + : multiple ? )
|
|
{
|
|
return $(target) ;
|
|
}
|
|
|
|
# Utility, clones a file-target with optional changes to the name, type, and project
|
|
# of the target.
|
|
# NOTE: This functionality should be moved, and generalized, to virtual-targets.
|
|
#
|
|
rule clone-file-target ( target : new-name ? : new-type ? : new-project ? )
|
|
{
|
|
# Need a MUTCH better way to clone a target...
|
|
new-name ?= [ $(target).name ] ;
|
|
new-type ?= [ $(target).type ] ;
|
|
new-project ?= [ $(target).project ] ;
|
|
local result = [ new file-target $(new-name) : $(new-type) : $(new-project) ] ;
|
|
|
|
if [ $(target).dependencies ] { $(result).depends [ $(target).dependencies ] ; }
|
|
$(result).suffix [ $(target).suffix ] ;
|
|
$(result).root [ $(target).root ] ;
|
|
$(result).set-usage-requirements [ $(target).usage-requirements ] ;
|
|
|
|
local action = [ $(target).action ] ;
|
|
local action-class = [ modules.peek $(action) : __class__ ] ;
|
|
|
|
local ps = [ $(action).properties-ps ] ;
|
|
local cloned-action = [ new $(action-class) $(result) :
|
|
[ $(action).sources ] : [ $(action).action-name ] : $(ps) ] ;
|
|
$(result).action $(cloned-action) ;
|
|
|
|
return $(result) ;
|
|
}
|
|
}
|
|
class modifier : generator ;
|
|
|
|
# A modifier that changes the name of a target, after it's generated, given
|
|
# a regular expression to slpit the name, and a set of token to insert
|
|
# between the split tokens of the name. This also exposes the target for other
|
|
# uses with a symlink to the original name (optionally).
|
|
#
|
|
rule name-modifier ( )
|
|
{
|
|
# Apply ourselves to EXE targets, for now.
|
|
modifier.__init__ name.modifier : : EXE LIB : <name-modify>yes ;
|
|
|
|
# Modifies the name, by cloning the target with the new name.
|
|
#
|
|
rule modify-target-after ( target : project name ? : property-set : sources + : multiple ? )
|
|
{
|
|
local result = $(target) ;
|
|
|
|
local name-mod-p = [ property.select <name-modifier> : [ $(property-set).raw ] ] ;
|
|
if $(name-mod-p)
|
|
{
|
|
local new-name = [ modify-name [ $(target).name ] : $(name-mod-p:G=) ] ;
|
|
if $(new-name) != [ $(target).name ]
|
|
{
|
|
result = [ clone-file-target $(target) : $(new-name) ] ;
|
|
}
|
|
local expose-original-as-symlink = [ MATCH "<symlink>(.*)" : $(name-mod-p) ] ;
|
|
if $(expose-original-as-symlink)
|
|
{
|
|
local symlink-t = [ new symlink-targets $(project) : $(name) : [ $(result).name ] ] ;
|
|
result = [ $(symlink-t).construct $(result)
|
|
: [ property-set.create [ $(property-set).raw ] <symlink-location>build-relative ] ] ;
|
|
}
|
|
}
|
|
|
|
return $(result) ;
|
|
}
|
|
|
|
# Do the transformation of the name.
|
|
#
|
|
rule modify-name ( name : modifier-spec + )
|
|
{
|
|
local match = [ MATCH "<match>(.*)" : $(modifier-spec) ] ;
|
|
local name-parts = [ MATCH $(match) : $(name) ] ;
|
|
local insertions = [ sequence.insertion-sort [ MATCH "(<[0123456789]+>.*)" : $(modifier-spec) ] ] ;
|
|
local new-name-parts ;
|
|
local insert-position = 1 ;
|
|
while $(insertions)
|
|
{
|
|
local insertion = [ MATCH "<$(insert-position)>(.*)" : $(insertions[1]) ] ;
|
|
if $(insertion)
|
|
{
|
|
new-name-parts += $(insertion) ;
|
|
insertions = $(insertions[2-]) ;
|
|
}
|
|
new-name-parts += $(name-parts[1]) ;
|
|
name-parts = $(name-parts[2-]) ;
|
|
insert-position = [ numbers.increment $(insert-position) ] ;
|
|
}
|
|
new-name-parts += $(name-parts) ;
|
|
return [ sequence.join $(new-name-parts) ] ;
|
|
}
|
|
|
|
rule optional-properties ( )
|
|
{
|
|
return <name-modify>yes ;
|
|
}
|
|
}
|
|
class name-modifier : modifier ;
|
|
feature.feature name-modifier : : free ;
|
|
feature.feature name-modify : no yes : incidental optional ;
|
|
generators.register [ new name-modifier ] ;
|
|
|
|
# Translates <version> property to a set of modification properties
|
|
# that are applied by the name-modifier, and symlink-modifier.
|
|
#
|
|
rule version-to-modifier ( property : properties * )
|
|
{
|
|
return
|
|
<name-modify>yes
|
|
<name-modifier><match>"^([^.]*)(.*)" <name-modifier><2>.$(property:G=)
|
|
<name-modifier><symlink>yes
|
|
;
|
|
}
|
|
feature.action <version> : version-to-modifier ;
|