Boost logo

Boost-Build :

From: Vladimir Prus (ghost_at_[hidden])
Date: 2003-02-25 03:31:17


Rene Rivera wrote:
> I made some time to work on the modifier ideas I had. The basic approach is
> one borrowed from V1 in which there are modifiers to mutate the generation
> of targets, files, etc.
>
> I thought I'd post some of the code I have so far, to get some feedback and
> to request help. I'm currently stuck because of a current limitation of
> BB2. The way the current code works it wraps some basic target types (EXE
> only for now) with a generic generator that mutates the target.
> Unfortunately this produces multiple possible transformations for a single
> target, which causes an error...

I'm now looking at your code. I see that there's generator "modifier" which
can create one target type from another target type, applying various
modifications. That's reasonable, and even more --- I do the same in
stage.jam, although I did not bother with genericity there and wrote the
minimalistic generator.

Later on, you derive 'name-modifier' from 'modifier' and say that this
new generator can produce EXE. And here it booms:

> /home/grafik/CVSROOTs/Boost/boost/tools/build/examples-v2/../new/generators
>.jam:811: in select-dependency-graph from module generators
> error: 2 possible generations for Can't handle this now.

Ee... the 'name-modifier' generator has '<name-modify>yes' as requirements, it
should be preferred to generic linker. There are three problems:

1. The <name-modify> is not optional, so the default value is added to build
request. Later <name-modify>yes is added too, so there are two different
values. Not sure this is the real problem yet.

2. The generator matching works in this way. All generators are asked for
their rank w.r.t specific properties. If generator returns nothing, it can't
work. Otherwise it returns a number: the larger the number, the more
specific the generator is. Requirements are used to check if generator
can work. To boost specificity, optional properties are used: now the match
rank is equal to the number of optional properties which are present in build
properties.

3. When cloning the target, you don't clone the action. The problem is that
action has a back pointer to all it's targets, so cloning just target does
not work. Your comment which reads:

# Need a MUTCH better way to clone a target...
# ...Or a way to mutate an existing target safely.

Is *extremely* right!

After addressing those problem I get the following:

MkDir1 bin
MkDir1 bin/gcc
MkDir1 bin/gcc/debug
MkDir1 bin/gcc/debug/main-target-hello
gcc.compile bin/gcc/debug/main-target-hello/hello.o
gcc.link bin/gcc/debug/main-target-hello/hello.1.0

Which looks sane. I attach the diff to your version as well as new version of
modifiers.jam. Now the issues are:

1. Cloning of targets should become separate rule, unless we want bugs all
over the place (current stage.jam uses the same).

2. How modifiers can be used to implement stage. I kind of like current idea
that targets are not altered during staging unless they define staged type.
OTOH, we might just use a new property <staging>, which will select generator
that will do the right thing and now this looks better to me.

- Volodya

 --------------Boundary-00=_5OVUL7KY8YXZ47P8FUA4 Content-Type: text/x-diff;
charset="iso-8859-1";
name="modifiers.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="modifiers.diff"

--- modifiers.jam.original Sun Feb 23 23:38:04 2003
+++ modifiers.jam Tue Feb 25 11:21:23 2003
@@ -18,7 +18,7 @@
{
# Generic name modification...
feature.feature name-modifier : : free ;
- feature.feature name-modify : no yes : incidental ;
+ feature.feature name-modify : no yes : incidental optional ;
generators.register [ new name-modifier ] ;

# Translates <version> to name modification...
@@ -112,6 +112,12 @@
{
return $(target) ;
}
+
+ rule optional-properties ( )
+ {
+ return <name-modify>yes ;
+ }
+
}
class modifier : generator ;

@@ -135,12 +141,20 @@
# Need a MUTCH better way to clone a target...
# ...Or a way to mutate an existing target safely.
result = [ new file-target $(new-name) : [ $(target).type ] : [ $(target).project ] ] ;
- if [ $(target).dependencies ] { $(result).depends [ $(target).dependencies ] ; }
+
+ if [ $(target).dependencies ] { $(result).depends [ $(target).dependencies ] ; }
$(result).suffix [ $(target).suffix ] ;
- $(result).action [ $(target).action ] ;
- $(result).root [ $(target).root ] ;
+ $(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) ;
+
#~ ECHO --> [$(result)] ;
#~ ECHO --> [ $(result).str ] ;
}
 --------------Boundary-00=_5OVUL7KY8YXZ47P8FUA4 Content-Type: text/x-java;
charset="iso-8859-1";
name="modifiers.jam"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="modifiers.jam"

# 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.

import modules ;
import feature ;
import errors ;
import type ;
import class : class new ;
import generators : generator ;
import property ;
import virtual-target ;
import numbers ;
import sequence ;

rule init ( )
{
# Generic name modification...
feature.feature name-modifier : : free ;
feature.feature name-modify : no yes : incidental optional ;
generators.register [ new name-modifier ] ;

# Translates <version> to name modification...
feature.action <version> : version-to-modifier ;
}

# Translates <version> to name modification...
rule version-to-modifier ( property : properties * )
{
return <name-modify>yes <name-modifier><match>"^([^.]*)(.*)" <name-modifier><2>.$(property:G=) ;
}

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 = ;

rule run ( project name ? : property-set : sources + : multiple ? )
{
#~ ECHO >>> run $(project) $(name) - [ $(property-set).raw ] - $(sources) - $(multiple) ;

local result ;
local current-target = $(project)^$(name) ;
if ! $(current-target) in $(self.targets-in-progress)
{
# Before type 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) ;
}

rule optional-properties ( )
{
return <name-modify>yes ;
}

}
class modifier : generator ;

rule name-modifier ( )
{
modifier.__init__ name.modifier : : EXE : <name-modify>yes ;

rule modify-target-after ( target : project name ? : property-set : sources + : multiple ? )
{
#~ ECHO >>> modify-target-after $(project) $(name) - [ $(property-set).raw ] - $(sources) - $(multiple) ;
local result = $(target) ;

local name-mod-p = [ property.select <name-modifier> : [ $(property-set).raw ] ] ;
if $(name-mod-p)
{
#~ ECHO --> [$(target)] ;
#~ ECHO --> [ $(target).str ] ;

local new-name = [ modify-name [ $(target).name ] : $(name-mod-p:G=) ] ;

# Need a MUTCH better way to clone a target...
# ...Or a way to mutate an existing target safely.
result = [ new file-target $(new-name) : [ $(target).type ] : [ $(target).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) ;

#~ ECHO --> [$(result)] ;
#~ ECHO --> [ $(result).str ] ;
}

return $(result) ;
}

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) ] ;
}
}
class name-modifier : modifier ;

 --------------Boundary-00=_5OVUL7KY8YXZ47P8FUA4--


Boost-Build list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk