2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-17 01:32:12 +00:00
Files
build/v2/tools/stage.jam
Vladimir Prus 533abcaadd Bugfix: the main target rules did not work unless called from Jamfile.
The used 'CALLER_MODULE' to determine the project where the main target
is to be declared, which did not work if the rule is called from another
module.

Thanks to Zbynek Winkler for the bug report.

* build/project.jam (current): New rule
* test/wrapper.py: New test
* other files: Use 'project.current'.


[SVN r22569]
2004-03-31 06:53:56 +00:00

308 lines
9.8 KiB
Plaintext

# Copyright (C) Vladimir Prus 2002. 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.
# This module defines the 'stage' rule, used to copy a set of targets to
# a single location
#
# Typical usage:
#
# stage dist : hello_world : <location>/usr/bin ;
#
# The source target will be copied to the specified location. Some targets will
# we specially processed. In particular, binaries will be relinked. Free properties
# from stage dist will be included to properties used for relinking. For example
#
# stage dist : hello_world : <location>/usr/bin <dll-path>/opt/lib ;
#
# will cause 'hello_world' to be relinked to the new location, and <dll-path>
# property will be added when relinking.
#
# Two properties specifically control 'stage' rule.
#
# - <location> tells where to put targets. If not specified, directory
# with the same name as stage name will be used.
#
# - <name> tells the new name of the staged target. In this case, only
# one target can be specified in sources.
#
# The stage rule can also traverse dependencies, for example to install a
# program an all required libraries. Two properties affect this.
#
# - <traverse-dependencies>on tells that dependencies should be traversed.
# For each target in 'stage' sources, all sources to that target and all
# dependency properties are traversed. Sources and dependecy properties of
# those target are traversed recursively.
#
# - <include-type>SOME_TYPE tells that targets of SOME_TYPE or a type derived
# from SOME_TYPE, should be included.
# If no such property is specified, then all found targets will be staged.
# Otherwise, only targets with types mentioned in <include-type> property
# will be included.
#
# Example usage::
#
# stage dist : hello_world :
# <traverse-dependencies>on <include-type>EXE <include-type>SHARED_LIB ;
#
import targets ;
import "class" : new ;
import property ;
import errors : error ;
import type : type ;
import type ;
import regex ;
import generators ;
import feature ;
import project ;
feature.feature <traverse-dependencies> : off on : incidental ;
feature.feature <include-type> : : free incidental ;
class stage-target-class : basic-target
{
import feature project type errors generators ;
import "class" : new ;
rule __init__ ( name-and-dir : project : sources * : requirements * : default-build * )
{
basic-target.__init__ $(name-and-dir) : $(project) : $(sources) : $(requirements)
: $(default-build) ;
}
# If <location> is not set, sets it based on the project data.
rule update-location ( property-set )
{
local loc = [ $(property-set).get <location> ] ;
if ! $(loc)
{
loc = [ project.path-relative-to-project-location $(self.name)
$(self.project) ] ;
property-set = [ $(property-set).add-raw $(loc:G=<location>) ] ;
}
return $(property-set) ;
}
# Constructs the targets of types for which a type exists
# with the form STAGED_*.
rule construct-special-targets ( property-set : source : type )
{
local targets = [ generators.construct $(self.project) : $(type) :
$(property-set) : $(source) : * ] ;
return $(targets) ;
}
# Constructs the targets of types for which there is no STAGED_* type.
rule construct-regular-targets ( property-set : source )
{
local n = [ $(source).name ] ;
if $(name)
{
n = $(name) ;
}
targets = [ new file-target $(n:D=) : [ $(source).type ]
: $(self.project) ] ;
local a = [ $(source).action ] ;
local new-a ;
if $(a)
{
# Copy the properties of original target. They, in particular
# can affect the suffix of the target.
new-a = [ new action $(targets) : $(source) : common.copy : [ $(a).properties ] ] ;
}
else
{
new-a = [ new action $(targets) : $(source) : common.copy ] ;
}
$(targets).suffix [ $(source).suffix ] ;
$(targets).action $(new-a) ;
return $(targets) ;
}
rule construct ( source-targets * : property-set )
{
local name = [ $(property-set).get <name> ] ;
if $(name) && $(source-targets[2])
{
errors.error "<name> property cannot be specified when staging several targets" ;
}
if [ $(property-set).get <traverse-dependencies> ] = "on"
{
source-targets = [ collect-targets $(source-targets)
: [ $(property-set).get <include-type> ] ] ;
}
property-set = [ update-location $(property-set) ] ;
local include-types = [ $(property-set).get <include-type> ] ;
local result ;
for local i in $(source-targets)
{
if ! [ $(i).intermediate ] && [ $(i).type ] != SEARCHED_LIB
{
local staged-targets ;
local t = [ $(i).type ] ;
# See if something special should be done when staging this
# type. It is indicated by presense of special "staged" type
if $(t) && [ type.registered STAGED_$(t) ]
{
staged-targets = [ construct-special-targets $(property-set) : $(i) : STAGED_$(t) ] ;
}
else
{
staged-targets = [ construct-regular-targets $(property-set) : $(i) ] ;
}
if ! $(staged-targets)
{
errors.error "Unable to generate staged version of " [ $(source).str ] ;
}
for t in [ select-included $(staged-targets) : $(include-types) ]
{
$(t).set-path [ $(property-set).get <location> ] ;
result += [ virtual-target.register $(t) ] ;
}
}
}
return $(result) ;
}
rule select-included ( source-targets * : types-to-include * )
{
local result-targets ;
if $(types-to-include)
{
for local r in $(source-targets)
{
local ty = [ $(r).type ] ;
if $(ty)
{
if [ include-type $(ty) : $(types-to-include) ]
{
result-targets += $(r) ;
}
}
}
}
else
{
result-targets = $(source-targets) ;
}
return $(result-targets) ;
}
rule collect-targets ( targets * : types-to-include * )
{
# Find subvariants
local s ;
for local t in $(targets)
{
s += [ $(t).creating-subvariant ] ;
}
s = [ sequence.unique $(s) ] ;
local result = $(targets) ;
for local i in $(s)
{
result += [ $(i).all-referenced-targets ] ;
}
result = [ sequence.unique $(result) ] ;
}
# Don't do nothing.
rule check-for-unused-sources ( result * : sources * )
{
}
rule check-for-link-compatibility ( * : * )
{
}
# Returns true iff 'type' is subtype of some element of 'types-to-include'.
local rule include-type ( type : types-to-include * )
{
local found ;
while $(types-to-include) && ! $(found)
{
if [ type.is-subtype $(type) $(types-to-include[1]) ]
{
found = true ;
}
types-to-include = $(types-to-include[2-]) ;
}
return $(found) ;
}
}
# Declare staged version of the EXE type. Generator for this type will
# cause relinking to the new location.
type.register STAGED_EXE : : EXE ;
class stage-exe-generator : generator
{
import type property-set modules ;
rule __init__ ( )
{
generator.__init__ stage-exe : EXE : STAGED_EXE ;
}
rule run ( project name ? : property-set : source : multiple ? )
{
local action = [ $(source).action ] ;
# stage can affect the relinking details.
local ps = [ $(action).properties ] ;
local new-ps = [ $(ps).add [ property-set.create [ $(property-set).free ] ] ] ;
local cloned-action = [ virtual-target.clone-action $(action) : $(project) :
"" : $(new-ps) ] ;
local result = [ $(cloned-action).targets ] ;
return $(result) ;
}
}
generators.register [ new stage-exe-generator ] ;
# Declares a stage target. When build, it will construct all sources
# and place in one directory. The directory can be specified in requirements
# with 'location' property. If not specified, the directory name will be
# the same as target name, relative to the project where the target
# is declared.
rule stage ( name : sources * : requirements * : default-build * )
{
local project = [ project.current ] ;
targets.main-target-alternative
[ new stage-target-class $(name) : $(project) : $(sources)
: [ targets.main-target-requirements $(requirements) : $(project) ]
: [ targets.main-target-default-build $(default-build) : $(project) ]
] ;
}
IMPORT $(__name__) : stage : : stage ;