| # Copyright 2006 Vladimir Prus |
| # Distributed under the Boost Software License, Version 1.0. |
| # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) |
| |
| # Declares main target 'generate' used to produce targets by calling a |
| # user-provided rule that takes and produces virtual targets. |
| |
| import "class" : new ; |
| import errors ; |
| import feature ; |
| import project ; |
| import property ; |
| import property-set ; |
| import targets ; |
| import regex ; |
| |
| |
| feature.feature generating-rule : : free ; |
| |
| |
| class generated-target-class : basic-target |
| { |
| import errors ; |
| import indirect ; |
| import virtual-target ; |
| |
| rule __init__ ( name : project : sources * : requirements * |
| : default-build * : usage-requirements * ) |
| { |
| basic-target.__init__ $(name) : $(project) : $(sources) |
| : $(requirements) : $(default-build) : $(usage-requirements) ; |
| |
| if ! [ $(self.requirements).get <generating-rule> ] |
| { |
| errors.user-error "The generate rule requires the <generating-rule>" |
| "property to be set" ; |
| } |
| } |
| |
| rule construct ( name : sources * : property-set ) |
| { |
| local result ; |
| local gr = [ $(property-set).get <generating-rule> ] ; |
| |
| # FIXME: this is a copy-paste from virtual-target.jam. We should add a |
| # utility rule to call a rule like this. |
| local rule-name = [ MATCH ^@(.*) : $(gr) ] ; |
| if $(rule-name) |
| { |
| if $(gr[2]) |
| { |
| local target-name = [ full-name ] ; |
| errors.user-error "Multiple <generating-rule> properties" |
| "encountered for target $(target-name)." ; |
| } |
| |
| result = [ indirect.call $(rule-name) $(self.project) $(name) |
| : $(property-set) : $(sources) ] ; |
| |
| if ! $(result) |
| { |
| ECHO "warning: Unable to construct" [ full-name ] ; |
| } |
| } |
| |
| local ur ; |
| local targets ; |
| |
| if $(result) |
| { |
| if [ class.is-a $(result[1]) : property-set ] |
| { |
| ur = $(result[1]) ; |
| targets = $(result[2-]) ; |
| } |
| else |
| { |
| ur = [ property-set.empty ] ; |
| targets = $(result) ; |
| } |
| } |
| # FIXME: the following loop should be doable using sequence.transform or |
| # some similar utility rule. |
| local rt ; |
| for local t in $(targets) |
| { |
| rt += [ virtual-target.register $(t) ] ; |
| } |
| return $(ur) $(rt) ; |
| } |
| } |
| |
| |
| rule generate ( name : sources * : requirements * : default-build * |
| : usage-requirements * ) |
| { |
| local project = [ project.current ] ; |
| |
| targets.main-target-alternative |
| [ new generated-target-class $(name) : $(project) |
| : [ targets.main-target-sources $(sources) : $(name) ] |
| : [ targets.main-target-requirements $(requirements) : $(project) ] |
| : [ targets.main-target-default-build $(default-build) : $(project) ] |
| : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ] |
| ] ; |
| } |
| |
| IMPORT $(__name__) : generate : : generate ; |