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