import utility ;
import path ;
import property ;
+ import property-set ;
import sequence ;
import set ;
+ import toolset ;
import type ;
import virtual-target ;
# name. We use parallel lists for prefix and postfix (as opposed to
# mapping), because given target type might occur several times, for
# example "H H(%_symbols)".
- local m = [ MATCH ([^\\(]*)(\\((.*)%(.*)\\))? : $(e) ] ;
+ local m = [ MATCH "([^\\(]*)(\\((.*)%(.*)\\))?" : $(e) ] ;
self.target-types += $(m[1]) ;
self.name-prefix += $(m[3]:E="") ;
self.name-postfix += $(m[4]:E="") ;
# Note that 'transform' here, is the same as 'for_each'.
sequence.transform type.validate : $(self.source-types) ;
sequence.transform type.validate : $(self.target-types) ;
+
+ local relevant-for-generator =
+ [ sequence.transform utility.ungrist : $(requirements:G) ] ;
+ self.relevant-features = [ property-set.create <relevant>$(relevant-for-generator) ] ;
}
################# End of constructor #################
local target-types ;
for local t in $(self.target-types-and-names)
{
- local m = [ MATCH ([^\\(]*)(\\(.*\\))? : $(t) ] ;
+ local m = [ MATCH "([^\\(]*)(\\(.*\\))?" : $(t) ] ;
if $(m) = $(base)
{
target-types += $(type)$(m[2]:E="") ;
}
local result ;
- if $(consumed)
+ if $(consumed[2])
{
- result = [ construct-result $(consumed) : $(project) $(name) :
- $(property-set) ] ;
+ result = [ construct-result $(consumed[2-]) : $(project) $(name) :
+ [ $(property-set).add $(consumed[1]) ] ] ;
}
if $(result)
generators.dout [ indent ] " FAILURE" ;
}
generators.dout ;
- return $(result) ;
+ if $(result)
+ {
+ # Make sure that we propagate usage-requirements up the stack.
+ return [ $(result[1]).add $(consumed[1]) ] $(result[2-]) ;
+ }
}
# Constructs the dependency graph to be returned by this generator.
)
{
local result ;
+
+ local relevant = [ toolset.relevant $(self.rule-name) ] ;
+ relevant = [ $(relevant).add $(self.relevant-features) ] ;
+ property-set = [ $(property-set).add $(relevant) ] ;
+
# If this is a 1->1 transformation, apply it to all consumed targets in
# order.
if ! $(self.source-types[2]) && ! $(self.composing)
result += [ generated-targets $(consumed) : $(property-set) :
$(project) $(name) ] ;
}
- return $(result) ;
+ if $(result)
+ {
+ return $(relevant) $(result) ;
+ }
}
# Determine target name from fullname (maybe including path components)
{
local _consumed ;
local missing-types ;
+ local usage-requirements ;
if $(sources[2])
{
local temp = [ consume-directly $(sources) ] ;
if $(temp[1])
{
+ usage-requirements = [ property-set.empty ] ;
_consumed = $(temp[1]) ;
}
missing-types = $(temp[2-]) ;
# everything to the required type. There is no need to rerun it on
# targets of different types.
- # NOTE: ignoring usage requirements.
+ usage-requirements = $(transformed[1]) ;
for local t in $(transformed[2-])
{
if [ $(t).type ] in $(missing-types)
}
}
- return [ sequence.unique $(_consumed) ] ;
+ return $(usage-requirements) [ sequence.unique $(_consumed) ] ;
}
# Converts several files to consumable types. Called for composing
if ! $(self.source-types)
{
# Anything is acceptible
- return $(sources) ;
+ return [ property-set.empty ] $(sources) ;
}
else
{
+ local usage-requirements = [ property-set.empty ] ;
local acceptible-types = [ sequence.unique
[ sequence.transform type.all-derived : $(self.source-types) ] ] ;
for local source in $(sources)
{
generators.dout [ indent ] " failed to convert " $(source) ;
}
+ else
+ {
+ usage-requirements = [ $(usage-requirements).add $(transformed[1]) ] ;
+ }
}
else
{
result += $(source) ;
}
}
- return [ sequence.unique $(result) : stable ] ;
+ return $(usage-requirements) [ sequence.unique $(result) : stable ] ;
}
}
.active-generators = ;
}
- if (.construct-stack)
+ # FIXME This is probably not intended be be run unconditionally,
+ # but changing it causes no_type to fail.
+ if "(.construct-stack)"
{
ensure-type $(sources) ;
}