|
|
@@ -1,1166 +0,0 @@
|
|
|
-# (C) Copyright David Abrahams and Carlos Pinto Coelho 2001. 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.
|
|
|
-#
|
|
|
-# Jamrules file by David Abrahams (abrahams@mediaone.net) and Carlos Pinto
|
|
|
-# Coelho (cfspc@altrabroadband.com).
|
|
|
-
|
|
|
-# Notes on the design of the system:
|
|
|
-#
|
|
|
-# This system is designed to support building the "same" targets with multiple
|
|
|
-# build tool suites (e.g. msvc, gcc,...) and build variants (e.g. debug,
|
|
|
-# release...). Although it currently varies across two dimensions, it should
|
|
|
-# trivially support extension to three or more, e.g. in case of cross-platform
|
|
|
-# builds. The word "same" is written in quotes above because internally,
|
|
|
-# separate targets are generated for each unique toolset/build-variant
|
|
|
-# combination.
|
|
|
-#
|
|
|
-# Specifics of build tool suites are specified in files with names of the form
|
|
|
-# "<name>-tools.jam", where <name> is the name used to identify the tool suite.
|
|
|
-
|
|
|
-# Workarounds for Jam limitations:
|
|
|
-#
|
|
|
-# 1. Jam supports something like the setting of attributes on targets using the
|
|
|
-# syntax:
|
|
|
-# <name> on <target> = <expression>
|
|
|
-#
|
|
|
-# This facility is used to control build actions for individual targets
|
|
|
-# (target-specific variables take precedence over global ones when build
|
|
|
-# actions # are executed). An obvious approach would be to use target
|
|
|
-# attributes to hold # properties of build tools (e.g. where to find the
|
|
|
-# standard includes). # Unfortunately, although you can write target
|
|
|
-# attributes, there is no way to # read them. Instead, we take advantage of
|
|
|
-# two properties of Jam:
|
|
|
-#
|
|
|
-# a. A variable name can be formed by evaluating an expression. For example,
|
|
|
-# the following rule, appends FOOBAR to its first argument to form the
|
|
|
-# name of a new variable, which is given the value "baz"
|
|
|
-#
|
|
|
-# rule X { $(1)FOOBAR = baz ; }
|
|
|
-#
|
|
|
-# b. Any character is allowed in a variable name. So, although they are
|
|
|
-# actually global variables, we can form names like <name>.c++-flags thus:
|
|
|
-#
|
|
|
-# C++FLAGS = $($(1).c++-flags) # Get the c++-flags "attribute" from $(1)
|
|
|
-#
|
|
|
-# 2. There is no way to call a rule based on the value of a variable
|
|
|
-# other than by using a switch statement. Because that approach requires
|
|
|
-# intrusive changes to rules when the system is extended, we have avoided
|
|
|
-# it. Instead, we have taken advantage of two "features" of Jam:
|
|
|
-#
|
|
|
-# a. The name of a file to be included can be computed from an
|
|
|
-# expression. For example, the following includes a file whose name is
|
|
|
-# formed by concatenating $(1) and "-tools.jam":
|
|
|
-#
|
|
|
-# include $(1)-tools.jam
|
|
|
-#
|
|
|
-# b. A rule can be redefined any number of times. Its latest definition is
|
|
|
-# the one invoked. For example, the following prints "#2".
|
|
|
-#
|
|
|
-# rule X { ECHO #1 ; }
|
|
|
-# rule X { ECHO #2 ; }
|
|
|
-# X ;
|
|
|
-#
|
|
|
-# Together, these facts allow us to select tool-suite-specific actions for
|
|
|
-# building specific target types by repeatedly redefining the generalized
|
|
|
-# build actions in the various <build-tools>-tools.jam files
|
|
|
-
|
|
|
-TOOLS ?= borland gcc metrowerks msvc ;
|
|
|
-
|
|
|
-# detect-build-tools <tools-name> : <detection-command>
|
|
|
-#
|
|
|
-# Declares a pseudotarget for the specified build tools which is built by
|
|
|
-# the given <detection-command>.
|
|
|
-#
|
|
|
-# Although not currently implemented, the plan is to make compilation of
|
|
|
-# tool-specific targets dependent on this pseudotarget. That way, we will never
|
|
|
-# even attempt to build targets for tools that don't exist.
|
|
|
-rule detect-build-tools
|
|
|
-{
|
|
|
- detection-command on $(<) = $($(<).bin-directory)$(>) ;
|
|
|
-}
|
|
|
-
|
|
|
-actions build-tools
|
|
|
-{
|
|
|
- $(detection-command)
|
|
|
-}
|
|
|
-
|
|
|
-rule library-file
|
|
|
-{
|
|
|
- LibraryFromObjects $(<) : [ Objects $(>) ] ;
|
|
|
-}
|
|
|
-
|
|
|
-rule executable-file
|
|
|
-{
|
|
|
- executable-from-objects $(<) : [ Objects $(>) ] ;
|
|
|
-}
|
|
|
-
|
|
|
-rule executable-from-objects
|
|
|
-{
|
|
|
- # make compiled sources a dependency of target
|
|
|
-
|
|
|
- type-DEPENDS exe : $(<) ;
|
|
|
- DEPENDS $(<) : $(>) ;
|
|
|
- MakeLocate $(<) : $(LOCATE_TARGET) ;
|
|
|
-
|
|
|
- Clean clean : $(<) ;
|
|
|
-
|
|
|
- Link $(<) : $(>) ;
|
|
|
-
|
|
|
- # Setting RUN_ALL causes all executable targets to be run.
|
|
|
- if $(RUN_ALL)
|
|
|
- {
|
|
|
- Run $(<) ;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-# A simple action to run an executable target
|
|
|
-actions Run
|
|
|
-{
|
|
|
- $(<)
|
|
|
-}
|
|
|
-
|
|
|
-# assert_equal a : b
|
|
|
-#
|
|
|
-# exits with an assertion failure if a != b
|
|
|
-rule assert_equal
|
|
|
-{
|
|
|
- # we can turn off assertions by putting the symbol NDEBUG in the global TEST
|
|
|
- # variable
|
|
|
- if ! ( NDEBUG in $(TEST) )
|
|
|
- {
|
|
|
- if $(<) != $(>)
|
|
|
- {
|
|
|
- EXIT "assertion failure: [" $(<) "] != [" $(>) "]" ;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-# bubble variable-name
|
|
|
-#
|
|
|
-# Helper function for sort, below
|
|
|
-# Removes the greatest element from $(variable-name) and returns it.
|
|
|
-rule bubble #
|
|
|
-{
|
|
|
- local result = ;
|
|
|
- local last = $($(<)[1]) ;
|
|
|
- for x in $($(<)[2-])
|
|
|
- {
|
|
|
- if $(last) <= $(x)
|
|
|
- {
|
|
|
- result += $(last) ;
|
|
|
- last = $(x) ;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- result += $(x) ;
|
|
|
- }
|
|
|
- }
|
|
|
- $(<) = $(result) ;
|
|
|
- return $(last) ;
|
|
|
-}
|
|
|
-
|
|
|
-# sort args
|
|
|
-#
|
|
|
-# return args sorted in lexicographic order.
|
|
|
-rule sort
|
|
|
-{
|
|
|
- local _all = $(<) ;
|
|
|
- local _result = ;
|
|
|
- local _count ;
|
|
|
- for _count in $(<)
|
|
|
- {
|
|
|
- _result = [ bubble _all ] $(_result) ;
|
|
|
- }
|
|
|
- return $(_result) ;
|
|
|
-}
|
|
|
-assert_equal [ sort 7 3 5 6 2 4 ] : 2 3 4 5 6 7 ;
|
|
|
-
|
|
|
-# min args
|
|
|
-#
|
|
|
-# return the lexicographic minimum element of args
|
|
|
-rule min
|
|
|
-{
|
|
|
- local result = ;
|
|
|
- local x ;
|
|
|
- for x in $(<)
|
|
|
- {
|
|
|
- if ! $(result) || ( $(x) < $(result) )
|
|
|
- {
|
|
|
- result = $(x) ;
|
|
|
- }
|
|
|
- }
|
|
|
- return $(result) ;
|
|
|
-}
|
|
|
-assert_equal [ min 7 3 5 6 2 4 ] : 2 ;
|
|
|
-
|
|
|
-# difference listB : listA
|
|
|
-# returns the elements of B that are not in A
|
|
|
-rule difference
|
|
|
-{
|
|
|
- local result = ;
|
|
|
- local element ;
|
|
|
- for element in $(<)
|
|
|
- {
|
|
|
- if ! ( $(element) in $(>) )
|
|
|
- {
|
|
|
- result += $(element) ;
|
|
|
- }
|
|
|
- }
|
|
|
- return $(result) ;
|
|
|
-}
|
|
|
-assert_equal [ difference 0 1 2 3 4 5 6 7 8 9 : 2 3 5 7 ] : 0 1 4 6 8 9 ;
|
|
|
-
|
|
|
-# replace list : old-value new-value
|
|
|
-#
|
|
|
-# returns list with occurrences of old-value replaced by new-value
|
|
|
-rule replace
|
|
|
-{
|
|
|
- local result = ;
|
|
|
- local x ;
|
|
|
- for x in $(<)
|
|
|
- {
|
|
|
- if $(x) = $(>[1])
|
|
|
- {
|
|
|
- result += $(>[2]) ;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- result += $(x) ;
|
|
|
- }
|
|
|
- }
|
|
|
- return $(result) ;
|
|
|
-}
|
|
|
-assert_equal [ replace 1 3 5 7 7 9 2 5 4 3 1 : 7 x ] : 1 3 5 x x 9 2 5 4 3 1 ;
|
|
|
-
|
|
|
-# select-ungristed list...
|
|
|
-#
|
|
|
-# Returns the elements of list that have no grist
|
|
|
-rule select-ungristed
|
|
|
-{
|
|
|
- local result x ;
|
|
|
- for x in $(<)
|
|
|
- {
|
|
|
- if ! $(x:G)
|
|
|
- {
|
|
|
- result += $(x) ;
|
|
|
- }
|
|
|
- }
|
|
|
- return $(result) ;
|
|
|
-}
|
|
|
-assert_equal [ select-ungristed <a>b c <d>e f ] : c f ;
|
|
|
-
|
|
|
-# Split a qualified property into 3 elements.
|
|
|
-#
|
|
|
-# Grammar description of qualified-property :
|
|
|
-# [[<toolset>]<variant>]property
|
|
|
-#
|
|
|
-# returns <toolset> <variant> property
|
|
|
-# missing <toolset> or <variant> are treated as <*>
|
|
|
-rule split-qualified-property
|
|
|
-{
|
|
|
- local grist1 = $(<:G) ;
|
|
|
- local ungrist1 = $(<:G=) ;
|
|
|
- local grist2 = $(ungrist1:G) ;
|
|
|
- local ungrist2 = $(ungrist1:G=) ;
|
|
|
- local grist3 = $(ungrist2:G) ;
|
|
|
- local ungrist3 = $(ungrist2:G=) ;
|
|
|
- if $(grist3)
|
|
|
- {
|
|
|
- return $(grist1) $(grist2) $(grist3)$(ungrist3) ;
|
|
|
- }
|
|
|
- else if $(grist2)
|
|
|
- {
|
|
|
- return <*> $(grist1) $(grist2)$(ungrist2) ;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- return <*> <*> $(<) ;
|
|
|
- }
|
|
|
-}
|
|
|
-assert_equal [ split-qualified-property <feature>value ]
|
|
|
- : <*> <*> <feature>value ;
|
|
|
-assert_equal [ split-qualified-property <variant><feature>value ]
|
|
|
- : <*> <variant> <feature>value ;
|
|
|
-assert_equal [ split-qualified-property <toolset><variant><feature>value ]
|
|
|
- : <toolset> <variant> <feature>value ;
|
|
|
-
|
|
|
-rule unique # list
|
|
|
-{
|
|
|
- local result = ;
|
|
|
- local f ;
|
|
|
- for f in $(<)
|
|
|
- {
|
|
|
- if ! $(f) in $(result)
|
|
|
- {
|
|
|
- result += $(f) ;
|
|
|
- }
|
|
|
- }
|
|
|
- return $(result) ;
|
|
|
-}
|
|
|
-
|
|
|
-assert_equal [ unique 0 1 2 3 1 7 6 6 4 5 ] : 0 1 2 3 7 6 4 5 ;
|
|
|
-
|
|
|
-# get-properties features : properties
|
|
|
-#
|
|
|
-# Given a list of gristed features and a list of properties, returns the
|
|
|
-# properties matching the given features.
|
|
|
-rule get-properties
|
|
|
-{
|
|
|
- local result = ;
|
|
|
- local property ;
|
|
|
- for property in $(>)
|
|
|
- {
|
|
|
- if $(property:G) in $(<)
|
|
|
- {
|
|
|
- result += $(property) ;
|
|
|
- }
|
|
|
- }
|
|
|
- return $(result) ;
|
|
|
-}
|
|
|
-assert_equal [ get-properties <foo> <bar> : <foo>bar <foo>baz <bar>fight <baz>niss ]
|
|
|
- : <foo>bar <foo>baz <bar>fight ;
|
|
|
-
|
|
|
-# get-values feature : properties
|
|
|
-#
|
|
|
-# Given a single gristed feature name and a list of properties, returns the
|
|
|
-# value(s) of that feature.
|
|
|
-rule get-values
|
|
|
-{
|
|
|
- if $(<[2])
|
|
|
- {
|
|
|
- EXIT "Error: Expecting a single gristed feature name for $1 in get-values, got" "$(<)" ;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- local _properties = [ get-properties $(<) : $(>) ] ;
|
|
|
- return $(_properties:G=) ;
|
|
|
- }
|
|
|
-}
|
|
|
-assert_equal [ get-values <foo> : <foo>bar <foo>baz <bar>fight <baz>niss ] : bar baz ;
|
|
|
-
|
|
|
-# normalize-properties properties
|
|
|
-#
|
|
|
-# Normalizes a set of (possibly qualified) properties by prepending <*> as many
|
|
|
-# times as neccessary to ensure that each property has at least 3 gristed elements.
|
|
|
-rule normalize-properties
|
|
|
-{
|
|
|
- local property ;
|
|
|
- local result ;
|
|
|
- for property in $(<)
|
|
|
- {
|
|
|
- result += [ join [ split-qualified-property $(property) ] ] ;
|
|
|
- }
|
|
|
- return $(result) ;
|
|
|
-}
|
|
|
-assert_equal [ normalize-properties <a>b <c><d>e <f><g><h>i ] :
|
|
|
- <*><*><a>b <*><c><d>e <f><g><h>i ;
|
|
|
-
|
|
|
-# intersection set1 : set2
|
|
|
-#
|
|
|
-# Removes from set1 any items which don't appear in set2 and returns the result.
|
|
|
-rule intersection
|
|
|
-{
|
|
|
- local result v ;
|
|
|
- for v in $(<)
|
|
|
- {
|
|
|
- if $(v) in $(>)
|
|
|
- {
|
|
|
- result += $(v) ;
|
|
|
- }
|
|
|
- }
|
|
|
- return $(result) ;
|
|
|
-}
|
|
|
-assert_equal [ intersection 1 2 2 3 3 4 5 6 7 : 5 1 3 7 3 9 11 ] : 1 3 3 5 7 ;
|
|
|
-
|
|
|
-# subset sub : super
|
|
|
-#
|
|
|
-# Returns true iff sub is a subset of super, empty otherwise
|
|
|
-rule is-subset
|
|
|
-{
|
|
|
- if [ intersection $(<) : $(>) ] = $(<)
|
|
|
- {
|
|
|
- return true ;
|
|
|
- }
|
|
|
-}
|
|
|
-assert_equal [ is-subset a b c : c a b d ] : true ;
|
|
|
-assert_equal [ is-subset a b z : c a b d ] : ;
|
|
|
-
|
|
|
-# distribute-feature <feature>value1[/value2...]
|
|
|
-#
|
|
|
-# Distribute the given feature across the slash-separated set of values, i.e.
|
|
|
-# returns <feature>value1[ <feature>/value2...]
|
|
|
-rule distribute-feature
|
|
|
-{
|
|
|
- local g = $(<:G) ;
|
|
|
- local result = [ split-path $(<:G=) ] ;
|
|
|
- return $(g)$(result) ;
|
|
|
-}
|
|
|
-assert_equal [ distribute-feature <feature>value1 ] : <feature>value1 ;
|
|
|
-assert_equal [ distribute-feature <feature>value1/value2 ] : <feature>value1 <feature>value2 ;
|
|
|
-assert_equal [ distribute-feature <feature>value1/value2/value3 ] : <feature>value1 <feature>value2 <feature>value3 ;
|
|
|
-
|
|
|
-# set-insert variable-name : value... ;
|
|
|
-#
|
|
|
-# Appends the given values to the list designated by variable-name if they are
|
|
|
-# not already present.
|
|
|
-rule set-insert
|
|
|
-{
|
|
|
- local v ;
|
|
|
- for v in $(>)
|
|
|
- {
|
|
|
- if ! ( $(v) in $($(<)) )
|
|
|
- {
|
|
|
- $(<) += $(v) ;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-if ! ( NDEBUG in $(TEST) )
|
|
|
-{
|
|
|
- gTEST_SET = 1 2 3 ;
|
|
|
- set-insert gTEST_SET : 2 ;
|
|
|
- assert_equal $(gTEST_SET) : 1 2 3 ;
|
|
|
- set-insert gTEST_SET : 0 ;
|
|
|
- assert_equal $(gTEST_SET) : 1 2 3 0 ;
|
|
|
-}
|
|
|
-
|
|
|
-# equal-sets set1 : set2
|
|
|
-#
|
|
|
-# Returns true iff set1 contains the same elements as set2.
|
|
|
-# Not sensitive to the same element appearing multiple times
|
|
|
-rule equal-sets
|
|
|
-{
|
|
|
- if ( ! [ difference $(<) : $(>) ] ) && ( ! [ difference $(>) : $(<) ] )
|
|
|
- {
|
|
|
- return true ;
|
|
|
- }
|
|
|
-}
|
|
|
-assert_equal [ equal-sets 1 2 3 : 3 2 2 1 ] : true ;
|
|
|
-assert_equal [ equal-sets 1 2 3 3 : 3 2 2 1 ] : true ;
|
|
|
-assert_equal [ equal-sets 1 2 3 3 4 : 3 2 2 1 ] : ;
|
|
|
-
|
|
|
-# flags tools-name variable-name condition [: value(s)]
|
|
|
-#
|
|
|
-# Declare command-line settings for a given toolset.
|
|
|
-# toolset: the name of the toolset
|
|
|
-# variable-name: the name of a global variable which can be used to carry
|
|
|
-# information to a command-line
|
|
|
-# condition: one of the following:
|
|
|
-# 1. zero or more <simple-feature>value[/<simple-feature>value...]
|
|
|
-# 2. <free-feature>
|
|
|
-# values: non-empty in case 1 above, empty in case 2.
|
|
|
-#
|
|
|
-# Semantics only affect targets built with the specified toolset, and depend on
|
|
|
-# the form of condition:
|
|
|
-#
|
|
|
-# 1. For targets whose build-properties are a superset of any element of condition
|
|
|
-# (or, when condition is empty, for all targets), values will be appended to
|
|
|
-# $(variable-name).
|
|
|
-#
|
|
|
-# 2. for each free property of a built target whose feature is specified by
|
|
|
-# condition, the property's value will be appended to $(variable-name)
|
|
|
-#
|
|
|
-# In either case, the variable will be set "on" the target so it may be used in
|
|
|
-# the build actions.
|
|
|
-rule flags
|
|
|
-{
|
|
|
- local toolset = $(<[1]) ;
|
|
|
- local variable = $(<[2]) ;
|
|
|
- local condition = $(<[3-]) ;
|
|
|
-
|
|
|
- # record the names of all variables used so they can be set on targets
|
|
|
- if ! ( $(variable) in $(gTARGET_VARIABLES) )
|
|
|
- {
|
|
|
- gTARGET_VARIABLES += $(variable) ;
|
|
|
- $(variable) = ;
|
|
|
- }
|
|
|
-
|
|
|
- if $(>)
|
|
|
- {
|
|
|
- # values is non-empty: specifying simple properties
|
|
|
- if ! $(condition)
|
|
|
- {
|
|
|
- $(variable) += $(>) ; # condition is empty: unconditionally add values
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- local found = ;
|
|
|
-
|
|
|
- local property_set ;
|
|
|
- for property_set in $(condition)
|
|
|
- {
|
|
|
- local properties = [ split-path $(property_set) ] ;
|
|
|
-
|
|
|
- # Add each feature to the set of features relevant to the toolset
|
|
|
- gRELEVANT_FEATURES($(toolset)) += $(properties:G) ;
|
|
|
-
|
|
|
- # if this property_set is a subset of the current build-properties
|
|
|
- if ( ! $(found) ) && [ is-subset $(properties) : $(gBUILD_PROPERTIES) ]
|
|
|
- {
|
|
|
- found = true ;
|
|
|
- $(variable) += $(>) ;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
-
|
|
|
- if $(condition[2])
|
|
|
- || $(condition[1]:G=)
|
|
|
- || ! ( $(condition[1]) in $(gFREE_FEATURES) )
|
|
|
- {
|
|
|
- EXIT "Error: rule flags expects only a single free feature"
|
|
|
- " name when no values are supplied. "
|
|
|
- "got (" $(condition) ") instead." ;
|
|
|
- }
|
|
|
- # Add the values of the free feature specified by condition to $(variable)
|
|
|
- $(variable) += [ get-values $(condition) : $(gBUILD_PROPERTIES) ] ;
|
|
|
- # Record that the feature is relevant to the toolset
|
|
|
- gRELEVANT_FEATURES($(toolset)) += $(condition) ;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-# include-tools toolset
|
|
|
-#
|
|
|
-# Unconditionally process the specification file for the given toolset. It is
|
|
|
-# neccessary to do this for each target built with that toolset, since the
|
|
|
-# toolset will invoke the flags rule to set global variables based on the build
|
|
|
-# properties of the target.
|
|
|
-rule include-tools
|
|
|
-{
|
|
|
- gCURRENT_TOOLSET = $(<) ;
|
|
|
-
|
|
|
- gTARGET_VARIABLES = ;
|
|
|
- gRELEVANT_FEATURES($(<)) = ; # clear relevant feature set
|
|
|
-
|
|
|
- include $(TOOLSET_DIR)$(SLASH)$(<)-tools.jam ;
|
|
|
-
|
|
|
- # Always maintain the list of relevant features as unique
|
|
|
- gRELEVANT_FEATURES($(<)) = [ unique $(gRELEVANT_FEATURES($(<))) ] ;
|
|
|
-
|
|
|
- gINCLUDED($(TOOLSET_DIR)$(SLASH)$(<)-tools.jam) = true ;
|
|
|
-}
|
|
|
-
|
|
|
-# relevant-features toolset
|
|
|
-#
|
|
|
-# Returns the set of unique features relevant to the given toolset; includes the
|
|
|
-# toolset description file as a side-effect if neccessary.
|
|
|
-rule relevant-features # name
|
|
|
-{
|
|
|
- if ! $(gRELEVANT_FEATURES($(<)))
|
|
|
- {
|
|
|
- include-tools $(<) ;
|
|
|
- }
|
|
|
- return $(gRELEVANT_FEATURES($(<))) ;
|
|
|
-}
|
|
|
-
|
|
|
-rule assert_equal_sets
|
|
|
-{
|
|
|
- # we can turn off assertions by putting the symbol NDEBUG in the global TEST
|
|
|
- # variable
|
|
|
- if ! ( NDEBUG in $(TEST) )
|
|
|
- {
|
|
|
- if ! [ equal-sets $(<) : $(>) ]
|
|
|
- {
|
|
|
- EXIT "assertion failure: [" $(<) "] !=(set) [" $(>) "]" ;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-{
|
|
|
- assert_equal [ sort $(<) ] : [ sort $(>) ] ;
|
|
|
-}
|
|
|
-
|
|
|
-# select-properties toolset variant target-name : qualified-properties...
|
|
|
-#
|
|
|
-# Returns
|
|
|
-rule select-properties
|
|
|
-{
|
|
|
- local relevant_features = [ relevant-features $(<[1]) ] ;
|
|
|
- local normalized = [ normalize-properties $(>) ] ;
|
|
|
-
|
|
|
- # Classify properties by the specificity of their qualification.
|
|
|
- # First, grab those that apply to this toolset, or all toolsets
|
|
|
- local this_toolset = [ get-values <$(<[1])> : $(normalized) ] ;
|
|
|
- local all_toolsets = [ get-values <*> : $(normalized) ] ;
|
|
|
-
|
|
|
- local 0-stars = [ get-values <$(<[2])> : $(this_toolset) ] ;
|
|
|
- local 1-stars = [ get-values <*> : $(this_toolset) ] [ get-values <$(<[2])> : $(all_toolsets) ] ;
|
|
|
- local 2-stars = [ get-values <*> : $(all_toolsets) ] ;
|
|
|
-
|
|
|
- # Select feature names from the features relevant to the toolset.
|
|
|
- local features = [ intersection $(relevant_features)
|
|
|
- : $(0-stars:G) $(1-stars:G) $(2-stars:G) ] ;
|
|
|
-
|
|
|
- local result f ;
|
|
|
- for f in $(features)
|
|
|
- {
|
|
|
- local is_free = [ intersection $(f) : $(gFREE_FEATURES) ] ;
|
|
|
-
|
|
|
- # Go through the $(n-stars) lists from most- to least- specific;
|
|
|
- # collect the best set of values of a simple feature, and /all/
|
|
|
- # values of a free feature.
|
|
|
- local r n ;
|
|
|
- for n in 0 1 2
|
|
|
- {
|
|
|
- if ! $(r) || $(is_free)
|
|
|
- {
|
|
|
- r += [ get-values $(f) : $($(n)-stars) ] ;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- r = [ unique $(r) ] ;
|
|
|
- if $(r[2]) && ! $(is_free) # Check for conflicting simple-feature requests
|
|
|
- {
|
|
|
- EXIT "Error: Ambiguous properties requested for"
|
|
|
- $(<[3]) <$(<[1])><$(<[2])> ":" $(f)$(r) ;
|
|
|
- }
|
|
|
- result += $(f)$(r) ;
|
|
|
- }
|
|
|
- return $(result) ;
|
|
|
-}
|
|
|
-# get toolset features
|
|
|
-include $(TOP)$(SLASH)features.jam ;
|
|
|
-if ! ( NDEBUG in $(TEST) )
|
|
|
-{
|
|
|
- TEST_PROPERTIES = <inlining>off <define>FOO <*><release><inlining>on
|
|
|
- <debug><define>DEBUG <msvc><release><foo>bar
|
|
|
- <gcc><*><inlining>on
|
|
|
- <msvc><*><foo>baz
|
|
|
- <msvc><release><optimization>speed
|
|
|
- <msvc><*><optimization>off
|
|
|
- <*><debug><optimization>off
|
|
|
- ;
|
|
|
- assert_equal_sets [ select-properties gcc debug my-target : $(TEST_PROPERTIES) ]
|
|
|
- : <define>FOO <define>DEBUG <inlining>on <optimization>off ;
|
|
|
-
|
|
|
- assert_equal_sets [ select-properties gcc release my-target : $(TEST_PROPERTIES) ]
|
|
|
- : <define>FOO <inlining>on ;
|
|
|
-
|
|
|
- assert_equal_sets [ select-properties msvc debug my-target : $(TEST_PROPERTIES) ]
|
|
|
- : <define>FOO <define>DEBUG <inlining>off <optimization>off ;
|
|
|
-
|
|
|
- assert_equal_sets [ select-properties msvc release my-target : $(TEST_PROPERTIES) ]
|
|
|
- : <define>FOO <inlining>on <optimization>speed ;
|
|
|
-}
|
|
|
-
|
|
|
-# ungrist-properties properties...
|
|
|
-#
|
|
|
-# Transforms a list of properties of the form:
|
|
|
-# <feature1>value1 [<feature2>value2... ]
|
|
|
-# into a list of the form:
|
|
|
-# feature1-value1 feature2-value2
|
|
|
-# suitable for use as directory path elements
|
|
|
-rule ungrist-properties
|
|
|
-{
|
|
|
- local property ;
|
|
|
- local result = ;
|
|
|
- for property in $(<)
|
|
|
- {
|
|
|
- local f = [ ungrist $(property:G) ] ;
|
|
|
- result += $(f)-$(property:G=) ;
|
|
|
- }
|
|
|
- return $(result) ;
|
|
|
-}
|
|
|
-if ! ( NDEBUG in $(TEST) )
|
|
|
-{
|
|
|
- feature TEST_FEATURE1 : a b ;
|
|
|
- feature TEST_FEATURE2 : c d ;
|
|
|
- assert_equal [ ungrist-properties <TEST_FEATURE1>a <TEST_FEATURE2>c ]
|
|
|
- : TEST_FEATURE1-a TEST_FEATURE2-c ;
|
|
|
-}
|
|
|
-
|
|
|
-# set-target-variables target
|
|
|
-#
|
|
|
-# attach global build tool settings to the given file-target, so that they can be
|
|
|
-# used in build actions.
|
|
|
-rule set-target-variables # file-target
|
|
|
-{
|
|
|
- local s ;
|
|
|
- for s in $(gTARGET_VARIABLES)
|
|
|
- {
|
|
|
- $(s) on $(<) = $($(s)) ;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-# fixup-path-properties properties...
|
|
|
-#
|
|
|
-# For free properties that have been declared with "PATH", add a relative path
|
|
|
-# prefix to the value as neccessary to locate the path relative to the current
|
|
|
-# subproject.
|
|
|
-rule fixup-path-properties
|
|
|
-{
|
|
|
- local path-properties = [ get-properties $(gPATH_FEATURES) : $(<) ] ;
|
|
|
- local non-path = [ difference $(<) : $(path-properties) ] ;
|
|
|
- if $(RELATIVE_SUBDIR) && ! $(path-properties:R)
|
|
|
- {
|
|
|
- path-properties = $(path-properties:R=$(RELATIVE_SUBDIR)) ;
|
|
|
- }
|
|
|
- return $(path-properties) $(non-path) ;
|
|
|
-}
|
|
|
-if ! ( NDEBUG in $(TEST) )
|
|
|
-{
|
|
|
- local RELATIVE_SUBDIR = foobar ;
|
|
|
- local gPATH_FEATURES = <include> ;
|
|
|
- assert_equal [ fixup-path-properties <a>b <include>.. <c>d ]
|
|
|
- : <include>foobar$(SLASH).. <a>b <c>d ;
|
|
|
-}
|
|
|
-
|
|
|
-# report-any-incompatible-properties requirements... : build-request... : target-name
|
|
|
-#
|
|
|
-# If any element of requirements has the same grist but a different ungristed
|
|
|
-# part as any element of build-request, exits with an error report about target-name
|
|
|
-rule report-any-incompatible-properties
|
|
|
-{
|
|
|
- local common_features = [ intersection $(<:G) : $(>:G) ] ;
|
|
|
- if ! [ equal-sets [ get-properties $(common_features) : $(<) ]
|
|
|
- : [ get-properties $(common_features) : $(>) ] ]
|
|
|
- {
|
|
|
- EXIT "Error:" "$(3):" "target requirements for the features {"
|
|
|
- $(common_features) "} conflict with requested build {" $(>) "}" ;
|
|
|
- }
|
|
|
-}
|
|
|
-if report-any-incompatible-properties in $(TEST)
|
|
|
-{
|
|
|
- report-any-incompatible-properties <foo>bar <baz>mumble : <b>c <foo>bar : my-target ;
|
|
|
- report-any-incompatible-properties <foo>bat <baz>mumble : <b>c <foo>bar : my-target ;
|
|
|
-}
|
|
|
-
|
|
|
-# multiply-property-sets [<feature>value1[/value2...] ]...
|
|
|
-#
|
|
|
-# Expands a set of (possibly multi-valued) properties into all the combinations
|
|
|
-# that include every feature in the set. Each combination is given as a path,
|
|
|
-# with the slash separating the properties, sorted in feature order.
|
|
|
-rule multiply-property-sets
|
|
|
-{
|
|
|
- local result p ;
|
|
|
- for p in [ sort $(<) ]
|
|
|
- {
|
|
|
- # expand any multi-valued simple features from the default build
|
|
|
- local multiple = [ distribute-feature $(p) ] ;
|
|
|
-
|
|
|
- # concatenation produces a product, so the tree branches for each
|
|
|
- # multi-valued simple feature.
|
|
|
- result = $(result)/$(multiple) ;
|
|
|
- result ?= $(multiple) ; # this trick allows us to get started
|
|
|
- }
|
|
|
- return $(result) ;
|
|
|
-}
|
|
|
-assert_equal [ multiply-property-sets <b>1 <a>2/3 <c>4/5 ]
|
|
|
- : <a>2/<b>1/<c>4 <a>2/<b>1/<c>5 <a>3/<b>1/<c>4 <a>3/<b>1/<c>5 ;
|
|
|
-
|
|
|
-# make-path-property-set-pairs base-path : common-properties : property-sets
|
|
|
-#
|
|
|
-# Returns a list of pairs where each odd-numbered element is a relative path
|
|
|
-# into which a configuration should be built, and each following
|
|
|
-# even-numbered element is a slash-separated property set describing the
|
|
|
-# properties of the target to be built.
|
|
|
-#
|
|
|
-# Each path returned is base-path extended by one of the ungristed property-sets
|
|
|
-# (or just the base-path if no property-sets are supplied). Each property set
|
|
|
-# returned is formed by extending common-properties with one of the property-sets.
|
|
|
-rule make-path-property-set-pairs
|
|
|
-{
|
|
|
- local result ;
|
|
|
- local s ;
|
|
|
- for s in $(3)
|
|
|
- {
|
|
|
- # Add the directory
|
|
|
- result += [ join-path $(<)
|
|
|
- [ ungrist-properties [ split-path $(s) ] ] ] ;
|
|
|
-
|
|
|
- # Add the complete set of properties (can't use join-path because of grist)
|
|
|
- result += [ join $(>) $(s) : $(SLASH) ] ;
|
|
|
- }
|
|
|
-
|
|
|
- if $(result)
|
|
|
- {
|
|
|
- return $(result) ;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- # if there were no overrides, just add the base variant and properties
|
|
|
- return $(<) [ join $(>) : $(SLASH) ] ;
|
|
|
- }
|
|
|
-}
|
|
|
-if ! ( NDEBUG in $(TEST) )
|
|
|
-{
|
|
|
- gUNGRISTED(<a>) = a ;
|
|
|
- gUNGRISTED(<c>) = c ;
|
|
|
- gUNGRISTED(<e>) = e ;
|
|
|
- gUNGRISTED(<g>) = g ;
|
|
|
- gUNGRISTED(<i>) = i ;
|
|
|
- assert_equal [ make-path-property-set-pairs foo$(SLASH)bar : <a>b <c>d : <e>f$(SLASH)<g>h <i>j ]
|
|
|
- : foo$(SLASH)bar$(SLASH)e-f$(SLASH)g-h <a>b$(SLASH)<c>d$(SLASH)<e>f$(SLASH)<g>h foo$(SLASH)bar$(SLASH)i-j <a>b$(SLASH)<c>d$(SLASH)<i>j ;
|
|
|
- assert_equal [ make-path-property-set-pairs foo$(SLASH)bar : <a>b <c>d : ]
|
|
|
- : foo$(SLASH)bar <a>b$(SLASH)<c>d ;
|
|
|
-}
|
|
|
-
|
|
|
-# expand-build-request
|
|
|
-# toolset variant target-name : requirements : build-request
|
|
|
-#
|
|
|
-# Returns a list of pairs (build-path, properties) for the given variant
|
|
|
-# build of the given target with the given toolset, and all subvariant builds
|
|
|
-# specified by build-request.
|
|
|
-rule expand-build-request
|
|
|
-{
|
|
|
- local toolset = $(<[1]) ;
|
|
|
- local variant = $(<[2]) ;
|
|
|
-
|
|
|
- # grab the requirements and BUILD-request relevant to this toolset and variant
|
|
|
- local requirements = [ select-properties $(toolset) $(variant) : $(>) ] ;
|
|
|
- local build-request = [ select-properties $(toolset) $(variant) : $(3) ] ;
|
|
|
-
|
|
|
- # Separate the free features (e.g. <define>, <undef>, <include>) from the others
|
|
|
- local free-properties = [ get-properties $(gFREE_FEATURES) : $(requirements) $(build-request) ] ;
|
|
|
- local requirements = [ difference $(requirements) : $(free-properties) ] ;
|
|
|
- local build-request = [ difference $(build-request) : $(free-properties) ] ;
|
|
|
-
|
|
|
- # Check for conflicts
|
|
|
- report-any-incompatible-properties $(requirements) : $(build-request) : $(<[3]) ;
|
|
|
-
|
|
|
- # Get the base variant for the toolset. Includes free features
|
|
|
- local base-properties = $(gBASE_PROPERTIES($(toolset),$(variant))) ;
|
|
|
-
|
|
|
- # Which properties will override settings in the base variant?
|
|
|
- local override-properties = [ unique $(requirements) $(build-request) ] ;
|
|
|
- override-properties = [ difference $(override-properties) : $(base-properties) ] ;
|
|
|
-
|
|
|
- # Which features, and thus properties, of the base variant are we keeping?
|
|
|
- local kept-features = [ difference $(base-properties:G) : $(override-properties:G) ] ;
|
|
|
- local kept-properties = [ get-properties $(kept-features) : $(base-properties) ] ;
|
|
|
-
|
|
|
- # Which features will pick up a default value because they are not in
|
|
|
- # the base variant or in the overrides?
|
|
|
- local relevant_features = [ relevant-features $(toolset) ] ;
|
|
|
- local defaulted-features = [ difference $(relevant_features)
|
|
|
- : $(override-properties:G) $(kept-features) ] ;
|
|
|
- local defaulted-properties = [ feature-default $(defaulted-features) ] ;
|
|
|
-
|
|
|
- # form override property sets of the form (property1[/property2...] )+,
|
|
|
- # sorted in feature order. These represent the properties of subvariants
|
|
|
- # that differ from the base variant
|
|
|
- local override-sets
|
|
|
- = [ multiply-property-sets $(override-properties) $(defaulted-properties) ] ;
|
|
|
-
|
|
|
- # return pairs (path, property-set) corresponding to each (sub)variant build
|
|
|
- # described.
|
|
|
- return [ make-path-property-set-pairs $(toolset)$(SLASH)$(variant)
|
|
|
- : $(kept-properties) [ fixup-path-properties $(free-properties) ]
|
|
|
- : $(override-sets) ] ;
|
|
|
-}
|
|
|
-
|
|
|
-# split-property-set property-set
|
|
|
-#
|
|
|
-# Used to peel apart path-separated property sets that may themselves
|
|
|
-# include paths. This arises most often when the <include> feature is used,
|
|
|
-# since its parameter is typically a path.
|
|
|
-#
|
|
|
-# The split properties are returned in reverse order
|
|
|
-rule split-property-set
|
|
|
-{
|
|
|
- local full-split = [ split-path $(<) ] ;
|
|
|
- local result x ;
|
|
|
- for x in $(full-split)
|
|
|
- {
|
|
|
- if $(x:G)
|
|
|
- {
|
|
|
- result = $(x) $(result) ;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- result = $(result[1])$(SLASH)$(x) $(result[2-]) ;
|
|
|
- }
|
|
|
- }
|
|
|
- return $(result) ;
|
|
|
-}
|
|
|
-assert_equal
|
|
|
- [ split-property-set <a>b$(SLASH)c$(SLASH)<d>e$(SLASH)<f>g$(SLASH)h$(SLASH)i ]
|
|
|
- : <f>g$(SLASH)h$(SLASH)i <d>e <a>b$(SLASH)c ;
|
|
|
-
|
|
|
-# declare-local-target name : sources : requirements : local-BUILD : target-type
|
|
|
-#
|
|
|
-# declares a subproject-local target of the given name and target-type. This is
|
|
|
-# all top-level rules which declare targets should eventually go through here.
|
|
|
-rule declare-local-target
|
|
|
-{
|
|
|
-
|
|
|
- # We grist the base target name here because we're referring the abstract
|
|
|
- # target which generates all of the actual builds. We need a way to
|
|
|
- # distinguish targets of the same name from different subprojects.
|
|
|
- local base-target = [ FGristFiles $(<) ] ;
|
|
|
-
|
|
|
- gTARGET_SOURCES($(base-target)) = $(2) ;
|
|
|
- gTARGET_REQUIREMENTS($(base-target)) = $(3) ;
|
|
|
- gTARGET_BUILD($(base-target)) = $(4) ;
|
|
|
- gTARGET_TYPE($(base-target)) = $(5) ;
|
|
|
-
|
|
|
- # Check to avoid infinite recursion when subprojects contain mutual
|
|
|
- # dependencies.
|
|
|
- if ! $(gCURRENTLY_DECLARING($(base-target)))
|
|
|
- {
|
|
|
- local gCURRENTLY_DECLARING($(base-target)) = true ;
|
|
|
- declare-target $(1) : $(2) : $(3) : $(4) : $(5) ;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-# directory-of files...
|
|
|
-#
|
|
|
-# Returns a list of the directories containing each element of files
|
|
|
-rule directory-of
|
|
|
-{
|
|
|
- local result d ;
|
|
|
- for d in $(<:D)
|
|
|
- {
|
|
|
- if $(d) = ""
|
|
|
- {
|
|
|
- result += $(DOT) ;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- result += $(d) ;
|
|
|
- }
|
|
|
- }
|
|
|
- return $(result) ;
|
|
|
-}
|
|
|
-assert_equal [ directory-of a$(SLASH)b c d$(SLASH)e$(SLASH)f ] : a . d$(SLASH)e ;
|
|
|
-
|
|
|
-# top-relative-tokens path
|
|
|
-#
|
|
|
-# Returns a list of path elements which form the relative path from TOP to path,
|
|
|
-# which is expected to be given relative to the current subproject.
|
|
|
-rule top-relative-tokens
|
|
|
-{
|
|
|
- return [ simplify-path-tokens $(SUBDIR_TOKENS) [ split-path $(<) ] ] ;
|
|
|
-}
|
|
|
-{
|
|
|
- local SUBDIR_TOKENS = a b c ;
|
|
|
- assert_equal [ top-relative-tokens ..$(SLASH)d$(SLASH)e ] : a b d e ;
|
|
|
-}
|
|
|
-
|
|
|
-# dependent-include target-path...
|
|
|
-#
|
|
|
-# For each target-path, ensure that the appropriate Jamfile has been
|
|
|
-# included. Used when a target declares its dependency on another target.
|
|
|
-
|
|
|
-rule dependent-include
|
|
|
-{
|
|
|
- local target ;
|
|
|
- for target in $(<)
|
|
|
- {
|
|
|
- # compute the path to the Jamfile containing target. This path must be
|
|
|
- # relative to the directory of Jam's invocation in order for the include
|
|
|
- # rule to find it.
|
|
|
-
|
|
|
- local jamfile-path
|
|
|
- = [ join-path
|
|
|
- [ simplify-path-tokens
|
|
|
- $(RELATIVE_SUBDIR_TOKENS) [ directory-of $(target) ] $(JAMFILE) ] ] ;
|
|
|
-
|
|
|
- if ! $(gINCLUDED($(jamfile-path)))
|
|
|
- {
|
|
|
- # protect variables from being permanently set by SubDir invocations
|
|
|
- # in included files.
|
|
|
- local SUBDIR SUBDIR_TOKENS SEARCH_SOURCE LOCATE_SOURCE LOCATE_TARGET ;
|
|
|
- local SOURCE_GRIST SUBDIRCCFLAGS SUBDIRC++FLAGS SUBDIRHDRS ;
|
|
|
- local RELATIVE_SUBDIR RELATIVE_SUBDIR_TOKENS ;
|
|
|
-
|
|
|
- # this stack allows us to avoid making dependee libraries part of
|
|
|
- # the "type" targets, e.g. all, exe, obj. See rule type-DEPENDS.
|
|
|
- local gIN_LIB_INCLUDE = 1 ;
|
|
|
-
|
|
|
- include $(jamfile-path) ;
|
|
|
- gINCLUDED($(jamfile-path)) = true ;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-# link-libraries dependent : libs... : target-path
|
|
|
-#
|
|
|
-# Used to make the given dependent target depend on the file result of building
|
|
|
-# the given libs. The 3rd argument should specify the directory path relative to
|
|
|
-# the subproject directory where the appropriate build is located.
|
|
|
-rule link-libraries
|
|
|
-{
|
|
|
- local lib-path ;
|
|
|
- for lib-path in $(>)
|
|
|
- {
|
|
|
- local new-subdir = TOP [ top-relative-tokens [ directory-of $(lib-path) ] ] ;
|
|
|
-
|
|
|
- # protect global variables from being permanently set by SubDir
|
|
|
- local SUBDIR SUBDIR_TOKENS SEARCH_SOURCE LOCATE_SOURCE LOCATE_TARGET ;
|
|
|
- local SOURCE_GRIST SUBDIRCCFLAGS SUBDIRC++FLAGS SUBDIRHDRS ;
|
|
|
- local RELATIVE_SUBDIR RELATIVE_SUBDIR_TOKENS ;
|
|
|
-
|
|
|
- # Enter the dependee subproject
|
|
|
- SubDir $(new-subdir) ;
|
|
|
-
|
|
|
- local target = [ FGristFiles $(lib-path:D=) ] ;
|
|
|
- local target-type = $(gTARGET_TYPE($(target))) ;
|
|
|
-
|
|
|
- local target-grist = [ join-path $(SOURCE_GRIST) $(3) ] ;
|
|
|
- local build-target = $(target:G=$(target-grist)) ;
|
|
|
-
|
|
|
- # if build instructions for the given target have not been given, do that now.
|
|
|
- if ! $(build-target) in $(gDECLARED_TARGETS)
|
|
|
- {
|
|
|
- declare-target $(target)
|
|
|
- : $(gTARGET_SOURCES($(target)))
|
|
|
- : $(gTARGET_REQUIREMENTS($(target)))
|
|
|
- : $(BUILD) : $(target-type) ;
|
|
|
- }
|
|
|
-
|
|
|
- # Get the name of the built target file
|
|
|
- local target-file = [ FAppendSuffix $(build-target) : $(SUF$(target-type)) ] ;
|
|
|
-
|
|
|
- # Set up dependencies and link instructions
|
|
|
- DEPENDS $(<) : $(target-file) ;
|
|
|
- NEEDLIBS on $(<) += $(target-file) ;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-# Which configuration(s) to build if nothing is explicitly specified
|
|
|
-DEFAULT_BUILD ?= debug ;
|
|
|
-
|
|
|
-# get-BUILD [target-default-build]
|
|
|
-#
|
|
|
-# If BUILD is set, return it. Otherwise if target-default-build is non-empty,
|
|
|
-# return it. Otherwise, return $(DEFAULT_BUILD)
|
|
|
-rule get-BUILD
|
|
|
-{
|
|
|
- local build = $(BUILD) ;
|
|
|
- build ?= $(<) ;
|
|
|
- build ?= $(DEFAULT_BUILD) ;
|
|
|
- return $(build) ;
|
|
|
-}
|
|
|
-
|
|
|
-BIN_DIRECTORY ?= bin ;
|
|
|
-
|
|
|
-# declare-fake-targets abstract-target : target-file
|
|
|
-#
|
|
|
-#
|
|
|
-rule declare-fake-targets
|
|
|
-{
|
|
|
- # make a fake target so that it can be built without knowing the suffix
|
|
|
- # Since executables under *NIX have no suffix, we'd better check
|
|
|
- if $(>) != $(<)
|
|
|
- {
|
|
|
- DEPENDS $(<) : $(>) ;
|
|
|
- NOTFILE $(<) ;
|
|
|
- }
|
|
|
-
|
|
|
- # The following checks that we're in the subdirectory of Jam's invocation
|
|
|
- # so that we can arrange for ungristed target names to be built from the
|
|
|
- # command-line.
|
|
|
- if ( $(SUBDIR) = $(gINVOCATION_SUBDIR) )
|
|
|
- {
|
|
|
- DEPENDS $(<:G=) : $(<) ; # allows $(<:G=) to be used to build all variants
|
|
|
- NOTFILE $(<:G=) ;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-rule declare-target # target : sources : requirements : local-build : target-type
|
|
|
-{
|
|
|
- local target-type = $(5) ;
|
|
|
- local requirements = $(3) ;
|
|
|
- local BUILD = [ get-BUILD $(4) ] ;
|
|
|
- local variants = [ select-ungristed $(BUILD) ] ;
|
|
|
- local build-request = [ difference $(BUILD) : $(variants) ] ;
|
|
|
-
|
|
|
- # extract and remove <lib> targets from $(>)
|
|
|
- local libs = [ get-values <lib> : $(>) ] ;
|
|
|
- local sources = [ FGristFiles [ difference $(>:G=) : $(libs) ] ] ;
|
|
|
-
|
|
|
- # include each jamfile describing a dependee target.
|
|
|
- dependent-include $(libs) ;
|
|
|
-
|
|
|
- local toolset ;
|
|
|
- for toolset in $(TOOLS)
|
|
|
- {
|
|
|
- local v ;
|
|
|
- for v in $(variants)
|
|
|
- {
|
|
|
- local build-pairs
|
|
|
- = [ expand-build-request $(toolset) $(v) $(<)
|
|
|
- : $(requirements) : $(build-request) ] ;
|
|
|
-
|
|
|
- local x;
|
|
|
- local build = $(build-pairs) ;
|
|
|
- for x in $(build-pairs)
|
|
|
- {
|
|
|
- if $(x:G) # Half the elements have grist; we're processing a pair-at-a-time
|
|
|
- {
|
|
|
- # extract the elements of the pair
|
|
|
- local bin-path = $(build[1]) ;
|
|
|
- local property-set = $(build[2]) ;
|
|
|
-
|
|
|
- # SOURCE_GRIST identifies the subproject directory; TARGET_GRIST
|
|
|
- # should identify the subvariant.
|
|
|
- local TARGET_GRIST = [ join-path $(SOURCE_GRIST) $(bin-path) ] ;
|
|
|
-
|
|
|
- # target is the unsuffixed name of the target, with TARGET_GRIST
|
|
|
- local target = $(<:G=$(TARGET_GRIST)) ;
|
|
|
-
|
|
|
- # Do nothing if build instructions and dependencies for this target
|
|
|
- # have already been generated.
|
|
|
- if ! $(target) in $(gDECLARED_TARGETS)
|
|
|
- {
|
|
|
- gDECLARED_TARGETS += $(target) ;
|
|
|
-
|
|
|
- # LOCATE_TARGET affects where built targets are generated. We move
|
|
|
- # it relative to the default location based on the subvariant
|
|
|
- local LOCATE_TARGET
|
|
|
- = [ join-path $(LOCATE_TARGET) $(BIN_DIRECTORY) $(bin-path) ] ;
|
|
|
-
|
|
|
- local target-file = [ FAppendSuffix $(target) : $(SUF$(target-type)) ] ;
|
|
|
- declare-fake-targets $(target) : $(target-file) ;
|
|
|
-
|
|
|
- # set up gBUILD_PROPERTIES for include-tools (below)
|
|
|
- local gBUILD_PROPERTIES = [ split-property-set $(property-set) ] ;
|
|
|
-
|
|
|
- # Include the toolset specification. This will set up the global
|
|
|
- # flags variables in a way appropriate to this build.
|
|
|
- include-tools $(toolset) ;
|
|
|
-
|
|
|
- # transfer target variables to the target file.
|
|
|
- set-target-variables $(target-file) ;
|
|
|
-
|
|
|
- # dispatch to the appropriate declaration function. It would be much
|
|
|
- # better to be able to do this with some sort of indirection, but
|
|
|
- # Jam doesn't yet support it.
|
|
|
- switch $(target-type)
|
|
|
- {
|
|
|
- case EXE : executable-file $(target-file) : $(sources) ;
|
|
|
- case LIB : library-file $(target-file) : $(sources) ;
|
|
|
- }
|
|
|
-
|
|
|
- # generate build instructions
|
|
|
- link-libraries $(target-file) : $(libs) : $(bin-path) ;
|
|
|
- }
|
|
|
-
|
|
|
- # peel the first pair off the front
|
|
|
- build = $(build[3-]) ;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-# exe target : sources : requirements : local-build
|
|
|
-#
|
|
|
-# Declare an executable target.
|
|
|
-rule exe
|
|
|
-{
|
|
|
- declare-local-target $(<) : $(2) : $(3) : $(4) : EXE ;
|
|
|
-}
|
|
|
-
|
|
|
-# lib target : sources : requirements : local-build
|
|
|
-#
|
|
|
-# Declare a statically-linked library target.
|
|
|
-rule lib
|
|
|
-{
|
|
|
- declare-local-target $(<) : $(2) : $(3) : $(4) : LIB ;
|
|
|
-}
|
|
|
-
|