summaryrefslogtreecommitdiff
path: root/jam-files/boost-build/build/virtual-target.jam
diff options
context:
space:
mode:
Diffstat (limited to 'jam-files/boost-build/build/virtual-target.jam')
-rw-r--r--jam-files/boost-build/build/virtual-target.jam1317
1 files changed, 0 insertions, 1317 deletions
diff --git a/jam-files/boost-build/build/virtual-target.jam b/jam-files/boost-build/build/virtual-target.jam
deleted file mode 100644
index 2e8446bc..00000000
--- a/jam-files/boost-build/build/virtual-target.jam
+++ /dev/null
@@ -1,1317 +0,0 @@
-# Copyright 2003 Dave Abrahams
-# Copyright 2005, 2006 Rene Rivera
-# Copyright 2002, 2003, 2004, 2005, 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)
-
-# Implements virtual targets, which correspond to actual files created during a
-# build, but are not yet targets in Jam sense. They are needed, for example,
-# when searching for possible transformation sequences, when it is not yet known
-# whether a particular target should be created at all.
-
-import "class" : new ;
-import errors ;
-import path ;
-import sequence ;
-import set ;
-import type ;
-import utility ;
-
-
-# +--------------------------+
-# | virtual-target |
-# +==========================+
-# | actualize |
-# +--------------------------+
-# | actualize-action() = 0 |
-# | actualize-location() = 0 |
-# +----------------+---------+
-# |
-# ^
-# / \
-# +-+-+
-# |
-# +---------------------+ +-------+--------------+
-# | action | | abstract-file-target |
-# +=====================| * +======================+
-# | action-name | +--+ action |
-# | properties | | +----------------------+
-# +---------------------+--+ | actualize-action() |
-# | actualize() |0..1 +-----------+----------+
-# | path() | |
-# | adjust-properties() | sources |
-# | actualize-sources() | targets |
-# +------+--------------+ ^
-# | / \
-# ^ +-+-+
-# / \ |
-# +-+-+ +-------------+-------------+
-# | | |
-# | +------+---------------+ +--------+-------------+
-# | | file-target | | searched-lib-target |
-# | +======================+ +======================+
-# | | actualize-location() | | actualize-location() |
-# | +----------------------+ +----------------------+
-# |
-# +-+------------------------------+
-# | |
-# +----+----------------+ +---------+-----------+
-# | compile-action | | link-action |
-# +=====================+ +=====================+
-# | adjust-properties() | | adjust-properties() |
-# +---------------------+ | actualize-sources() |
-# +---------------------+
-#
-# The 'compile-action' and 'link-action' classes are not defined here but in
-# builtin.jam modules. They are shown in the diagram to give the big picture.
-
-
-# Models a potential target. It can be converted into a Jam target and used in
-# building, if needed. However, it can be also dropped, which allows us to
-# search for different transformations and select only one.
-#
-class virtual-target
-{
- import scanner ;
- import sequence ;
- import utility ;
- import virtual-target ;
-
- rule __init__ (
- name # Target/project name.
- : project # Project to which this target belongs.
- )
- {
- self.name = $(name) ;
- self.project = $(project) ;
- self.dependencies = ;
- }
-
- # Name of this target.
- #
- rule name ( )
- {
- return $(self.name) ;
- }
-
- # Project of this target.
- #
- rule project ( )
- {
- return $(self.project) ;
- }
-
- # Adds additional 'virtual-target' instances this one depends on.
- #
- rule depends ( d + )
- {
- self.dependencies = [ sequence.merge $(self.dependencies) :
- [ sequence.insertion-sort $(d) ] ] ;
- }
-
- rule dependencies ( )
- {
- return $(self.dependencies) ;
- }
-
- rule always ( )
- {
- .always = 1 ;
- }
-
- # Generates all the actual targets and sets up build actions for this
- # target.
- #
- # If 'scanner' is specified, creates an additional target with the same
- # location as the actual target, which will depend on the actual target and
- # be associated with a 'scanner'. That additional target is returned. See
- # the docs (#dependency_scanning) for rationale. Target must correspond to a
- # file if 'scanner' is specified.
- #
- # If scanner is not specified then the actual target is returned.
- #
- rule actualize ( scanner ? )
- {
- local actual-name = [ actualize-no-scanner ] ;
-
- if $(.always)
- {
- ALWAYS $(actual-name) ;
- }
-
- if ! $(scanner)
- {
- return $(actual-name) ;
- }
- else
- {
- # Add the scanner instance to the grist for name.
- local g = [ sequence.join
- [ utility.ungrist $(actual-name:G) ] $(scanner) : - ] ;
- local name = $(actual-name:G=$(g)) ;
-
- if ! $(self.made.$(name))
- {
- self.made.$(name) = true ;
-
- DEPENDS $(name) : $(actual-name) ;
-
- actualize-location $(name) ;
-
- scanner.install $(scanner) : $(name) $(__name__) ;
- }
- return $(name) ;
- }
- }
-
-# private: (overridables)
-
- # Sets up build actions for 'target'. Should call appropriate rules and set
- # target variables.
- #
- rule actualize-action ( target )
- {
- errors.error "method should be defined in derived classes" ;
- }
-
- # Sets up variables on 'target' which specify its location.
- #
- rule actualize-location ( target )
- {
- errors.error "method should be defined in derived classes" ;
- }
-
- # If the target is a generated one, returns the path where it will be
- # generated. Otherwise, returns an empty list.
- #
- rule path ( )
- {
- errors.error "method should be defined in derived classes" ;
- }
-
- # Returns the actual target name to be used in case when no scanner is
- # involved.
- #
- rule actual-name ( )
- {
- errors.error "method should be defined in derived classes" ;
- }
-
-# implementation
- rule actualize-no-scanner ( )
- {
- # In fact, we just need to merge virtual-target with
- # abstract-file-target as the latter is the only class derived from the
- # former. But that has been left for later.
-
- errors.error "method should be defined in derived classes" ;
- }
-}
-
-
-# Target corresponding to a file. The exact mapping for file is not yet
-# specified in this class. (TODO: Actually, the class name could be better...)
-#
-# May be a source file (when no action is specified) or a derived file
-# (otherwise).
-#
-# The target's grist is a concatenation of its project's location, action
-# properties (for derived targets) and, optionally, value identifying the main
-# target.
-#
-class abstract-file-target : virtual-target
-{
- import project ;
- import regex ;
- import sequence ;
- import path ;
- import type ;
- import property-set ;
- import indirect ;
-
- rule __init__ (
- name # Target's name.
- exact ? # If non-empty, the name is exactly the name created file
- # should have. Otherwise, the '__init__' method will add a
- # suffix obtained from 'type' by calling
- # 'type.generated-target-suffix'.
- : type ? # Target's type.
- : project
- : action ?
- )
- {
- virtual-target.__init__ $(name) : $(project) ;
-
- self.type = $(type) ;
- self.action = $(action) ;
- if $(action)
- {
- $(action).add-targets $(__name__) ;
-
- if $(self.type) && ! $(exact)
- {
- _adjust-name $(name) ;
- }
- }
- }
-
- rule type ( )
- {
- return $(self.type) ;
- }
-
- # Sets the path. When generating target name, it will override any path
- # computation from properties.
- #
- rule set-path ( path )
- {
- self.path = [ path.native $(path) ] ;
- }
-
- # Returns the currently set action.
- #
- rule action ( )
- {
- return $(self.action) ;
- }
-
- # Sets/gets the 'root' flag. Target is root if it directly corresponds to
- # some variant of a main target.
- #
- rule root ( set ? )
- {
- if $(set)
- {
- self.root = true ;
- }
- return $(self.root) ;
- }
-
- # Gets or sets the subvariant which created this target. Subvariant is set
- # when target is brought into existance and is never changed after that. In
- # particular, if a target is shared by a subvariant, only the first is
- # stored.
- #
- rule creating-subvariant ( s ? # If specified, specifies the value to set,
- # which should be a 'subvariant' class
- # instance.
- )
- {
- if $(s) && ! $(self.creating-subvariant)
- {
- self.creating-subvariant = $(s) ;
- }
- return $(self.creating-subvariant) ;
- }
-
- rule actualize-action ( target )
- {
- if $(self.action)
- {
- $(self.action).actualize ;
- }
- }
-
- # Return a human-readable representation of this target. If this target has
- # an action, that is:
- #
- # { <action-name>-<self.name>.<self.type> <action-sources>... }
- #
- # otherwise, it is:
- #
- # { <self.name>.<self.type> }
- #
- rule str ( )
- {
- local action = [ action ] ;
- local name-dot-type = [ sequence.join $(self.name) "." $(self.type) ] ;
-
- if $(action)
- {
- local sources = [ $(action).sources ] ;
- local action-name = [ $(action).action-name ] ;
-
- local ss ;
- for local s in $(sources)
- {
- ss += [ $(s).str ] ;
- }
-
- return "{" $(action-name)-$(name-dot-type) $(ss) "}" ;
- }
- else
- {
- return "{" $(name-dot-type) "}" ;
- }
- }
-
- rule less ( a )
- {
- if [ str ] < [ $(a).str ]
- {
- return true ;
- }
- }
-
- rule equal ( a )
- {
- if [ str ] = [ $(a).str ]
- {
- return true ;
- }
- }
-
-# private:
- rule actual-name ( )
- {
- if ! $(self.actual-name)
- {
- local grist = [ grist ] ;
- local basename = [ path.native $(self.name) ] ;
- self.actual-name = <$(grist)>$(basename) ;
- }
- return $(self.actual-name) ;
- }
-
- # Helper to 'actual-name', above. Computes a unique prefix used to
- # distinguish this target from other targets with the same name creating
- # different files.
- #
- rule grist ( )
- {
- # Depending on target, there may be different approaches to generating
- # unique prefixes. We generate prefixes in the form:
- # <one letter approach code> <the actual prefix>
- local path = [ path ] ;
- if $(path)
- {
- # The target will be generated to a known path. Just use the path
- # for identification, since path is as unique as it can get.
- return p$(path) ;
- }
- else
- {
- # File is either source, which will be searched for, or is not a
- # file at all. Use the location of project for distinguishing.
- local project-location = [ $(self.project).get location ] ;
- local location-grist = [ sequence.join [ regex.split
- $(project-location) "/" ] : "!" ] ;
-
- if $(self.action)
- {
- local ps = [ $(self.action).properties ] ;
- local property-grist = [ $(ps).as-path ] ;
- # 'property-grist' can be empty when 'ps' is an empty property
- # set.
- if $(property-grist)
- {
- location-grist = $(location-grist)/$(property-grist) ;
- }
- }
-
- return l$(location-grist) ;
- }
- }
-
- # Given the target name specified in constructor, returns the name which
- # should be really used, by looking at the <tag> properties. Tag properties
- # need to be specified as <tag>@rule-name. This makes Boost Build call the
- # specified rule with the target name, type and properties to get the new
- # name. If no <tag> property is specified or the rule specified by <tag>
- # returns nothing, returns the result of calling
- # virtual-target.add-prefix-and-suffix.
- #
- rule _adjust-name ( specified-name )
- {
- local ps ;
- if $(self.action)
- {
- ps = [ $(self.action).properties ] ;
- }
- else
- {
- ps = [ property-set.empty ] ;
- }
-
- # We add ourselves to the properties so that any tag rule can get more
- # direct information about the target than just that available through
- # the properties. This is useful in implementing name changes based on
- # the sources of the target. For example to make unique names of object
- # files based on the source file. --grafik
- ps = [ property-set.create [ $(ps).raw ] <target>$(__name__) ] ;
-
- local tag = [ $(ps).get <tag> ] ;
-
- if $(tag)
- {
- local rule-name = [ MATCH ^@(.*) : $(tag) ] ;
- if $(rule-name)
- {
- if $(tag[2])
- {
- errors.error "<tag>@rulename is present but is not the only"
- "<tag> feature" ;
- }
-
- self.name = [ indirect.call $(rule-name) $(specified-name)
- : $(self.type) : $(ps) ] ;
- }
- else
- {
- errors.error
- "The value of the <tag> feature must be '@rule-name'" ;
- }
- }
-
- # If there is no tag or the tag rule returned nothing.
- if ! $(tag) || ! $(self.name)
- {
- self.name = [ virtual-target.add-prefix-and-suffix $(specified-name)
- : $(self.type) : $(ps) ] ;
- }
- }
-
- rule actualize-no-scanner ( )
- {
- local name = [ actual-name ] ;
-
- # Do anything only on the first invocation.
- if ! $(self.made.$(name))
- {
- self.made.$(name) = true ;
-
- if $(self.action)
- {
- # For non-derived target, we do not care if there are several
- # virtual targets that refer to the same name. One case when
- # this is unavoidable is when the file name is main.cpp and two
- # targets have types CPP (for compiling) and MOCCABLE_CPP (for
- # conversion to H via Qt tools).
- virtual-target.register-actual-name $(name) : $(__name__) ;
- }
-
- for local i in $(self.dependencies)
- {
- DEPENDS $(name) : [ $(i).actualize ] ;
- }
-
- actualize-location $(name) ;
- actualize-action $(name) ;
- }
- return $(name) ;
- }
-}
-
-
-# Appends the suffix appropriate to 'type/property-set' combination to the
-# specified name and returns the result.
-#
-rule add-prefix-and-suffix ( specified-name : type ? : property-set )
-{
- local suffix = [ type.generated-target-suffix $(type) : $(property-set) ] ;
-
- # Handle suffixes for which no leading dot is desired. Those are specified
- # by enclosing them in <...>. Needed by python so it can create "_d.so"
- # extensions, for example.
- if $(suffix:G)
- {
- suffix = [ utility.ungrist $(suffix) ] ;
- }
- else
- {
- suffix = .$(suffix) ;
- }
-
- local prefix = [ type.generated-target-prefix $(type) : $(property-set) ] ;
-
- if [ MATCH ^($(prefix)) : $(specified-name) ]
- {
- prefix = ;
- }
- return $(prefix:E="")$(specified-name)$(suffix:E="") ;
-}
-
-
-# File targets with explicitly known location.
-#
-# The file path is determined as
-# * Value passed to the 'set-path' method, if any.
-# * For derived files, project's build dir, joined with components that
-# describe action properties. If free properties are not equal to the
-# project's reference properties an element with the name of the main
-# target is added.
-# * For source files, project's source dir.
-#
-# The file suffix is determined as:
-# * The value passed to the 'suffix' method, if any.
-# * The suffix corresponding to the target's type.
-#
-class file-target : abstract-file-target
-{
- import "class" : new ;
- import common ;
- import errors ;
-
- rule __init__ (
- name exact ?
- : type ? # Optional type for this target.
- : project
- : action ?
- : path ?
- )
- {
- abstract-file-target.__init__ $(name) $(exact) : $(type) : $(project) :
- $(action) ;
-
- self.path = $(path) ;
- }
-
- rule clone-with-different-type ( new-type )
- {
- return [ new file-target $(self.name) exact : $(new-type) :
- $(self.project) : $(self.action) : $(self.path) ] ;
- }
-
- rule actualize-location ( target )
- {
- if $(self.action)
- {
- # This is a derived file.
- local path = [ path ] ;
- LOCATE on $(target) = $(path) ;
-
- # Make sure the path exists.
- DEPENDS $(target) : $(path) ;
- common.MkDir $(path) ;
-
- # It is possible that the target name includes a directory too, for
- # example when installing headers. Create that directory.
- if $(target:D)
- {
- local d = $(target:D) ;
- d = $(d:R=$(path)) ;
- DEPENDS $(target) : $(d) ;
- common.MkDir $(d) ;
- }
-
- # For a real file target, we create a fake target depending on the
- # real target. This allows us to run
- #
- # bjam hello.o
- #
- # without trying to guess the name of the real target. Note that the
- # target has no directory name and uses a special <e> grist.
- #
- # First, that means that "bjam hello.o" will build all known hello.o
- # targets. Second, the <e> grist makes sure this target will not be
- # confused with other targets, for example, if we have subdir 'test'
- # with target 'test' in it that includes a 'test.o' file, then the
- # target for directory will be just 'test' the target for test.o
- # will be <ptest/bin/gcc/debug>test.o and the target we create below
- # will be <e>test.o
- DEPENDS $(target:G=e) : $(target) ;
- # Allow bjam <path-to-file>/<file> to work. This will not catch all
- # possible ways to refer to the path (relative/absolute, extra ".",
- # various "..", but should help in obvious cases.
- DEPENDS $(target:G=e:R=$(path)) : $(target) ;
- }
- else
- {
- SEARCH on $(target) = [ path.native $(self.path) ] ;
- }
- }
-
- # Returns the directory for this target.
- #
- rule path ( )
- {
- if ! $(self.path)
- {
- if $(self.action)
- {
- local p = [ $(self.action).properties ] ;
- local path,relative-to-build-dir = [ $(p).target-path ] ;
- local path = $(path,relative-to-build-dir[1]) ;
- local relative-to-build-dir = $(path,relative-to-build-dir[2]) ;
-
- if $(relative-to-build-dir)
- {
- path = [ path.join [ $(self.project).build-dir ] $(path) ] ;
- }
-
- self.path = [ path.native $(path) ] ;
- }
- }
- return $(self.path) ;
- }
-}
-
-
-class notfile-target : abstract-file-target
-{
- rule __init__ ( name : project : action ? )
- {
- abstract-file-target.__init__ $(name) : : $(project) : $(action) ;
- }
-
- # Returns nothing to indicate that the target's path is not known.
- #
- rule path ( )
- {
- return ;
- }
-
- rule actualize-location ( target )
- {
- NOTFILE $(target) ;
- ALWAYS $(target) ;
- # TEMPORARY $(target) ;
- NOUPDATE $(target) ;
- }
-}
-
-
-# Class representing an action. Both 'targets' and 'sources' should list
-# instances of 'virtual-target'. Action name should name a rule with this
-# prototype:
-# rule action-name ( targets + : sources * : properties * )
-# Targets and sources are passed as actual Jam targets. The rule may not
-# establish additional dependency relationships.
-#
-class action
-{
- import "class" ;
- import errors ;
- import type ;
- import toolset ;
- import property-set ;
- import indirect ;
- import path ;
- import set : difference ;
-
- rule __init__ ( sources * : action-name + : property-set ? )
- {
- self.sources = $(sources) ;
-
- self.action-name = [ indirect.make-qualified $(action-name) ] ;
-
- if ! $(property-set)
- {
- property-set = [ property-set.empty ] ;
- }
-
- if ! [ class.is-instance $(property-set) ]
- {
- errors.error "Property set instance required" ;
- }
-
- self.properties = $(property-set) ;
- }
-
- rule add-targets ( targets * )
- {
- self.targets += $(targets) ;
- }
-
- rule replace-targets ( old-targets * : new-targets * )
- {
- self.targets = [ set.difference $(self.targets) : $(old-targets) ] ;
- self.targets += $(new-targets) ;
- }
-
- rule targets ( )
- {
- return $(self.targets) ;
- }
-
- rule sources ( )
- {
- return $(self.sources) ;
- }
-
- rule action-name ( )
- {
- return $(self.action-name) ;
- }
-
- rule properties ( )
- {
- return $(self.properties) ;
- }
-
- # Generates actual build instructions.
- #
- rule actualize ( )
- {
- if ! $(self.actualized)
- {
- self.actualized = true ;
-
- local ps = [ properties ] ;
- local properties = [ adjust-properties $(ps) ] ;
-
- local actual-targets ;
- for local i in [ targets ]
- {
- actual-targets += [ $(i).actualize ] ;
- }
-
- actualize-sources [ sources ] : $(properties) ;
-
- DEPENDS $(actual-targets) : $(self.actual-sources)
- $(self.dependency-only-sources) ;
-
- # This works around a bug with -j and actions that
- # produce multiple target, where:
- # - dependency on the first output is found, and
- # the action is started
- # - dependency on the second output is found, and
- # bjam noticed that command is already running
- # - instead of waiting for the command, dependents
- # of the second targets are immediately updated.
- if $(actual-targets[2])
- {
- INCLUDES $(actual-targets) : $(actual-targets) ;
- }
-
- # Action name can include additional argument to rule, which should
- # not be passed to 'set-target-variables'
- toolset.set-target-variables
- [ indirect.get-rule $(self.action-name[1]) ] $(actual-targets)
- : $(properties) ;
-
- # Reflect ourselves in a variable for the target. This allows
- # looking up additional info for the action given the raw target.
- # For example to debug or output action information from action
- # rules.
- .action on $(actual-targets) = $(__name__) ;
-
- indirect.call $(self.action-name) $(actual-targets)
- : $(self.actual-sources) : [ $(properties).raw ] ;
-
- # Since we set up the creating action here, we set up the action for
- # cleaning up as well.
- common.Clean clean-all : $(actual-targets) ;
- }
- }
-
- # Helper for 'actualize-sources'. For each passed source, actualizes it with
- # the appropriate scanner. Returns the actualized virtual targets.
- #
- rule actualize-source-type ( sources * : property-set )
- {
- local result = ;
- for local i in $(sources)
- {
- local scanner ;
- if [ $(i).type ]
- {
- scanner = [ type.get-scanner [ $(i).type ] : $(property-set) ] ;
- }
- result += [ $(i).actualize $(scanner) ] ;
- }
- return $(result) ;
- }
-
- # Creates actual Jam targets for sources. Initializes the following member
- # variables:
- # 'self.actual-sources' -- sources passed to the updating action.
- # 'self.dependency-only-sources' -- sources marked as dependencies, but
- # are not used otherwise.
- #
- # New values will be *appended* to the variables. They may be non-empty if
- # caller wants it.
- #
- rule actualize-sources ( sources * : property-set )
- {
- local dependencies = [ $(self.properties).get <dependency> ] ;
-
- self.dependency-only-sources +=
- [ actualize-source-type $(dependencies) : $(property-set) ] ;
- self.actual-sources +=
- [ actualize-source-type $(sources) : $(property-set) ] ;
-
- # This is used to help bjam find dependencies in generated headers and
- # other main targets, e.g. in:
- #
- # make a.h : ....... ;
- # exe hello : hello.cpp : <implicit-dependency>a.h ;
- #
- # For bjam to find the dependency the generated target must be
- # actualized (i.e. have its Jam target constructed). In the above case,
- # if we are building just hello ("bjam hello"), 'a.h' will not be
- # actualized unless we do it here.
- local implicit = [ $(self.properties).get <implicit-dependency> ] ;
- for local i in $(implicit)
- {
- $(i:G=).actualize ;
- }
- }
-
- # Determines real properties when trying to build with 'properties'. This is
- # the last chance to fix properties, for example to adjust includes to get
- # generated headers correctly. Default implementation simply returns its
- # argument.
- #
- rule adjust-properties ( property-set )
- {
- return $(property-set) ;
- }
-}
-
-
-# Action class which does nothing --- it produces the targets with specific
-# properties out of nowhere. It is needed to distinguish virtual targets with
-# different properties that are known to exist and have no actions which create
-# them.
-#
-class null-action : action
-{
- rule __init__ ( property-set ? )
- {
- action.__init__ : .no-action : $(property-set) ;
- }
-
- rule actualize ( )
- {
- if ! $(self.actualized)
- {
- self.actualized = true ;
- for local i in [ targets ]
- {
- $(i).actualize ;
- }
- }
- }
-}
-
-
-# Class which acts exactly like 'action', except that its sources are not
-# scanned for dependencies.
-#
-class non-scanning-action : action
-{
- rule __init__ ( sources * : action-name + : property-set ? )
- {
- action.__init__ $(sources) : $(action-name) : $(property-set) ;
- }
-
- rule actualize-source-type ( sources * : property-set )
- {
- local result ;
- for local i in $(sources)
- {
- result += [ $(i).actualize ] ;
- }
- return $(result) ;
- }
-}
-
-
-# Creates a virtual target with an appropriate name and type from 'file'. If a
-# target with that name in that project already exists, returns that already
-# created target.
-#
-# FIXME: a more correct way would be to compute the path to the file, based on
-# name and source location for the project, and use that path to determine if
-# the target has already been created. This logic should be shared with how we
-# usually find targets identified by a specific target id. It should also be
-# updated to work correctly when the file is specified using both relative and
-# absolute paths.
-#
-# TODO: passing a project with all virtual targets is starting to be annoying.
-#
-rule from-file ( file : file-loc : project )
-{
- import type ; # Had to do this here to break a circular dependency.
-
- # Check whether we already created a target corresponding to this file.
- local path = [ path.root [ path.root $(file) $(file-loc) ] [ path.pwd ] ] ;
-
- if $(.files.$(path))
- {
- return $(.files.$(path)) ;
- }
- else
- {
- local name = [ path.make $(file) ] ;
- local type = [ type.type $(file) ] ;
- local result ;
-
- result = [ new file-target $(file) : $(type) : $(project) : :
- $(file-loc) ] ;
-
- .files.$(path) = $(result) ;
- return $(result) ;
- }
-}
-
-
-# Registers a new virtual target. Checks if there is already a registered target
-# with the same name, type, project and subvariant properties as well as the
-# same sources and equal action. If such target is found it is returned and a
-# new 'target' is not registered. Otherwise, 'target' is registered and
-# returned.
-#
-rule register ( target )
-{
- local signature = [ sequence.join
- [ $(target).path ] [ $(target).name ] : - ] ;
-
- local result ;
- for local t in $(.cache.$(signature))
- {
- local a1 = [ $(t).action ] ;
- local a2 = [ $(target).action ] ;
-
- if ! $(result)
- {
- if ! $(a1) && ! $(a2)
- {
- result = $(t) ;
- }
- else
- {
- if $(a1) && $(a2) &&
- ( [ $(a1).action-name ] = [ $(a2).action-name ] ) &&
- ( [ $(a1).sources ] = [ $(a2).sources ] )
- {
- local ps1 = [ $(a1).properties ] ;
- local ps2 = [ $(a2).properties ] ;
- local p1 = [ $(ps1).base ] [ $(ps1).free ] [ set.difference
- [ $(ps1).dependency ] : [ $(ps1).incidental ] ] ;
- local p2 = [ $(ps2).base ] [ $(ps2).free ] [ set.difference
- [ $(ps2).dependency ] : [ $(ps2).incidental ] ] ;
- if $(p1) = $(p2)
- {
- result = $(t) ;
- }
- }
- }
- }
- }
-
- if ! $(result)
- {
- .cache.$(signature) += $(target) ;
- result = $(target) ;
- }
-
- .recent-targets += $(result) ;
- .all-targets += $(result) ;
-
- return $(result) ;
-}
-
-
-# Each target returned by 'register' is added to the .recent-targets list,
-# returned by this function. This allows us to find all virtual targets created
-# when building a specific main target, even those constructed only as
-# intermediate targets.
-#
-rule recent-targets ( )
-{
- return $(.recent-targets) ;
-}
-
-
-rule clear-recent-targets ( )
-{
- .recent-targets = ;
-}
-
-
-# Returns all virtual targets ever created.
-#
-rule all-targets ( )
-{
- return $(.all-targets) ;
-}
-
-
-# Returns all targets from 'targets' with types equal to 'type' or derived from
-# it.
-#
-rule select-by-type ( type : targets * )
-{
- local result ;
- for local t in $(targets)
- {
- if [ type.is-subtype [ $(t).type ] $(type) ]
- {
- result += $(t) ;
- }
- }
- return $(result) ;
-}
-
-
-rule register-actual-name ( actual-name : virtual-target )
-{
- if $(.actual.$(actual-name))
- {
- local cs1 = [ $(.actual.$(actual-name)).creating-subvariant ] ;
- local cs2 = [ $(virtual-target).creating-subvariant ] ;
- local cmt1 = [ $(cs1).main-target ] ;
- local cmt2 = [ $(cs2).main-target ] ;
-
- local action1 = [ $(.actual.$(actual-name)).action ] ;
- local action2 = [ $(virtual-target).action ] ;
- local properties-added ;
- local properties-removed ;
- if $(action1) && $(action2)
- {
- local p1 = [ $(action1).properties ] ;
- p1 = [ $(p1).raw ] ;
- local p2 = [ $(action2).properties ] ;
- p2 = [ $(p2).raw ] ;
- properties-removed = [ set.difference $(p1) : $(p2) ] ;
- properties-removed ?= "none" ;
- properties-added = [ set.difference $(p2) : $(p1) ] ;
- properties-added ?= "none" ;
- }
- errors.error "Duplicate name of actual target:" $(actual-name)
- : "previous virtual target" [ $(.actual.$(actual-name)).str ]
- : "created from" [ $(cmt1).full-name ]
- : "another virtual target" [ $(virtual-target).str ]
- : "created from" [ $(cmt2).full-name ]
- : "added properties:" $(properties-added)
- : "removed properties:" $(properties-removed) ;
- }
- else
- {
- .actual.$(actual-name) = $(virtual-target) ;
- }
-}
-
-
-# Traverses the dependency graph of 'target' and return all targets that will be
-# created before this one is created. If the root of some dependency graph is
-# found during traversal, it is either included or not, depending on the
-# 'include-roots' value. In either case traversal stops at root targets, i.e.
-# root target sources are not traversed.
-#
-rule traverse ( target : include-roots ? : include-sources ? )
-{
- local result ;
- if [ $(target).action ]
- {
- local action = [ $(target).action ] ;
- # This includes the 'target' as well.
- result += [ $(action).targets ] ;
-
- for local t in [ $(action).sources ]
- {
- if ! [ $(t).root ]
- {
- result += [ traverse $(t) : $(include-roots) : $(include-sources) ] ;
- }
- else if $(include-roots)
- {
- result += $(t) ;
- }
- }
- }
- else if $(include-sources)
- {
- result = $(target) ;
- }
- return $(result) ;
-}
-
-
-# Takes an 'action' instance and creates a new instance of it and all targets
-# produced by the action. The rule-name and properties are set to
-# 'new-rule-name' and 'new-properties', if those are specified. Returns the
-# cloned action.
-#
-rule clone-action ( action : new-project : new-action-name ? : new-properties ? )
-{
- if ! $(new-action-name)
- {
- new-action-name = [ $(action).action-name ] ;
- }
- if ! $(new-properties)
- {
- new-properties = [ $(action).properties ] ;
- }
-
- local action-class = [ modules.peek $(action) : __class__ ] ;
- local cloned-action = [ class.new $(action-class)
- [ $(action).sources ] : $(new-action-name) : $(new-properties) ] ;
-
- local cloned-targets ;
- for local target in [ $(action).targets ]
- {
- local n = [ $(target).name ] ;
- # Do not modify produced target names.
- local cloned-target = [ class.new file-target $(n) exact :
- [ $(target).type ] : $(new-project) : $(cloned-action) ] ;
- local d = [ $(target).dependencies ] ;
- if $(d)
- {
- $(cloned-target).depends $(d) ;
- }
- $(cloned-target).root [ $(target).root ] ;
- $(cloned-target).creating-subvariant [ $(target).creating-subvariant ] ;
-
- cloned-targets += $(cloned-target) ;
- }
-
- return $(cloned-action) ;
-}
-
-
-class subvariant
-{
- import sequence ;
- import type ;
-
- rule __init__ ( main-target # The instance of main-target class.
- : property-set # Properties requested for this target.
- : sources *
- : build-properties # Actually used properties.
- : sources-usage-requirements # Properties propagated from sources.
- : created-targets * ) # Top-level created targets.
- {
- self.main-target = $(main-target) ;
- self.properties = $(property-set) ;
- self.sources = $(sources) ;
- self.build-properties = $(build-properties) ;
- self.sources-usage-requirements = $(sources-usage-requirements) ;
- self.created-targets = $(created-targets) ;
-
- # Pre-compose a list of other dependency graphs this one depends on.
- local deps = [ $(build-properties).get <implicit-dependency> ] ;
- for local d in $(deps)
- {
- self.other-dg += [ $(d:G=).creating-subvariant ] ;
- }
-
- self.other-dg = [ sequence.unique $(self.other-dg) ] ;
- }
-
- rule main-target ( )
- {
- return $(self.main-target) ;
- }
-
- rule created-targets ( )
- {
- return $(self.created-targets) ;
- }
-
- rule requested-properties ( )
- {
- return $(self.properties) ;
- }
-
- rule build-properties ( )
- {
- return $(self.build-properties) ;
- }
-
- rule sources-usage-requirements ( )
- {
- return $(self.sources-usage-requirements) ;
- }
-
- rule set-usage-requirements ( usage-requirements )
- {
- self.usage-requirements = $(usage-requirements) ;
- }
-
- rule usage-requirements ( )
- {
- return $(self.usage-requirements) ;
- }
-
- # Returns all targets referenced by this subvariant, either directly or
- # indirectly, and either as sources, or as dependency properties. Targets
- # referred to using the dependency property are returned as properties, not
- # targets.
- #
- rule all-referenced-targets ( theset )
- {
- # Find directly referenced targets.
- local deps = [ $(self.build-properties).dependency ] ;
- local all-targets = $(self.sources) $(deps) ;
-
- # Find other subvariants.
- local r ;
- for local t in $(all-targets)
- {
- if ! [ $(theset).contains $(t) ]
- {
- $(theset).add $(t) ;
- r += [ $(t:G=).creating-subvariant ] ;
- }
- }
- r = [ sequence.unique $(r) ] ;
- for local s in $(r)
- {
- if $(s) != $(__name__)
- {
- $(s).all-referenced-targets $(theset) ;
- }
- }
- }
-
- # Returns the properties specifying implicit include paths to generated
- # headers. This traverses all targets in this subvariant and subvariants
- # referred by <implcit-dependecy> properties. For all targets of type
- # 'target-type' (or for all targets, if 'target-type' is not specified), the
- # result will contain <$(feature)>path-to-that-target.
- #
- rule implicit-includes ( feature : target-type ? )
- {
- local key = ii$(feature)-$(target-type:E="") ;
- if ! $($(key))-is-not-empty
- {
- local target-paths = [ all-target-directories $(target-type) ] ;
- target-paths = [ sequence.unique $(target-paths) ] ;
- local result = $(target-paths:G=$(feature)) ;
- if ! $(result)
- {
- result = "" ;
- }
- $(key) = $(result) ;
- }
- if $($(key)) = ""
- {
- return ;
- }
- else
- {
- return $($(key)) ;
- }
- }
-
- rule all-target-directories ( target-type ? )
- {
- if ! $(self.target-directories)
- {
- compute-target-directories $(target-type) ;
- }
- return $(self.target-directories) ;
- }
-
- rule compute-target-directories ( target-type ? )
- {
- local result ;
- for local t in $(self.created-targets)
- {
- # Skip targets of the wrong type.
- if ! $(target-type) ||
- [ type.is-derived [ $(t).type ] $(target-type) ]
- {
- result = [ sequence.merge $(result) : [ $(t).path ] ] ;
- }
- }
- for local d in $(self.other-dg)
- {
- result += [ $(d).all-target-directories $(target-type) ] ;
- }
- self.target-directories = $(result) ;
- }
-}