Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/tools/build/v1/boost-base.jam @ 12

Last change on this file since 12 was 12, checked in by landauf, 18 years ago

added boost

File size: 91.8 KB
Line 
1#~ Copyright 2002-2004 Rene Rivera.
2#~ Copyright 2001-2004 David Abrahams.
3#~ Distributed under the Boost Software License, Version 1.0.
4#~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
5
6#  (C) Copyright David Abrahams and Carlos Pinto Coelho 2001. Permission to
7#  copy, use, modify, sell and distribute this software is granted provided this
8#  copyright notice appears in all copies. This software is provided "as is"
9#  without express or implied warranty, and with no claim as to its suitability
10#  for any purpose.
11#
12# Jamrules file by David Abrahams (abrahams@mediaone.net) and Carlos Pinto
13# Coelho (cfspc@altrabroadband.com).
14
15# Notes on the design of the system:
16#
17# This system is designed to support building the "same" targets with multiple
18# build tool suites (e.g. msvc, gcc,...)  and build variants (e.g. debug,
19# release...). Although it currently varies across two dimensions, it should
20# trivially support extension to three or more, e.g. in case of cross-platform
21# builds. The word "same" is written in quotes above because internally,
22# separate targets are generated for each unique toolset/build-variant
23# combination.
24#
25# Specifics of build tool suites are specified in files with names of the form
26# "<name>-tools.jam", where <name> is the name used to identify the tool suite.
27
28# Workarounds for Jam limitations:
29#
30# 1. Jam supports something like the setting of attributes on targets using the
31#    syntax:
32#       <name> on <target> = <expression>
33#
34#    This facility is used to control build actions for individual targets
35#    (target-specific variables take precedence over global ones when build
36#    actions # are executed). An obvious approach would be to use target
37#    attributes to hold # properties of build tools (e.g. where to find the
38#    standard includes).  # Unfortunately, although you can write target
39#    attributes, there is no way to # read them. Instead, we take advantage of
40#    two properties of Jam:
41#
42#    a. A variable name can be formed by evaluating an expression. For example,
43#       the following rule, appends FOOBAR to its first argument to form the
44#       name of a new variable, which is given the value "baz"
45#
46#          rule X { $(1)FOOBAR = baz ; }
47#
48#    b. Any character is allowed in a variable name. So, although they are
49#       actually global variables, we can form names like <name>.c++-flags thus:
50#       
51#          C++FLAGS = $($(1).c++-flags) # Get the c++-flags "attribute" from $(1)
52#
53# 2. There is no way to call a rule based on the value of a variable
54#    other than by using a switch statement. Because that approach requires
55#    intrusive changes to rules when the system is extended, we have avoided
56#    it. Instead, we have taken advantage of two "features" of Jam:
57#
58#    a. The name of a file to be included can be computed from an
59#       expression. For example, the following includes a file whose name is
60#       formed by concatenating $(1) and "-tools.jam":
61#
62#           include $(1)-tools.jam
63#
64#    b. A rule can be redefined any number of times. Its latest definition is
65#       the one invoked. For example, the following prints "#2".
66#
67#           rule X { ECHO #1 ; }
68#           rule X { ECHO #2 ; }
69#           X ;
70#
71#    Together, these facts allow us to select tool-suite-specific actions for
72#    building specific target types by repeatedly redefining the generalized
73#    build actions in the various <build-tools>-tools.jam files
74
75if $(NT)
76{
77    TOOLS ?= vc-7_1 ;
78}
79else if $(UNIX)
80{
81  switch $(JAMUNAME)
82    {
83    case Darwin* :
84        {
85        TOOLS ?= darwin ;
86        }
87
88    case * :
89        {
90        TOOLS ?= gcc ;
91        }
92    }
93}
94else
95{
96    TOOLS ?= gcc ;
97}
98
99SHARED_TYPES = DLL ;
100STATIC_TYPES = LIB ;
101
102# detect-build-tools <tools-name> : <detection-command>
103#
104# Declares a pseudotarget for the specified build tools which is built by
105# the given <detection-command>.
106#
107# Although not currently implemented, the plan is to make compilation of
108# tool-specific targets dependent on this pseudotarget. That way, we will never
109# even attempt to build targets for tools that don't exist.
110rule detect-build-tools
111{
112    detection-command on $(<) = $($(<).bin-directory)$(>) ;
113}
114
115# lib: generator function
116#
117rule library-file ( target : sources + )
118{
119    LibraryFromObjects $(<) : [ Objects $(>) ] ;
120}
121
122# exe: generator function
123#
124rule executable-file ( target : sources + )
125{
126    type-DEPENDS exe : $(<) ;
127    main-from-objects $(<) : [ Objects $(>) ] : EXE ;
128}
129
130# dll: generator function
131#
132rule dll-files ( module implib ? : sources * : target-type ? )
133{
134    type-DEPENDS dll : $(<) ;
135   
136    # Set up the import library dependency on Windows
137    if $(<[2])
138    {
139        INCLUDES $(<[1]) : $(<[2-]) ;
140        INCLUDES $(<[2-]) : $(<[1]) ;
141    }
142   
143    target-type ?= DLL ;
144    if [ MATCH ^(CRAY).* : $(JAMUNAME[-1]) ] # no shared libs on cray
145    {
146        NOTFILE $(<) ;
147    }
148    else
149    {
150        main-from-objects $(<) : [ Objects $(>) ] : $(target-type) ;
151    }
152}
153
154# template: modifier function
155#
156# The target specs are modified by adding those previously specified in a template source.
157# Any specs containing paths are rerooted to correctly reference the dependee locations.
158#
159rule template-modifier ( target : source )
160{
161    local source-dir = [ directory-of $(source:G=) ] ;
162    local source-id = [ target-id-of $(source) ] ;
163   
164    # Make sure it's defined.
165    #
166    if ! $(gTARGET_TYPE($(source-id)))
167    {
168        dependent-include $(source:G=) ;
169    }
170   
171    # Copy the base specs into the target specs, adjust any paths
172    #
173    gTARGET_SOURCES($(target)) +=
174        [ root-paths $(gTARGET_SOURCES($(source-id))) : $(source-dir) ] ;
175    gTARGET_DEPS($(target)) +=
176        [ root-paths $(gTARGET_DEPS($(source-id))) : $(source-dir) ] ;
177    gTARGET_REQUIREMENTS($(target)) +=
178        [ fixup-path-properties $(gTARGET_REQUIREMENTS($(source-id))) : $(source-dir) ] ;
179    gTARGET_DEFAULT_BUILD($(target)) +=
180        $(gTARGET_DEFAULT_BUILD($(source-id))) ;
181}
182
183# main-from-objects exe-target : obj-target... : ("EXE"|"DLL")
184#
185# generate instructions to build the given "main" target from the given object
186# files given in the 2nd parameter. The 3rd parameter should be EXE for an
187# executable, or DLL for a shared library.
188rule main-from-objects ( targets * : objects * : type )
189{
190    # make compiled sources a dependency of target
191
192    MakeLocate $(targets) : $(LOCATE_TARGET) ;
193
194    Clean clean : $(targets) ;
195
196    MODE on $(targets) = $($(type)MODE) ;
197    local link-function = Link-$(type) ;
198    local extra-files = [ $(link-function) $(targets) : $(objects) : $(type) ] ;
199    Chmod $(targets[1]) ;
200    DEPENDS $(targets) : $(objects) ;
201   
202    # locate and attach the extra files generated
203    if $(extra-files)
204    {
205        MakeLocate $(extra-files) : $(LOCATE_TARGET) ;
206        DEPENDS $(targets) : $(extra-files) ;
207    }
208   
209    gFILES($(targets[1])) = $(targets) $(extra-files) ;
210}
211
212rule .do-link ( targets + : sources + : type )
213{
214    # Prepare NEEDLIBS for use by the toolsets' link action (e.g. for
215    # invoking with-command-file)
216    local NEEDLIBS = [ on $(<) return $(NEEDLIBS) ] ;
217   
218    return [ Link-action $(targets) : $(sources) : $(type) ] ;
219}
220
221rule Link-EXE
222{
223    # N.B. By the time this rule is invoked, we had better have gRUN_PATH completely set.
224   
225    local extra-files = [ .do-link $(<) : $(>) : EXE ] ;
226    RUN_PATH on $(<) = [ join [ unique $(gRUN_PATH($(<))) $(gTOOLSET_LIB_PATH) ] : $(SPLITPATH) ] ;
227    if $(UNIX)
228    {
229        LINK_LIBPATH on $(<) = [ join $(gRUN_LD_LIBRARY_PATH($(<))) : $(SPLITPATH) ] ;
230    }
231   
232    return $(extra-files) ;
233}
234
235rule Link-DLL
236{
237    gRUN_LD_LIBRARY_PATH($(<)) += $(gLOCATE($(<[1]))) $(gTOOLSET_LIB_PATH) ;
238    if $(UNIX)
239    {
240        LINK_LIBPATH on $(<) = [ join $(gRUN_LD_LIBRARY_PATH($(<))) : $(SPLITPATH) ] ;
241    }
242   
243    return [ .do-link $(<) : $(>) : DLL ] ;
244}
245
246# store the shell's PATH again, just in case someone uses PATH.
247# This also allows the user to customize the base path for running built
248# products from the command-line
249RUN_PATH ?= $(PATH) ;
250if $(UNIX)
251{
252    LINK_LIBPATH ?= $($(gSHELL_LIBPATH)) ;
253    gAPPEND_LD_LIBRARY_PATH = ":$"$(gSHELL_LIBPATH) ;
254    gAPPEND_PATH = ":$"PATH ;
255}
256if $(NT)
257{
258    # Try some other likely spellings
259    RUN_PATH ?= $(Path) ;
260    RUN_PATH ?= $(path) ;
261    gAPPEND_LD_LIBRARY_PATH = ";%LD_LIBRARY_PATH%" ;
262    gAPPEND_PATH =  ;\"%PATH%\" ;
263}
264
265# Now set this, just in case someone tries to use it.
266PATH = $(RUN_PATH) ;
267if $(UNIX)
268{
269    $(gSHELL_LIBPATH) = $(LINK_LIBPATH) ;
270}
271
272DOLLAR = "$" ;
273 
274# bubble variable-name
275#
276# Helper function for sort, below
277# Removes the greatest element from $(variable-name) and returns it.
278rule bubble #
279{
280    local result = ;
281    local last = $($(<)[1]) ;
282    for x in $($(<)[2-])
283    {
284        if $(last) <= $(x)
285        {
286            result += $(last) ;
287            last = $(x) ;
288        }
289        else
290        {
291            result += $(x) ;
292        }
293    }
294    $(<) = $(result) ;
295    return $(last) ;
296}
297
298# sort args
299#
300# return args sorted in lexicographic order.
301rule sort
302{
303    local _all = $(<) ;
304    local _result = ;
305    local _count ;
306    for _count in $(<)
307    {
308        _result = [ bubble _all ] $(_result) ;
309    }
310    return $(_result) ;
311}
312
313# min args
314#
315# return the lexicographic minimum element of args
316rule min
317{
318    local result = ;
319    local x ;
320    for x in $(<)
321    {
322        if ! $(result) || ( $(x) < $(result) )
323        {
324            result = $(x) ;
325        }
326    }
327    return $(result) ;
328}
329
330# difference listB : listA
331# returns the elements of B that are not in A
332rule difference
333{
334    local result = ;
335    local element ;
336    for element in $(<)
337    {
338        if ! ( $(element) in $(>) )
339        {
340            result += $(element) ;
341        }
342    }
343    return $(result) ;
344}
345
346# replace list : old-value new-value
347#
348# returns list with occurrences of old-value replaced by new-value
349rule replace
350{
351    local result = ;
352    local x ;
353    for x in $(<)
354    {
355        if $(x) = $(>[1])
356        {
357            result += $(>[2]) ;
358        }
359        else
360        {
361            result += $(x) ;
362        }
363    }
364    return $(result) ;
365}
366
367# select-ungristed list...
368#
369# Returns the elements of list that have no grist
370rule select-ungristed
371{
372    local result x ;
373    for x in $(<)
374    {
375        if ! $(x:G)
376        {
377            result += $(x) ;
378        }
379    }
380    return $(result) ;
381}
382
383rule select-gristed ( list * )
384{
385    local result ;
386    for local x in $(list)
387    {
388        if $(x:G)
389        {
390            result += $(x) ;
391        }
392    }
393    return $(result) ;
394}
395
396# Returns grist without "<"/">" for elements matching "<.*>",
397# and ignores other elements.
398rule ungrist ( names * )
399{
400    local result ;
401    for local name in $(names)
402    {
403        local stripped = [ MATCH ^<(.*)>$ : $(name) ] ;
404        result += $(stripped) ;
405    }
406    return $(result) ;
407}
408
409
410# Split a qualified property into 3 elements.
411#
412# Grammar description of qualified-property :
413#   [[<toolset>]<variant>]property
414#
415# returns <toolset> <variant> property
416# missing <toolset> or <variant> are treated as <*>
417rule split-qualified-property
418{
419    local grist1 = $(<:G) ;
420    local ungrist1 = $(<:G=) ;
421    local grist2 = $(ungrist1:G) ;
422    local ungrist2 = $(ungrist1:G=) ;
423    local grist3 = $(ungrist2:G) ;
424    local ungrist3 = $(ungrist2:G=) ;
425    if $(grist3)
426    {
427        return $(grist1) $(grist2) $(grist3)$(ungrist3) ;
428    }
429    else if $(grist2)
430    {
431        return <*> $(grist1) $(grist2)$(ungrist2) ;
432    }
433    else
434    {
435        return <*> <*> $(<) ;
436    }
437}
438
439rule unique # list
440{
441    local result = ;
442    local f ;
443    for f in $(<)
444    {
445        if ! $(f) in $(result)
446        {
447            result += $(f) ;
448        }
449    }
450    return $(result) ;
451}
452
453# get-properties features : properties
454#
455# Given a list of gristed features and a list of properties, returns the
456# properties matching the given features.
457rule get-properties
458{
459    local result = ;
460    local property ;
461    for property in $(>)
462    {
463        if $(property:G) in $(<)
464        {
465            result += $(property) ;
466        }
467    }
468    return $(result) ;
469}
470   
471# get-values features : properties
472#
473# Given a list of gristed feature names and a list of properties, returns the
474# value(s) of the given features.
475rule get-values
476{
477    local _properties = [ get-properties $(<) : $(>) ] ;
478    return $(_properties:G=) ;
479}
480
481rule replace-properties ( property-set * : new-properties * )
482{
483    local result = ;
484    for local x in $(property-set)
485    {
486        if $(x:G) in $(new-properties:G)
487        {
488            if ! $(x:G) in $(result:G)
489            {
490                result += [ get-properties $(x:G) : $(new-properties) ] ;
491            }
492           
493        }
494        else
495        {
496            result += $(x) ;
497        }
498    }
499    return $(result) ;
500}
501
502
503# normalize-properties properties
504#
505# Normalizes a set of (possibly qualified) properties by prepending <*> as many
506# times as necessary to ensure that each property has at least 3 gristed elements.
507rule normalize-properties
508{
509    local property ;
510    local result ;
511    for property in $(<)
512    {
513        switch $(property)
514        {
515            case <*><*><tag>* : result += $(property) ;
516            case <*><tag>* : result += <*>$(property) ;
517            case <tag>* : result += <*><*>$(property) ;
518           
519            case <*><*><*><default>* : result += $(property) ;
520            case <*><*><default><*>* : result += <*>$(property) ;
521            case <*><*><default>* : result += $(property) ;
522            case <*><default><*>* : result += <*><*>$(property) ;
523            case <*><default>* : result += <*>$(property) ;
524            case <default><*>* : result += <*><*><*>$(property) ;
525            case <default>* : result += <*><*>$(property) ;
526                       
527            case <*><*><*><*@*>* : result += $(property) ;
528            case <*><*><*@*>* : result += <*>$(property) ;
529            case <*><*@*>* : result += <*><*>$(property) ;
530            case <*@*>* : result += <*><*><*>$(property) ;
531                       
532            case <*><*><*>* : result += $(property) ;
533            case <*><*>* : result += <*>$(property) ;
534            case <*>* : result += <*><*>$(property) ;
535            case * : result += <*><*><*>$(property) ;
536        }
537    }
538    return $(result) ;
539}
540
541# intersection set1 : set2
542#
543# Removes from set1 any items which don't appear in set2 and returns the result.
544rule intersection
545{
546    local result v ;
547    for v in $(<)
548    {
549        if $(v) in $(>)
550        {
551            result += $(v) ;
552        }
553    }
554    return $(result) ;
555}
556
557# subset sub : super
558#
559# Returns true iff sub is a subset of super, empty otherwise
560rule is-subset
561{
562    if [ intersection $(<) : $(>) ] = $(<)
563    {
564        return true ;
565    }
566}
567
568# distribute-feature <feature>value1[/value2...]
569#
570# Distribute the given feature across the slash-separated set of values, i.e.
571# returns <feature>value1[ <feature>/value2...]
572rule distribute-feature
573{
574    local g = $(<:G) ;
575    local result = [ split-path $(<:G=) ] ;
576    return $(g)$(result) ;
577}
578
579# set-insert variable-name : value... ;
580#
581# Appends the given values to the list designated by variable-name if they are
582# not already present.
583rule set-insert
584{
585    local v ;
586    for v in $(>)
587    {
588        if ! ( $(v) in $($(<)) )
589        {
590            $(<) += $(v) ;
591        }
592    }
593}
594
595# equal-sets set1 : set2
596#
597# Returns true iff set1 contains the same elements as set2.
598# Not sensitive to the same element appearing multiple times
599rule equal-sets
600{
601    if ( ! [ difference $(<) : $(>) ] ) && ( ! [ difference $(>) : $(<) ] )
602    {
603        return true ;
604    }
605}
606
607# feature name : [values...]
608#
609# Declares a feature with the given name, and the given allowed values.
610rule feature
611{
612    if $(<) in $(gFEATURES)
613    {
614        EXIT feature $(<) : $(gFEATURE_VALUES(<$(<)>) redeclared as $(<) : $(>) ;
615    }
616    gFEATURES += <$(<)> ;
617    gUNGRISTED(<$(<)>) = $(<) ;
618    gFEATURE_VALUES(<$(<)>) = $(>) ;
619}
620
621rule free-feature
622{
623    feature $(<) : $(>) ;
624    gFREE_FEATURES += <$(<)> ;
625    if $(>)
626    {
627        gSINGLE_VALUED_FREE_FEATURES += <$(<)> ;
628    }
629}
630
631rule path-feature
632{
633    free-feature $(<) : $(>) ;
634    gPATH_FEATURES += <$(<)> ;
635}
636
637rule dependency-feature
638{
639    path-feature $(<) : $(>) ;
640    gDEPENDENCY_FEATURES += <$(<)> ;
641}
642
643# feature-default <feature>...
644#
645# return the default properties corresponding to the given feature(s)
646rule feature-default
647{
648    local result f ;
649    for f in $(<)
650    {
651        result += $(f)$(gFEATURE_VALUES($(f))[1]) ;
652    }
653    return $(result) ;
654}
655
656# flags tools-name variable-name condition [: value(s)]
657#
658# Declare command-line settings for a given toolset.
659#   toolset:         the name of the toolset
660#   variable-name:   the name of a global variable which can be used to carry
661#                    information to a command-line
662#   condition:       One of the following:
663#                    1. zero or more property-sets of the form:
664#                          <feature>value[/<feature>value...]
665#                    2. one or more <feature>[/<feature>...]
666#
667# This rule appends to the specified variable, depending on a target's build
668# configuration and the form of condition.
669#
670#   1. if any specified property-set is a subset of the target's build properties or if
671#   condition is empty, the values specified in $(3) will be appended once to
672#   /variable-name/.
673#
674#   2. The value of each specified feature that participates in the target's
675#   build properaties is appended to /variable-name/.
676#
677# The variable will be set "on" the target so it may be  used in its build actions.
678rule flags
679{
680    local toolset = $(gCURRENT_TOOLSET) ;
681    local variable = $(<[2]) ;
682    local condition = $(<[3-]) ;
683
684    # record the names of all variables used so they can be set on targets
685    if ! ( $(variable) in $(gTARGET_VARIABLES) )
686    {
687        gTARGET_VARIABLES += $(variable) ;
688        $(variable) = ;
689    }
690
691    local found = ;
692    local x ;
693    for x in $(condition)
694    {
695        x = [ split-path $(x) ] ;
696       
697        # Add each feature to the set of features relevant to the toolset
698        gRELEVANT_FEATURES($(toolset)) += $(x:G) ;
699
700        # is it a property set?
701        if $(x:G=)
702        {
703             # if this property_set is a subset of the current build-properties
704             if ( ! $(found) ) && [ is-subset $(x) : $(gBUILD_PROPERTIES) ]
705             {
706                 found = true ;
707                 $(variable) += $(>) ;
708             }
709        }
710        else
711        {
712            $(variable) += [ get-values $(x) : $(gBUILD_PROPERTIES) ] ;
713            if $(x:G) in $(gDEPENDENCY_FEATURES)
714            {
715                gDEPENDENCY_VARIABLES($(toolset)) += $(variable) ;
716            }
717        }
718    }
719    if ! $(condition)
720    {
721        $(variable) += $(>) ;
722    }
723}
724
725# include-tools toolset
726#
727# Unconditionally process the specification file for the given toolset. It is
728# necessary to do this for each target built with that toolset, since the
729# toolset will invoke the flags rule to set global variables based on the build
730# properties of the target.
731rule include-tools
732{
733    if ! $(gIN_INCLUDE_TOOLS)
734    {
735        gCURRENT_TOOLSET = $(<) ;
736        gRELEVANT_FEATURES($(<)) = ; # clear relevant feature set
737        gDEPENDENCY_VARIABLES($(<)) = ;
738
739        # clear any lingering target variables that may have been declared
740        $(gTARGET_VARIABLES) = ;
741        gTARGET_VARIABLES = NEEDLIBS NEEDIMPS ; # start over from the beginning
742        gTOOLSET_LIB_PATH = ;
743    }
744   
745    {
746        local gIN_INCLUDE_TOOLS = true ;
747        SEARCH on <jam-module>$(<)-tools.jam = $(BOOST_BUILD_PATH) ;
748        include <jam-module>$(<)-tools.jam ;
749    }
750   
751    # Always maintain the list of relevant features as unique
752    if ! $(gIN_INCLUDE_TOOLS)
753    {
754        gRELEVANT_FEATURES($(<)) = [
755          unique $(gRELEVANT_FEATURES($(<)))
756            $(gALWAYS_RELEVANT)
757        ] ;
758    }
759   
760    gINCLUDED(<jam-module>$(<)-tools.jam) = TRUE ;
761}
762
763# extends-toolset toolset
764#
765# Used in a toolset definition file; Declares that the toolset currently being
766# defined is an extension of the given toolset.
767rule extends-toolset
768{
769    include-tools $(<) ;
770}
771
772# relevant-features toolset
773#
774# Returns the set of unique features relevant to the given toolset; includes the
775# toolset description file as a side-effect if necessary.
776rule relevant-features # name
777{
778    if ! $(gRELEVANT_FEATURES($(<)))
779    {
780        include-tools $(<) ;
781    }
782    return $(gRELEVANT_FEATURES($(<))) ;
783}
784
785# variant name [ : parents... ] : [<toolset>]<feature>value...
786#
787# Declare a build variant, whose configuration is given by the given (optionally
788# toolset-qualified) properties.
789rule variant ( name : parents-or-properties * : tool-properties * )
790{
791    gALL_VARIANTS += $(name) ;
792    local parents ;
793    if ! $(tool-properties)
794    {
795        if $(parents-or-properties[1]:G)
796        {
797            tool-properties = $(parents-or-properties) ;
798        }
799        else
800        {
801            parents = $(parents-or-properties) ;
802        }
803    }
804    else
805    {
806        parents = $(parents-or-properties) ;
807    }
808    local toolset ;
809    for toolset in $(TOOLS)
810    {
811        # We hijack select-properties to do our dirty work here.
812        # Because properties in a variant declaration are only qualified with
813        # toolset and not variant, we specify the toolset where
814        # select-properties expects a variant name. The first toolset parameter
815        # is necessary to get the relevant-features correctly set. We supply
816        # the variant name as the target name, so that error messages will look
817        # coherent.
818        local name-properties
819            = [ select-properties $(toolset) $(toolset) $(name) : $(tool-properties) ] ;
820        if $(parents)
821        {
822            local parent ;
823            for parent in $(parents)
824            {
825                local parent-properties
826                    = $(gBASE_PROPERTIES($(toolset),$(parent))) ;
827                local inherited-features
828                    = [ unique
829                        [ difference $(parent-properties:G) : $(name-properties:G) ]
830                        $(gFREE_FEATURES)
831                        $(gPATH_FEATURES)
832                        $(gDEPENDENCY_FEATURES ] ;
833                local inherited-properties
834                    = [ get-properties $(inherited-features) : $(parent-properties) ] ;
835                name-properties
836                    += $(inherited-properties) ;
837            }
838        }
839        gBASE_PROPERTIES($(toolset),$(name)) = [ sort $(name-properties) ] ;
840    }
841}
842
843# select-properties toolset variant target : qualified-properties...
844#
845# Returns
846rule select-properties ( toolset variant target ? : qualified-properties * )
847{
848    local relevant_features = [ relevant-features $(toolset) ] ;
849    local normalized = [ normalize-properties $(>) ] ;
850
851    # Classify properties by the specificity of their qualification.
852    # First, grab those that apply to this toolset, or all toolsets
853    local this_toolset = [ get-values <$(toolset)> : $(normalized) ] ;
854    local all_toolsets = [ get-values <*> : $(normalized) ] ;
855   
856    local 0-stars = [ get-values <$(variant)> : $(this_toolset) ] ;
857    local 1-stars = [ get-values <*> : $(this_toolset) ] [ get-values <$(variant)> : $(all_toolsets) ] ;
858    local 2-stars = [ get-values <*> : $(all_toolsets) ] ;
859
860    # Select feature names from the features relevant to the toolset.
861    local features = [ intersection $(relevant_features)
862        : $(0-stars:G) $(1-stars:G) $(2-stars:G) ] ;
863
864    local result f ;
865    for f in $(features)
866    {
867        local is_free = [ intersection $(f) : $(gFREE_FEATURES) ] ;
868       
869        # Go through the $(n-stars) lists from most- to least- specific;
870        # collect the best set of values of a simple feature, and /all/
871        # values of a free feature.
872        local r n ;
873        for n in 0 1 2
874        {
875            if ! $(r) || $(is_free)
876            {
877                r += [ get-values $(f) : $($(n)-stars) ] ;
878            }
879        }
880
881        r = [ unique $(r) ] ;
882        if $(r[2]) && ! $(is_free) # Check for conflicting simple-feature requests
883        {
884            EXIT "Error: Ambiguous properties requested for"
885            $(target) <$(toolset)><$(variant)> ":" $(f)$(r) ;
886        }
887        result += $(f)$(r) ;
888    }
889    return $(result) ;
890}
891# get toolset features
892SEARCH on <jam-module>features.jam = $(BOOST_BUILD_PATH) ;
893include <jam-module>features.jam ;
894
895# ungrist-properties properties...
896#
897# Transforms a list of properties of the form:
898#       <feature1>value1 [<feature2>value2... ]
899# into a list of the form:
900#       feature1-value1 feature2-value2
901# suitable for use as directory path elements
902#
903rule ungrist-properties
904{
905    local property ;
906    local result = ;
907    for property in $(<)
908    {
909        result += $(gUNGRISTED($(property:G)))-$(property:G=) ;
910    }
911    return $(result) ;
912}
913
914# set-target-variables target
915#
916# attach global build tool settings to the given file-target, so that they can be
917# used in build actions.
918rule set-target-variables ( targets * )
919{
920    local s ;
921    for s in $(gTARGET_VARIABLES)
922    {
923        $(s) on $(targets) = $($(s)) ;
924
925        # set up dependencies if the target is a "top-level" target
926        if ( $(s) in $(gDEPENDENCY_VARIABLES($(gCURRENT_TOOLSET))) ) && $(gTARGET_TYPE($(<)))
927        {
928            DEPENDS $(targets) : $($(s)) ;
929        }
930    }
931    local libpath = [ get-properties <library-path> : $(gBUILD_PROPERTIES) ] ;
932    gRUN_PATH($(targets)) += $(libpath:G=) ;
933    gRUN_LD_LIBRARY_PATH($(targets)) += $(libpath:G=) ;
934}
935
936# For path properties, add a relative path prefix to the value as
937# necessary to locate the path relative to the given subproject
938# directory.
939rule fixup-path-properties ( properties * : subproject-directory ? )
940{
941    local result ;
942   
943    for local p in $(properties)
944    {
945        if $(p:G) in $(gPATH_FEATURES)
946        {
947            # If the path property value is project-relative, re-root
948            # it appropriately for that project
949            local parse-project = [ MATCH ^@([^/$(SLASH)]+)[/$(SLASH)]?(.*) : $(p:G=) ] ;
950            if $(parse-project)
951            {
952                local project = $(parse-project[1]) ;
953                local subproject = $(parse-project[2]) ;
954                p = [ root-paths $(subproject:G=$(p:G)) : $(gPROJECT($(project))) ] ;
955            }
956            else if $(subproject-directory)  # re-root it relative to this directory
957            {
958                p = [ root-paths $(p) : $(subproject-directory) ] ;
959            }
960        }
961       
962        result += $(p) ;
963    }
964   
965    return $(result) ;
966}
967
968# remove-incompatible-builds requirements... : build-request... : target-name
969#
970# If any element of requirements has the same grist but a different ungristed
971# part as any element of build-request, exits with an error report about target-name
972rule remove-incompatible-builds ( requirements * : build-request * : target-name + )
973{
974    local all-properties = [ unique $(<) $(>) ] ;
975    local all-features = $(all-properties:G) ;
976    local unique-features = [ unique $(all-features) ] ;
977    if $(all-features) != $(unique-features)
978    {
979        local result ;
980        local skip ;
981        for local p in $(build-request)
982        {
983            # if a feature of the build request is also in the
984            # requirements, but with differing value(s)
985            if ( $(p:G) in $(requirements:G) )
986              && ! ( $(p) in $(requirements) )
987            {
988                # decide what to do.
989                local value = [ get-values $(p:G) : $(requirements) ] ;
990                if $(value[2])
991                {
992                    EXIT Unexpectedly found multiple build requests
993                          for feature $(p:G) with values $(values) ;
994                }
995               
996                local requested = [ split-path $(p:G=) ] ;
997                if $(requested[2])
998                {
999                    local skipped = [ difference $(requested) : $(value) ] ;
1000                   
1001                    if ! $(gNOWARN_INCOMPATIBLE_BUILDS)
1002                    {
1003                        ECHO $(target-name) requires $(p:G)$(value),
1004                            skipping requested build configuration(s) $(p:G)$(skipped). ;
1005                    }
1006                   
1007                    result += $(p:G)$(value) ;
1008                }
1009                else
1010                {
1011                    if ! $(gNOWARN_INCOMPATIBLE_BUILDS)
1012                    {
1013                        ECHO skipping $(target-name) due to incompatible
1014                            build requirements $(p:G)$(value). ;
1015                    }
1016                    skip = true ;
1017                }
1018            }
1019            else
1020            {
1021                result += $(p) ;
1022            }
1023        }
1024       
1025        if $(skip)
1026        {
1027            build-request = SKIP ;
1028        }
1029        else
1030        {
1031            build-request = $(result) ;
1032        }
1033    }
1034    return $(build-request) ;
1035}
1036
1037# multiply-property-sets [<feature>value1[/value2...] ]...
1038#
1039# Expands a set of (possibly multi-valued) properties into all the combinations
1040# that include every feature in the set. Each combination is given as a path,
1041# with the slash separating the properties, sorted in feature order.
1042rule multiply-property-sets
1043{
1044    local result p ;
1045    for p in [ sort $(<) ]
1046    {
1047        # expand any multi-valued simple features from the default build
1048        local multiple = [ distribute-feature $(p) ] ;
1049
1050        # concatenation produces a product, so the tree branches for each
1051        # multi-valued simple feature.
1052        result = $(result)/$(multiple) ;
1053        result ?= $(multiple) ; # this trick allows us to get started
1054    }
1055    return $(result) ;
1056}
1057
1058# Return a list consisting of all the elements of properties which
1059# aren't the defaults for their features.
1060rule remove-default-properties ( properties * )
1061{
1062    return [ difference $(properties) : [ feature-default $(properties:G) ] ] ;
1063}
1064
1065# make-path-property-sets base-path : common-properties : property-sets
1066#
1067# Returns a list of paths where the initial ungristed part of each element is a
1068# relative path to a subvariant directory from a target's build root and the
1069# rest of the element is a slash-separated property set describing the
1070# properties of the target to be built.
1071#
1072# Each path returned is base-path extended by one of the ungristed property-sets
1073# (or just the base-path if no property-sets are supplied). Each property set
1074# returned is formed by extending common-properties with one of the property-sets.
1075#
1076# For example,
1077#
1078#   make-path-property-sets gcc/release : <p1>v1 : <p2>v2/<p3>v3
1079#
1080# returns this single-element list:
1081#
1082#      gcc/release/p2-v2/p3-v3/<p1>v1/<p2>v2/<p3>v3
1083#     |<-- subvariant path -->|<-- property-set -->|
1084rule make-path-property-sets ( base-path : common-properties * : property-sets * )
1085{
1086    local result ;
1087    local s ;
1088    for s in $(property-sets)
1089    {
1090        local x =
1091          # directory components
1092          $(base-path)
1093          [ ungrist-properties
1094              [ remove-default-properties [ split-path $(s) ] ]
1095          ]
1096          # properties
1097          $(common-properties) $(s)
1098            ;
1099       
1100        result += $(x:J=$(SLASH)) ;
1101    }
1102
1103    # if there were no overrides, just add the base variant and properties
1104    if ! $(result)
1105    {
1106        result = [ join $(base-path) $(common-properties) : $(SLASH) ] ;
1107    }
1108    return $(result) ;
1109}
1110
1111# segregate-overrides override-var base-var
1112#
1113# removes elements of $(base-var) from $(override-var), and removes elements
1114# whose grist is in $(override-var:G) from $(base-var).
1115rule segregate-overrides
1116{
1117    $(<) = [ difference $($(<)) : $($(>)) ] ;
1118
1119    # Which features, and thus properties, of the base variant are we keeping?
1120    local kept-features = [ difference $($(>):G) : $($(<):G) ] ;
1121    $(>) = [ get-properties $(kept-features) : $($(>)) ] ;
1122}
1123
1124# If any single-valued free-feature appears more than once in free-property...,
1125# exit with an appropriate error message.
1126rule report-free-property-conflicts ( free-property * : target + )
1127{
1128    local p = [ get-properties $(gSINGLE_VALUED_FREE_FEATURES) : $(free-property) ] ;
1129    local f = [ unique $(p:G) ] ;
1130    if $(p:G) != $(f)
1131    {
1132        EXIT $(>): multiple values for single-valued free feature(s)
1133            [ difference $(p:G) $(f) ] requested ;
1134    }
1135}
1136
1137# Returns a list of path-property-sets (see make-path-property-sets above) for
1138# all build configurations based on the given toolset, requirements, and
1139# build-request. Target-name is just used for error reporting.
1140rule expand-build-request ( toolset variant target : raw-requirements * : raw-build-request * )
1141{
1142    # grab the requirements and BUILD-request relevant to this toolset and variant
1143    local requirements = [ select-properties $(toolset) $(variant) : $(raw-requirements) ] ;
1144    local build-request = [ select-properties $(toolset) $(variant) : $(raw-build-request) ] ;
1145
1146    # Separate the free features (e.g. <define>, <undef>, <include>) from the others
1147    local free-properties = [ segregate-free-properties requirements build-request ] ;
1148
1149    # Check for conflicts
1150    report-free-property-conflicts $(free-properties) : $(target) ;
1151    build-request = [ remove-incompatible-builds $(requirements)
1152      : $(build-request) : $(target) ] ;
1153
1154    if $(build-request) != SKIP
1155    {
1156        # Get  the base variant for the toolset. Includes free features
1157        local base-properties = $(gBASE_PROPERTIES($(toolset),$(variant))) ;
1158
1159        # Which properties will override settings in the base variant?
1160        local override-properties = [ unique $(requirements) $(build-request) ] ;
1161        segregate-overrides override-properties : base-properties ;
1162
1163        # Which features will pick up a default value because they are not in
1164        # the base variant or in the overrides?
1165        local relevant-features = [ relevant-features $(toolset) ] ;
1166        local override-free-features = [ intersection $(gSINGLE_VALUED_FREE_FEATURES)
1167                                        : $(free-properties:G) ] ;
1168        local defaulted-features = [ difference $(relevant-features)
1169                                    : $(override-properties:G) $(base-properties:G)
1170                                      $(override-free-features)
1171                                   ] ;
1172       
1173        local defaulted-properties = [ feature-default $(defaulted-features) ] ;
1174       
1175        # VP: defaulted-properties have the form <feature>value and there's 1 value.
1176        # Hence, each element of defaulted-properties will be part of each
1177        # component of override-sets and will be a part of each property-set
1178        # returned. By segregating them, the result is changed in only one
1179        # way: free properties does not show up in target path.
1180        local defaulted-free-properties = [ segregate-free-properties defaulted-properties ] ;
1181
1182        #
1183        # Allow <default> properties and rules to take effect.
1184        #
1185        local default-requirements = [ get-values <default> : $(free-properties) ] ;
1186       
1187        defaulted-properties = [ replace-properties $(defaulted-properties)
1188                                : [ select-gristed $(default-requirements) ] ] ;
1189       
1190        local non-defaults =  $(requirements) $(build-request) $(free-properties) ;
1191
1192        for local r in [ select-ungristed $(default-requirements) ]
1193        {
1194            local x = [ $(r) $(toolset) $(variant) : $(non-defaults) ] ;
1195            # ECHO  $(r) yields $(x) ;
1196            # ECHO defaulted-properties= $(defaulted-properties) ;
1197            defaulted-properties = [
1198              replace-properties $(defaulted-properties) : $(x) ] ;
1199        }
1200       
1201        # In case any defaults should conflict with the requirements,
1202        # force them to match up.
1203        defaulted-properties = [ replace-properties $(defaulted-properties) : $(requirements) ] ;
1204
1205        # form override property sets of the form (property1[/property2...] )+,
1206        # sorted in feature order. These represent the properties of subvariants
1207        # that differ from the base variant
1208        local override-sets
1209            = [ multiply-property-sets $(override-properties) $(defaulted-properties) ] ;
1210
1211        # return path-property-sets corresponding to each (sub)variant build
1212        # described.
1213        return [ make-path-property-sets
1214                   $(toolset)$(SLASH)$(variant)
1215                 : [ fixup-path-properties
1216                         $(base-properties)
1217                         $(free-properties)
1218                         $(defaulted-free-properties)
1219                       : $(RELATIVE_SUBDIR)
1220                   ]
1221                 : $(override-sets)
1222               ] ;
1223    }
1224}
1225
1226# split-path-at-grist path
1227#
1228# Breaks path at each $(SLASH) that is followed by grist. This can be used to
1229# break apart property sets, particularly where the <include> feature is used,
1230# since its value is typically a path.
1231rule split-path-at-grist
1232{
1233    local full-split = [ split-path $(<) ] ;
1234    local last ;
1235    local result x ;
1236    for x in $(full-split)
1237    {
1238        if $(x:G)
1239        {
1240            result += $(last) ;
1241            last = $(x) ;
1242        }
1243        else
1244        {
1245            last = $(last)$(SLASH)$(x) ;
1246            last ?= $(x) ;
1247        }
1248    }
1249    return $(result) $(last) ;
1250}
1251
1252#
1253# GIVEN:
1254#
1255# A set of dependency sources with grist to indicate the types
1256# (<dll>*, <lib>*, etc)
1257#
1258# RESULT:
1259#
1260# Will use the type, basename, and SUF*/PRE* to expand the name
1261# of the sources to their fully specific target name.
1262#
1263# EXAMPLE:
1264#
1265# [ expand-source-names <lib>test <dll>test <exe>test README.txt <pyd>test ]
1266#
1267# RETURNS:
1268#
1269# <lib>libtest.a <dll>libtest.so <exe>test.app README.TXT <pyd>test.so
1270#
1271rule expand-source-names ( sources * )
1272{
1273    local x-sources = ;
1274    for local source in $(sources)
1275    {
1276        local grist = [ ungrist $(source:G) ] ;
1277        local type = $(gTARGET_TYPE_ID($(grist))) ;
1278        if $(type)
1279        {
1280            local p = "" ; if $(source:B=:S=:G=) { p = "/" ; }
1281            local prefix = "" ;
1282            local suffix = "" ;
1283            if $(PRE$(type)[1]) { prefix = $(PRE$(type)[1]) ; }
1284            if $(SUF$(type)[1]) { suffix = $(SUF$(type)[1]) ; }
1285            x-sources += $(source:B=:S=)$(p)$(prefix)$(source:B:S=)$(suffix) ;
1286        }
1287        else
1288        {
1289            x-sources += $(source) ;
1290        }
1291    }
1292    return $(x-sources) ;
1293}
1294
1295#
1296# GIVEN:
1297#
1298# A set of targets and a single target type for all the targets
1299# (DLL, LIB, etc.)
1300#
1301# RESULT:
1302#
1303# Will use the type, basename, and SUF*/PRE* to expand the name
1304# of the targets to their fully specific target name.
1305#
1306# EXAMPLE:
1307#
1308# [ expand-targets-names foo bar : DLL ]
1309#
1310# RETURNS:
1311#
1312# libfoo.a libbar.so
1313#
1314rule expand-target-names ( targets + : target-type )
1315{
1316    local x-targets = ;
1317    for local target in $(targets)
1318    {
1319        local prefix = "" ;
1320        local suffix = "" ;
1321        if $(PRE$(target-type)[1]) { prefix = $(PRE$(target-type)[1]) ; }
1322        if $(SUF$(target-type)[1]) { suffix = $(SUF$(target-type)[1]) ; }
1323        x-targets += $(prefix)$(target)$(suffix) ;
1324    }
1325    return $(x-targets) ;
1326}
1327
1328# declare-local-target name : sources : requirements : local-BUILD : target-type
1329#
1330# declares a subproject-local target of the given name and target-type. This is
1331# all top-level rules which declare targets should eventually go through here.
1332#
1333# RETURNS: the a list of target names for the files built by the target.
1334rule declare-local-target ( target : sources * : requirements * : default-build * : target-type )
1335{
1336    # We expand out the name of the target
1337    local x-target = [ expand-target-names $(target) : $(target-type) ] ;
1338
1339    # We add SOURCE_GRIST the base target name here because we're referring the
1340    # abstract  target which generates all of the actual builds. We need a way to
1341    # distinguish targets of the same name from different subprojects.
1342    local target-id = [ FGristFiles $(x-target) ] ;
1343
1344    if ! $(target-type)
1345    {
1346        EXIT No target type given for "$(x-target)" ;
1347    }
1348
1349    # Define the specifications of the target.
1350    gTARGET_NAME($(target-id)) = $(target) ;
1351
1352    # Declare the basic target.
1353    declare-basic-target $(target-id) : $(sources) : $(requirements) : $(default-build) : $(target-type) ;
1354
1355    # Generate build instructions, but only if the target has a generator.
1356    #
1357    if $(gGENERATOR_FUNCTION($(gTARGET_TYPE($(target-id)))))
1358    {
1359        # Supress the regular build of this target
1360        local suppress = [ get-values <suppress> : $(default-build) ] ;
1361        local gSUPPRESS_FAKE_TARGETS = $(suppress[1]) ;
1362
1363        declare-fake-targets $(target) : $(target-id) ;
1364
1365        # Just gather information if we are including a library's Jamfile for a
1366        # dependent target. Don't generate build instructions here.
1367        if ! $(gIN_LIB_INCLUDE)
1368        {
1369            main-target $(target-id) : $(gTARGET_DEFAULT_BUILD($(target-id))) ;
1370        }
1371    }
1372
1373    return $(gTARGET_FILES($(target-id))) ;
1374}
1375
1376# declare-basic-target target-id : sources : requirements : local-BUILD : target-type
1377#
1378# Declares a basic target for the given target-id and target-type.
1379# All target generation should go through here to ensure all vars are set
1380# for the targets.
1381#
1382# WARNING: This only declares, no build instructions are generated here.
1383rule declare-basic-target ( target-id : sources * : requirements * : default-build * : target-type )
1384{
1385    # We expand out the name of the sources
1386    local x-sources = [ expand-source-names $(sources) ] ;
1387
1388    # Define the specifications of the target, but only if we haven't already.
1389    #
1390    if ! $(gTARGET_TYPE($(target-id)))
1391    {
1392        # Save basic information about the target.
1393        #
1394        gTARGET_TYPE($(target-id)) = $(target-type) ;
1395
1396        # Add the specified requirements to any requirements given by the target
1397        # type, and the corresponding <target-type> property.
1398        #
1399        gTARGET_REQUIREMENTS($(target-id))
1400            = toolset::requirements $(requirements) $(gTARGET_TYPE_REQUIREMENTS($(target-type))) ;
1401        if ! $(gNO_TARGET_TYPE_REQUIREMENT($(target-type)))
1402        {
1403            gTARGET_REQUIREMENTS($(target-id)) += <target-type>$(target-type) ;
1404        }
1405
1406        # Collect the recognized dependencies to other targets.
1407        #
1408        local dependencies ;
1409        for local source in [ select-gristed $(x-sources) ]
1410        {
1411            local dependency-type = [ ungrist $(source:G:L) ] ;
1412            local dependency-type-id = $(gTARGET_TYPE_ID($(dependency-type))) ;
1413            if $(gIS_DEPENDENCY($(dependency-type-id)))
1414            {
1415                gTARGET_DEPS($(target-id)) += $(source:G=$(dependency-type-id)) ;
1416            }
1417        }
1418
1419        # Sources that aren't recognized as targets, are considered raw sources.
1420        #
1421        gTARGET_SOURCES($(target-id))
1422            = [ FGristFiles
1423                [ difference $(x-sources:G=) : $(gTARGET_DEPS($(target-id)):G=) ] ] ;
1424
1425        # Save the default builds.
1426        #
1427        gTARGET_DEFAULT_BUILD($(target-id)) = $(default-build) ;
1428
1429        # Apply any modifiers to the target specs.
1430        #
1431        for local mod in $(gTARGET_DEPS($(target-id)))
1432        {
1433            local dependency-type-id = [ ungrist $(mod:G) ] ;
1434            local modifier-function = $(gMODIFIER_FUNCTION($(dependency-type-id))) ;
1435            if $(modifier-function)
1436            {
1437                # Remove and apply the modifier.
1438                gTARGET_DEPS($(target-id)) = [ difference $(gTARGET_DEPS($(target-id))) : $(mod) ] ;
1439                local ignored = [ $(modifier-function) $(target-id) : $(mod) ] ;
1440            }
1441        }
1442    }
1443    # Trying to define the same specific target with a different type.
1444    #
1445    else if $(gTARGET_TYPE($(target-id))) != $(target-type)
1446    {
1447        EXIT conflicting target types for "$(x-target)":
1448        "$(gTARGET_TYPE($(target-id)))" "$(target-type)" ;
1449    }
1450}
1451
1452# directory-of files...
1453#
1454# Returns a list of the directories containing each element of files
1455rule directory-of
1456{
1457    local result d ;
1458    for d in $(<:D)
1459    {
1460        if $(d) = ""
1461        {
1462            result += $(DOT) ;
1463        }
1464        else
1465        {
1466            result += $(d) ;
1467        }
1468    }
1469    return $(result) ;
1470}
1471
1472# top-relative-tokens path
1473#
1474# Returns a list of path elements which form the relative path from TOP to path,
1475# which is expected to be given relative to the current subproject.
1476rule top-relative-tokens
1477{
1478    return [ simplify-path-tokens $(SUBDIR_TOKENS) [ split-path $(<) ] ] ;
1479}
1480
1481.project-root-tokens = [ split-path $(.boost-build-file:D) ] ;
1482
1483# try to make a potentially absolute path relative to the project
1484# root.  Only works for paths below the project root right now; others
1485# will remain absolute.
1486rule relative-path ( path )
1487{
1488    local path-tokens = [ split-path $(path) ] ;
1489   
1490    # try to strip the project root
1491    local r = $(.project-root-tokens) ;
1492    local p = $(path-tokens) ;
1493    while $(r) && ( $(r[1]) = $(p[1]) )
1494    {
1495        p = $(p[2-]) ;
1496        r = $(r[2-]) ;
1497    }
1498   
1499    # if successful, use the stripped project root
1500    if ! $(r)
1501    {
1502        path-tokens = $(p) ;
1503    }
1504   
1505    return [ tokens-to-simple-path  $(path-tokens) ] ;
1506}
1507
1508# dependent-include target-path...
1509#
1510# For each target-path, ensure that the appropriate Jamfile has been
1511# included. Used when a target declares its dependency on another target.
1512rule dependent-include
1513{
1514    local target ;
1515    for target in $(<)
1516    {
1517        {
1518            local .project-path = [ target-path-of $(target) ] ;
1519            .project-path = $(.project-path:D) ;
1520           
1521            # load the file as a dependent.
1522            local gIN_LIB_INCLUDE = TRUE ;
1523           
1524            #
1525            local [ protect-subproject ] ;
1526            local .project-name-and-subdir = [ enter-subproject $(.project-path) ] ;
1527            local .project-name = $(.project-name-and-subdir[1]) ;
1528            local .project-subdir = $(.project-name-and-subdir[2]) ;
1529            local .jamfile-path = [ root-paths $(JAMFILE) : [ root-paths $(.project-subdir) : $(TOP) ] ] ;
1530           
1531            load-jamfiles $(.jamfile-path) ;
1532        }
1533    }
1534}
1535
1536# segregate-free-properties variable1 variable2...
1537#
1538# returns the and removes the unique list of free properties from
1539# $(variable1) $(variable2)...
1540rule segregate-free-properties
1541{
1542    local free-properties = [ unique [ get-properties $(gFREE_FEATURES) : $($(<)) ] ] ;
1543    local v ;
1544    for v in $(<)
1545    {
1546        $(v) = [ difference $($(v)) : $(free-properties) ] ;
1547    }
1548    return $(free-properties) ;
1549}
1550
1551# is-link-compatible feature : value1 : value2
1552#
1553# return non-empty iff a library built with <feature>value1 can be linked into a
1554# target with <feature>value2, empty otherwise
1555rule is-link-compatible ( feature : value1 : value2 )
1556{
1557    return [ intersection
1558        $(feature) $(value1:G=$(feature))
1559        $(value1:G=$(feature))$(SLASH)$(value12:G=$(feature))
1560        $(value2:G=$(feature))
1561        : $(gLINK_COMPATIBLE) ] ;
1562}
1563
1564# find-compatible-subvariant main-target : toolset variant : dependent-simple-properties
1565rule find-compatible-subvariant ( main-target : toolset variant : dependent-simple-properties * )
1566{
1567    # calculate the subvariant only of what is requested
1568    # the subvariant requested...
1569    local sv-request =
1570        [ multiply-property-sets
1571            [ get-properties $(BUILD:G) : $(dependent-simple-properties) ] ] ;
1572    # the available build requests...
1573    local build-requests =
1574        [ multiply-property-sets [ select-gristed $(BUILD) ] ] ;
1575    # the build requst we want to build...
1576    local sv-build =
1577        [ intersection $(sv-request) : $(build-requests) ] ;
1578        sv-build ?= "" ;
1579    local BUILD = $(variant) [ split-path $(sv-build) ] ;
1580    local gTARGET_DEFAULT_BUILD($(main-target)) = ;
1581    # the full subvariant to build...
1582    local subvariant = [ expand-target-subvariants $(main-target) : $(variant) : $(toolset) ] ;
1583
1584    local sv-target = ; local sv-properties = ; local sv-toolset = ; local sv-variant = ;
1585    split-target-subvariant sv-target sv-properties sv-toolset sv-variant : $(subvariant) ;
1586    local sv-overrides =
1587        [ difference $(dependent-simple-properties) : [ select-gristed $(sv-properties) ] ] ;
1588    sv-overrides +=
1589        [ get-properties
1590            [ difference $(dependent-simple-properties:G) : $(sv-overrides:G) ] : $(sv-properties) ] ;
1591
1592    if ! $(gTARGET_TYPE($(main-target)))
1593    {
1594        EXIT unknown dependent target $(main-target) ;
1595    }
1596   
1597    # check to make sure we can link against the subvariant
1598    local target-requirements
1599        = [ select-gristed $(gTARGET_REQUIREMENTS($(main-target))) ] ;
1600    local override-conflicts
1601        = [ get-properties $(target-requirements:G) $(gALWAYS_RELEVANT) : $(sv-overrides) ] ;
1602    for local sv-override in $(override-conflicts)
1603    {
1604        local sv-required = [ get-values $(sv-override:G) : $(sv-properties) ] ;
1605        if $(sv-override:G=) != $(sv-required) &&
1606            ! [ is-link-compatible $(sv-override:G) : $(sv-override:G=) : $(sv-required) ]
1607        {
1608            EXIT $(main-target): required property $(sv-override:G)$(sv-required)
1609                incompatible with $(sv-override) ;
1610        }
1611    }
1612
1613    # now that we have a mostly (or completely) compatible subvariant do the overrides
1614    local gTARGET_REQUIREMENTS($(main-target)) =
1615        # property rules...
1616        [ select-ungristed $(gTARGET_REQUIREMENTS($(main-target))) ]
1617        # always relevant properties to target...
1618        [ difference
1619            $(target-requirements) :
1620            [ get-properties [ difference $(sv-overrides:G) : $(gALWAYS_RELEVANT) ] : $(target-requirements) ] ]
1621        # link compatible properties, on the target...
1622        [ get-properties
1623            [ difference $(sv-overrides:G) : $(gALWAYS_RELEVANT) ] : $(target-requirements) ]
1624        # overrides from dependent...
1625        [ get-properties
1626            [ difference $(sv-overrides:G) : $(override-conflicts:G) ] : $(dependent-simple-properties) ]
1627        ;
1628    subvariant = [ expand-target-subvariants $(sv-target) : $(sv-variant) : $(sv-toolset) ] ;
1629    split-target-subvariant sv-target sv-properties sv-toolset sv-variant : $(subvariant) ;
1630
1631    return $(sv-properties) ;
1632}
1633
1634
1635# For each target specified in libs, generate build instructions
1636# for a subvariant that can be linked with a dependent target with
1637# dependent-properties, returning a list of all generated targets.
1638rule link-libraries ( libs * : toolset variant : dependent-simple-properties * )
1639{
1640    local lib-path result ;
1641   
1642    for lib-path in $(libs)
1643    {
1644        local lib-path = [ target-path-of $(lib-path) ] ;
1645        local lib-target = [ target-id-of $(lib-path) ] ;
1646
1647        # Enter the dependee subproject
1648        local [ protect-subproject ] ;
1649        enter-subproject [ directory-of $(lib-path) ] ;
1650
1651        local lib-subvariant = [
1652          find-compatible-subvariant $(lib-target)
1653            : $(toolset) $(variant)
1654              : $(dependent-simple-properties) ] ;
1655
1656        # Generate build instructions for the library target
1657        result += [ subvariant-target $(lib-target) : $(lib-subvariant) : $(toolset) $(variant) ] ;
1658    }
1659    return $(result) ;
1660}
1661
1662# Which configuration(s) to build if nothing is explicitly specified
1663DEFAULT_BUILD ?= debug ;
1664
1665# get-BUILD [target-default-build]
1666#
1667# pick the first of ($(BUILD), $(>), $(DEFAULT_BUILD)) which is set. If it
1668# contains no variants, add variants from $(DEFAULT_BUILD).
1669rule get-BUILD
1670{
1671  local build = $(BUILD) ;
1672  build ?= $(<) ;
1673  build ?= $(DEFAULT_BUILD) ;
1674  local variants = [ select-ungristed $(build) ] ;
1675  if ! $(variants)
1676  {
1677    build += [ select-ungristed $(DEFAULT_BUILD) ] ;
1678  }
1679  return $(build) ;
1680}
1681
1682# declare-fake-targets abstract-target : target-file
1683#
1684#
1685rule declare-fake-targets
1686{
1687    # make a fake target so that it can be built without knowing the suffix
1688    # Since executables under *NIX have no suffix, we'd better check
1689    if $(>) != $(<)
1690    {
1691        DEPENDS $(<) : $(>) ;
1692        NOTFILE $(<) ;
1693    }
1694   
1695    # The following checks that we're in the subdirectory of Jam's invocation
1696    # so that we can arrange for ungristed target names to be built from the
1697    # command-line.
1698    if $(<:G) && [ in-invocation-subdir ]
1699    {
1700        DEPENDS $(<:G=) : $(<) ; # allows $(<:G=) to be used to build all variants
1701        NOTFILE $(<:G=) ;
1702    }
1703}
1704
1705# declare-target-type TYPE : [[<compiler>]<variant>]<feature>value...
1706rule declare-target-type
1707{
1708    gTARGET_TYPE_REQUIREMENTS($(<)) = $(>) ;
1709}
1710
1711declare-target-type DLL : <shared-linkable>true ;
1712
1713if $(NT)
1714{
1715  gIMPORT_SUFFIX(DLL) = .lib ;
1716  gIMPORT_SUFFIX(LIB) = .lib ;
1717  gEXPORT_SUFFIX(DLL) = .lib ;
1718}
1719else
1720{
1721  gIMPORT_SUFFIX(DLL) = .so ;
1722  gIMPORT_SUFFIX(LIB) = .a ;
1723}
1724
1725#
1726# prepare path constants
1727#
1728{
1729    # The names of path variables that are set on targets
1730    .run-path-vars = LD_LIBRARY_PATH PATH PYTHONPATH ;
1731
1732    for local v in $(.run-path-vars)
1733    {
1734        .shell-var($(v)) = $(v) ;
1735    }
1736   
1737    # Dynamic libraries are actually found on PATH
1738    if $(NT) || ( $(UNIX) = CYGWIN )
1739    {
1740        .shell-var(LD_LIBRARY_PATH) = PATH ;
1741    }
1742
1743    # Dynamic libraries search path var is loader, and hence system, dependant.
1744    else
1745    {
1746        .shell-var(LD_LIBRARY_PATH) = $(gSHELL_LIBPATH) ;
1747    }
1748
1749    # The names of path variables in the shell
1750    .run-path-shell-vars = [ unique $(.shell-var($(.run-path-vars))) ] ;
1751   
1752    # Record the original value of each shell variable
1753    for local v in $(.run-path-shell-vars)
1754    {
1755        .run-path-shell-var-value($(v)) = $($(v)) ;
1756    }
1757   
1758    if $(NT)
1759    {
1760        .env-prefix = % ;
1761        .env-suffix = % ;
1762    }
1763    else
1764    {
1765        .env-prefix = "$" ;
1766        .env-suffix = "" ;
1767    }
1768}
1769
1770
1771
1772# Helper
1773rule depend-on-libs ( targets + : libs * )
1774{
1775    LIBPATH on $(<) += [ unique $(gLOCATE($(>))) ] ;
1776    DEPENDS $(<) : $(>) ;
1777    library-dependencies on $(<) += $(>) ;
1778   
1779    # To run these targets, we need everything needed to run the libraries
1780    for local v in $(.run-path-vars)
1781    {
1782        gRUN_$(v)($(<)) = [ unique $(gRUN_$(v)($(<))) $(gRUN_$(v)($(>))) ] ;
1783    }
1784}
1785
1786rule depend-on-static ( targets + : static-libs * )
1787{
1788    local NEEDLIBS = [ unique $(NEEDLIBS) $(>) ] ;
1789    NEEDLIBS on $(<) = [ on $(<) return [ unique $(NEEDLIBS) $(>) ] ] ;
1790    depend-on-libs $(targets) : $(static-libs) ;
1791}
1792
1793rule depend-on-shared ( targets + : dlls-and-import-libs * )
1794{
1795    local linkable ;
1796   
1797    # collect the linkable elements of the source libs into the appropriate variables
1798    for local f in $(dlls-and-import-libs)
1799    {
1800        local v = $(gLINK_VARIABLE($(f:S))) ;
1801        $(v) += $(f) ;
1802        $(v) on $(targets) += $(f) ;
1803        if $(v)
1804        {
1805            linkable += $(f) ;
1806        }
1807    }
1808
1809    FINDLIBS on $(<) += [ unique $(gTARGET_BASENAME($(gTARGET_SUBVARIANT($(>))))) ] ;
1810   
1811    depend-on-libs $(targets) : $(dlls-and-import-libs) ;
1812}
1813
1814# Given build properties, returns the normalised version of the <tag> features for
1815# use by rename-targets.
1816rule get-tag-features ( variant : build-properties * )
1817{
1818    local result = ;
1819    local tags = [ get-properties <tag> : $(build-properties) ] ;
1820    for local tag in $(tags)
1821    {
1822        tag = $(tag:G=) ;
1823        if $(tag:G)
1824        {
1825            result += <tag>$(tag) ;
1826        }
1827        else
1828        {
1829            result += <tag><$(variant)>$(tag) ;
1830        }
1831    }
1832    return $(result) ;
1833}
1834
1835rule generate-dependencies ( main-target : subvariant-targets + )
1836{
1837    local dependencies = $(gTARGET_DEPS($(main-target))) ;
1838    {
1839        # Protect target variables against modification while lib dependencies
1840        # are built. They will be made empty here, and restored when this scope exits
1841        local $(gTARGET_VARIABLES) ;
1842
1843        # extract the simple properties from dependent-properties
1844        local p = $(gBUILD_PROPERTIES) ;
1845        segregate-free-properties p ;
1846
1847        # generate library build instructions
1848        local BUILD = $(BUILD) ;
1849        BUILD ?= $(gTARGET_DEFAULT_BUILD($(main-target))) ;
1850       
1851        for t in static shared
1852        {
1853            local lib-main-targets = [ get-values <$($(t:U)_TYPES)> : $(dependencies) ] ;
1854           
1855            local lib-targets
1856              = [ link-libraries $(lib-main-targets)
1857                  : $(gCURRENT_TOOLSET) $(variant) : $(p)
1858                ] ;
1859            depend-on-$(t) $(subvariant-targets) : $(lib-targets) ;
1860        }
1861    }
1862}
1863
1864# Given main-target, a main target name gristed with $(SOURCE_GRIST), generate build
1865# instructions for a subvariant target using the given toolset, variant, etc.
1866#
1867# RETURNS: the a list of target names for the files built by the subvariant. If
1868# the main-target is a library, the first filename is the one that should be linked
1869# into a dependent target.
1870rule subvariant-target ( main-target : subvariant-id build-properties * : toolset variant )
1871{
1872  # SOURCE_GRIST identifies the subproject directory; TARGET_GRIST will identify
1873  # the target and subvariant, since unique versions of files will be built for
1874  # that combination.
1875  local property-tags = [ get-tag-features $(variant) : $(build-properties) ] ;
1876  local tags = [ get-properties <tag> : $(gIMPOSED_REQUIREMENTS($(main-target))) ] $(property-tags) ;
1877  local TARGET_GRIST = [ join-path $(SOURCE_GRIST) $(main-target:G=) $(subvariant-id) ] ;
1878  local subvariant = $(main-target:G=$(TARGET_GRIST)) ;
1879
1880  # Keep track of the generated targets.
1881  if ! $(TARGET_GRIST) in $(gDECLARED_TARGETS)
1882  {
1883    gDECLARED_TARGETS += $(TARGET_GRIST) ;
1884  }
1885
1886  # Make sure we know how to generate these types of targets.
1887  local target-type = $(gTARGET_TYPE($(main-target))) ;
1888  if ! $(target-type)
1889  {
1890      EXIT unknown target type for $(main-target) ;
1891  }
1892 
1893  gTARGET_TYPE($(subvariant)) = $(target-type) ;
1894 
1895  # LOCATE_TARGET affects where built targets are generated. We move it
1896  # relative to the default location based on the subvariant
1897  local LOCATE_TARGET
1898    = [ join-path $(LOCATE_TARGET) $(main-target:G=) $(subvariant-id) ] ;
1899
1900  # The renamed base name of the target. Only considers the tags defined directly
1901  # on the target.
1902  if $(gTARGET_NAME($(main-target)))
1903  {
1904    gTARGET_BASENAME($(main-target)) =
1905      [ rename-target $(gTARGET_NAME($(main-target))) : [ split-path [ ungrist $(subvariant:G) ] ] : $(property-tags) ] ;
1906  }
1907
1908  # First order names have the suffix, if any according to the platform.
1909  local target-files = [ FAppendSuffix $(subvariant) : $(SUF$(target-type)) ] ;
1910  # Second order names have any tags as imposed from stage target contexts.
1911  target-files = [ rename-target $(target-files) : [ split-path [ ungrist $(subvariant:G) ] ] : $(tags) ] ;
1912  # Third order names are customized as determined by a rename rule on the target type.
1913  if $(gNAME_ADJUST($(target-type)))
1914  {
1915    target-files = [
1916      $(gNAME_ADJUST($(target-type))) $(target-files)
1917      : $(subvariant-id) $(build-properties)
1918      : $(toolset) $(variant) ] ;
1919    gTARGET_TYPE($(target-files[1])) = $(target-type) ;
1920  }
1921
1922  # Do nothing if we already have the build instructions for the specific
1923  # target files of this subvariant target.
1924  if ! $(target-files) in $(gTARGET_FILES($(main-target)))
1925  {
1926    gTARGET_SUBVARIANT($(target-files)) = $(main-target) ;
1927   
1928    ###gTARGET_FILES($(subvariant)) = $(target-files) ;
1929    gTARGET_FILES($(main-target)) += $(target-files) ;
1930
1931    # Remember the path from the build root to the subvariant directory
1932    gSUBVARIANT_PATH($(subvariant)) = $(subvariant-id) ;
1933   
1934    # Add target suppression if <suppress> was in the requirements
1935    local gSUPPRESS_FAKE_TARGETS = [ get-values <suppress> : $(gTARGET_REQUIREMENTS($(main-target))) ] $(gSUPPRESS_FAKE_TARGETS) ;
1936
1937    declare-fake-targets $(main-target) : $(target-files) ;
1938
1939    # set up gBUILD_PROPERTIES for include-tools (below)
1940    local gBUILD_PROPERTIES = $(build-properties) ;
1941
1942    # Include the toolset specification. This will set up the global flags
1943    # variables in a way appropriate to this build.
1944   
1945    include-tools $(toolset) ;
1946
1947    # headers should be identified specific to the target, since search paths
1948    # may differ for different subvariants. The same header name or relative
1949    # path may refer to different files.
1950    local HDRGRIST = [ join $(SOURCE_GRIST) $(STDHDRS) $(SYSHDRS) $(HDRS) "" : "#" ] ;
1951   
1952    # transfer target variables to the target file.
1953    set-target-variables $(target-files) ;
1954
1955    local dependencies
1956        = [ get-values <$(STATIC_TYPES)> <$(SHARED_TYPES)>
1957          : $(gTARGET_DEPS($(main-target)))
1958        ] ;
1959     
1960    if $(dependencies)
1961    {
1962        # include each jamfile describing a dependee target.
1963        dependent-include $(dependencies) ;
1964        generate-dependencies $(main-target) : $(target-files) ;
1965    }
1966   
1967    local generator = $(gGENERATOR_FUNCTION($(target-type))) ;
1968    local sources = $(gTARGET_SOURCES($(main-target))) ;
1969    $(generator) $(target-files) : $(sources) ;
1970                       
1971    $(gTARGET_VARIABLES) = ; # Be sure that we don't mask bugs with lingering target variables
1972  }
1973  return $(target-files) ;
1974}
1975
1976# Generate the expanded subvariants of a target.
1977#
1978rule expand-target-subvariants ( target : local-build * : tools + : )
1979{
1980    local BUILD = [ get-BUILD $(local-build) ] ;
1981    local variants = [ select-ungristed $(BUILD) ] ;
1982    local build-request = [ difference $(BUILD) : $(variants) ] ;
1983
1984    local subvariants = ;
1985    for local toolset in $(tools)
1986    {
1987        for local variant in $(variants)
1988        {
1989            local rules = [ select-ungristed
1990                $(gTARGET_REQUIREMENTS($(target)))
1991                $(gIMPOSED_REQUIREMENTS($(target))) ] ;
1992            local requirements = [ select-gristed
1993                $(gTARGET_REQUIREMENTS($(target)))
1994                $(gIMPOSED_REQUIREMENTS($(target))) ] ;
1995           
1996            local expanded
1997                = [ expand-build-request $(toolset) $(variant) $(target)
1998                    : $(requirements) : $(build-request) ] ;
1999           
2000            local gNOWARN_INCOMPATIBLE_BUILDS = TRUE ;
2001           
2002            for local instance in $(expanded)
2003            {
2004                local properties = [ split-path-at-grist $(instance) ] ;
2005                for local r in $(rules)
2006                {
2007                    properties = [ $(r) $(toolset) $(variant) : $(properties) ] ;
2008                }
2009               
2010                if ! ( <build>no in $(properties) )
2011                {
2012                    # the rules may have modified the build request, reconstruct it
2013                    properties = [ expand-build-request $(toolset) $(variant) $(target)
2014                      : $(properties[2-]) : $(build-request) ] ;
2015                   
2016                    subvariants += $(target)|$(properties)|$(toolset)|$(variant) ;
2017                }
2018                else if --dump-unbuilt
2019                {
2020                    ECHO **** skipping build of $(target); toolset= $(toolset) variant= $(variant) **** ;
2021                }
2022            }
2023        }
2024    }
2025    return [ unique $(subvariants) ] ;
2026}
2027
2028# Given an expanded subvariant of a terget, sets the various variables accordingly.
2029#
2030rule split-target-subvariant ( target-var properties-var toolset-var variant-var : subvariant )
2031{
2032    local subvariant-items = [ MATCH (.*)[|](.*)[|](.*)[|](.*) : $(subvariant) ] ;
2033    $(target-var) = $(subvariant-items[1]) ;
2034    $(properties-var) = [ split-path-at-grist $(subvariant-items[2]) ] ;
2035    $(toolset-var) = $(subvariant-items[3]) ;
2036    $(variant-var) = $(subvariant-items[4]) ;
2037    return $((target-var)) ;
2038}
2039
2040# main-target target : local-build
2041#
2042# Generates requested subvariant build instructions for the given main target
2043rule main-target
2044{
2045    local subvariants = [ expand-target-subvariants $(<) : $(>) : $(TOOLS) ] ;
2046
2047    # include each jamfile describing a dependee target.
2048    dependent-include [ get-values <$(STATIC_TYPES)> <$(SHARED_TYPES)> : $(gTARGET_DEPS($(<))) ] ;
2049
2050    for local subvariant in $(subvariants)
2051    {
2052        local target = ;
2053        local properties = ;
2054        local toolset = ;
2055        local variant = ;
2056        split-target-subvariant target properties toolset variant : $(subvariant) ;
2057        subvariant-target $(target) : $(properties) : $(toolset) $(variant) ;
2058    }
2059}
2060
2061# Declare an executable target.
2062#
2063gTARGET_TYPE_ID(exe) = EXE ;
2064gGENERATOR_FUNCTION(EXE) = executable-file ;
2065rule exe ( target : sources + : requirements * : default-build * )
2066{
2067    declare-local-target $(target) : $(sources) : $(requirements) : $(default-build) : EXE ;
2068}
2069
2070# Declare a shared library target.
2071#
2072gTARGET_TYPE_ID(dll) = DLL ;
2073gGENERATOR_FUNCTION(DLL) = dll-files ;
2074gIS_DEPENDENCY(DLL) = TRUE ;
2075rule dll ( target : sources + : requirements * : default-build * )
2076{
2077    if $(JAMUNAME[1]) = OpenBSD
2078    {
2079        if ! [ get-values <dllversion> : $(requirements) ]
2080        {
2081            requirements += <dllversion>0.0 ;
2082        }
2083    }
2084    declare-local-target $(target) : $(sources) : $(requirements) : $(default-build) : DLL ;
2085}
2086
2087# Declare a statically-linked library target.
2088#
2089gTARGET_TYPE_ID(lib) = LIB ;
2090gGENERATOR_FUNCTION(LIB) = library-file ;
2091gIS_DEPENDENCY(LIB) = TRUE ;
2092rule lib ( target : sources + : requirements * : default-build * )
2093{
2094    declare-local-target $(target) : $(sources) : $(requirements) : $(default-build) : LIB ;
2095}
2096
2097# Declare a template target for other targets. This is a modifier only. It
2098# Adds the specs specified here to any other target it's a dependee of.
2099#
2100gTARGET_TYPE_ID(template) = TEMPLATE ;
2101gMODIFIER_FUNCTION(TEMPLATE) = template-modifier ;
2102gIS_DEPENDENCY(TEMPLATE) = TRUE ;
2103gNO_TARGET_TYPE_REQUIREMENT(TEMPLATE) = TRUE ;
2104rule template ( target : sources * : requirements * : default-build * )
2105{
2106    declare-local-target $(target) : $(sources) : $(requirements) : $(default-build) : TEMPLATE ;
2107}
2108
2109# Declare an executable target, to be run by tests.
2110rule unit-test ( target +  : sources + : requirements * : default-build * : cmd-line * )
2111{
2112    if ! $(.testing.jam-included)
2113    {
2114        SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
2115        include testing.jam ;
2116    }
2117   
2118    DEPENDS all
2119      : [ run $(sources)
2120          : $(cmd-line)
2121          : # input-files
2122          : $(requirements)
2123          : $(target)
2124          : $(default-build)
2125        ]
2126      ;
2127}
2128
2129# Used to build command files from a list of sources.
2130rule build-command-file ( command : sources * : prefix ? line-break ? )
2131{
2132    # Clean up after ourselves
2133    Clean clean : $(command) ;
2134   
2135    DEPENDS $(command) : $(sources) ;
2136   
2137    PREFIX on $(command) = $(prefix:E=) ;
2138   
2139    local ' _  = "" ;
2140   
2141    if ! $(NT)
2142    {
2143        ' = ' ;
2144        _ = " " ;
2145    }
2146       
2147    ' on $(command) = $(') ;
2148    _ on $(command) = $(_) ;
2149   
2150    EOL on $(command) = \"$(line-break:E=)$(')$(_)>>$(_)\" ;
2151    BOL on $(command) = "\"
2152echo $(')$(prefix:E=)\"" ;
2153   
2154    # Check whether there's anything to dump, so that we don't end up
2155    # executing a line of the form:
2156    #
2157    #    echo >> file.CMD
2158    #
2159    # on Windows this writes "echo is on." into the command-file,
2160    # which then breaks the link.
2161   
2162    if $(sources)
2163    {
2164        # Handle the first target specially, so that the first source file
2165        # will clear the command file
2166        command-file-dump $(command) : $(sources) ;
2167    }   
2168}
2169
2170# Quietly delete $(x) if it exists with $(RM1)"$(x)" 
2171if $(NT)
2172{
2173    RM1 = "IF EXIST " "DEL " ;
2174}
2175else
2176{
2177    RM1 = "$(RM) " ;
2178}
2179
2180# Build the command-file
2181actions quietly command-file-dump
2182{
2183    $(RM1)"$(<)"
2184    echo $(')$(PREFIX)"$(>:J=$(EOL)$(<)$(BOL))"$(')$(_)>>$(_)$(<)
2185}
2186
2187# Clean up the temporary COMMAND-FILE used to build TARGETS.
2188rule remove-command-file ( targets + : command-file )
2189{
2190    TEMPORARY $(command-file) ;
2191    Clean clean : $(command-file) ; # Mark the file for removal via clean
2192}
2193actions ignore quietly piecemeal together remove-command-file
2194{
2195    $(RM) $(>)
2196}
2197
2198# build TARGETS from SOURCES using a command-file, where RULE-NAME is
2199# used to generate the build instructions from the command-file to
2200# TARGETS
2201rule with-command-file ( rule-name targets * : sources * : prefix ? line-break ? )
2202{
2203    # create a command-file target and place it where the first target
2204    # will be built
2205    local command-file = $(targets[1]:S=.CMD) ;
2206    LOCATE on $(command-file) = $(gLOCATE($(targets[1]))) ;
2207    build-command-file $(command-file) : $(sources) : $(prefix) $(line-break) ;
2208
2209    # Build the targets from the command-file instead of the sources
2210    DEPENDS $(targets) : $(command-file) ;
2211    local result = [ $(rule-name) $(targets) : $(command-file) ] ;
2212
2213    # clean up afterwards
2214    # Can't really do this until <find-library> arguments are accounted for.
2215    # remove-command-file $(targets) : $(command-file) ;
2216    return $(result) ;
2217}
2218
2219TAG(prefix) = "" ;
2220TAG(postfix) = "" ;
2221
2222# GIVEN:
2223#
2224# A target subvariant, the subvariant info, and a set of rename tags.
2225#
2226# RESULT:
2227#
2228# Uses the rename tags, and the global TAG map, to append a tag to the
2229# target basename. The new subvariant target is returned. The tag for
2230# the target is composed from the subvariant info and the corresponding
2231# entry in the tags. This creates the tag in the order as given by the
2232# subvariant info.
2233#
2234# EXAMPLE:
2235#
2236# [ rename-target <gcc/debug>libtest.so : gcc debug : <tag><gcc>_gcc <tag><debug>_debug ]
2237#
2238# RETURNS:
2239#
2240# <gcc/debug>libtest_gcc_debug.so
2241#
2242rule rename-target ( target + : subvariant * : tags * )
2243{
2244    local tag-values = ;
2245    for local tag in $(tags)
2246    {
2247        local tag-tokens = [ MATCH (<)(.*)(>)(.*) : $(tag:G=) ] ;
2248        tag-tokens = $(tag-tokens[2]) $(tag-tokens[4]) ;
2249        tag-values += $(tag-tokens[2]:G=$(tag-tokens[1])) ;
2250    }
2251
2252    local tag-text = "" ;
2253
2254    # the prefix of the tag...
2255    #
2256    local prefix-tag = [ get-values <prefix> : $(tag-values) $(TAG(prefix):G=prefix) ] ;
2257    tag-text = $(prefix-tag[1]) ;
2258
2259    # the subvariant tags...
2260    #
2261    for local sv in $(subvariant)
2262    {
2263        local sv-tag = [ get-values <$(sv)> : $(tag-values) $(TAG($(sv)):G=$(sv)) ] ;
2264        if $(sv-tag)
2265        {
2266            tag-text = $(tag-text)$(sv-tag[1]) ;
2267        }
2268    }
2269
2270    # the postfix of the tag...
2271    #
2272    local postfix-tag = [ get-values <postfix> : $(tag-values) $(TAG(postfix):G=postfix) ] ;
2273    tag-text = $(tag-text)$(postfix-tag[1]) ;
2274
2275    local renamed-target = ;
2276    for local t in $(target)
2277    {
2278        local B-S = [ MATCH ([^\\.]*)(.*) : $(t:G=) ] ;
2279        local B = $(B-S[1]) ; B ?= "" ;
2280        local S = $(B-S[2]) ; S ?= "" ;
2281        local new-name = $(B)$(tag-text)$(S) ; new-name = $(new-name:G=$(t:G)) ;
2282        renamed-target += $(new-name) ;
2283    }
2284    return $(renamed-target) ;
2285}
2286
2287rule grist-targets ( targets + : subdir-tokens * )
2288{
2289    local subdir-grist = "" ;
2290    if $(subdir-tokens)
2291    {
2292        subdir-grist = [ FGrist $(subdir-tokens) ] ;
2293        if $(SOURCE_GRIST)
2294        {
2295            subdir-grist = "!$(subdir-grist)" ;
2296        }
2297    }
2298    if ! $(SOURCE_GRIST)
2299    {
2300        return $(targets:G=$(subdir-grist)) ;
2301    }
2302    else
2303    {
2304        return $(targets:G=$(SOURCE_GRIST)$(subdir-grist)) ;
2305    }
2306}
2307
2308# EXAMPLE:
2309#
2310# stage test-stage
2311#   : <exe>foo/bar/test1 <dll>qwerty/keys docs/README
2312#   : <tag><prefix>"_" <tag><debug>"D" <tag><profile>"P" <tag><gcc>"GCC"
2313#   : debug profile <suppress>true
2314#   ;
2315#
2316# PRODUCES:
2317#
2318# test-stage/libkeys_GCCD.so
2319# test-stage/libkeys_GCCP.so
2320# test-stage/test1_GCCD
2321# test-stage/test1_GCCP
2322# test-stage/README
2323#
2324# IFF:
2325#
2326# $shell> jam test-stage
2327#
2328rule stage ( name : sources + : requirements * : local-build * )
2329{
2330    if ! $(gIN_LIB_INCLUDE)
2331    {
2332
2333    local stage-id =
2334        [ grist-targets $(name) ] ;
2335    local arch-subdirs = [ get-values <architecture-subdirs> : $(requirements) ] ;
2336    local tree-root = [ get-values <tree-subdirs> : $(requirements) ] ;
2337    if $(tree-root) { tree-root = [ split-path $(tree-root[1]) ] ; }
2338    local locate = [ get-values <locate> : $(requirements) ] ;
2339    if $(locate) { locate = [ split-path $(locate) ] ; }
2340    local fake-target = [ get-values <target> : $(requirements) ] ;
2341    local rename-rule = [ get-values <rename> : $(requirements) ] ;
2342
2343    # Supress the regular build of this target
2344    local gSUPPRESS_FAKE_TARGETS = [ get-values <suppress> : $(local-build) ] ;
2345
2346    local stage-dir = $(name:G=) ;
2347    local files ;
2348    local file-mode ;
2349    local file-tagged ;
2350    local file-subdir ;
2351
2352    # Prevent built object from getting deleted so that when targets are linked
2353    # multiple times they are available.
2354    local KEEPOBJS = true ;
2355
2356    # For each source, collect its information, and possibly generate it.
2357    #
2358    for local source in $(sources)
2359    {
2360        source = [ split-qualified-property $(source) ] ;
2361        local source-build = [ MATCH "^<([^>]*)>" : $(source[1-2]) ] ;
2362        source = [ expand-source-names $(source[3]) ] ;
2363
2364        if $(source:G)
2365        {
2366            local gIN_LIB_INCLUDE = TRUE ;
2367
2368            local target = $(source:D=:G=) ;
2369            local target-id = [ target-id-of $(source) ] ;
2370            local target-subdir = [ directory-of [ target-path-of $(source) ] ] ;
2371
2372            dependent-include $(source:G=) ;
2373            local gIMPOSED_REQUIREMENTS($(target-id)) = $(requirements) ;
2374            local subvariants = [ expand-target-subvariants $(target-id) : $(local-build) : $(TOOLS) ] ;
2375
2376            for local subvariant in $(subvariants)
2377            {
2378                local s-target = ;
2379                local s-properties = ;
2380                local s-toolset = ;
2381                local s-variant = ;
2382                split-target-subvariant s-target s-properties s-toolset s-variant : $(subvariant) ;
2383                local s-subdir ;
2384                if $(arch-subdirs)
2385                {
2386                    local arch = [ get-values <instruction-set> : $(s-properties) ] ;
2387                    arch ?= [ get-values <architecture> : $(s-properties) ] ;
2388                    arch ?= $(OSPLAT:L) ;
2389                    if $(arch) = "default" { arch = $(OSPLAT:L) ; }
2390                    arch += [ get-values <address-model> : $(s-properties) ] ;
2391                    arch += $(OS:L) ;
2392                    s-subdir = $(arch:J=-) ;
2393                }
2394               
2395                local source-build-rule = [ MATCH "[`]([^`]+)[`]" : $(source-build[2]) ] ;
2396                if  ( $(s-toolset) = $(source-build[1]) || $(source-build[1]) = * ) &&
2397                        ( $(s-variant) = $(source-build[2]) || $(source-build[2]) = * ) ||
2398                    $(source-build-rule) && [ $(source-build-rule) $(s-toolset) $(s-variant) ]
2399                {
2400
2401                    local target-subvariant = ;
2402                    {
2403                        local [ protect-subproject ] ;
2404                        enter-subproject $(target-subdir) ;
2405                        target-subvariant =
2406                            [ subvariant-target $(s-target) : $(s-properties) : $(s-toolset) $(s-variant) ] ;
2407                    }
2408
2409                    local sv-files = ;
2410                    for local sv in $(target-subvariant)
2411                    {
2412                        local sv-file = $(gFILES($(sv))) ;
2413                        sv-file ?= $(sv) ;
2414                        sv-files += $(sv-file) ;
2415                    }
2416                    sv-files = [ unique $(sv-files) ] ;
2417                    for local sv in $(sv-files)
2418                    {
2419                        local renamed-target ;
2420                        local split-properties = [ split-path $(s-properties[1]) ] ;
2421                        for local rr in $(rename-rule)
2422                        {
2423                            renamed-target += [ $(rr) $(sv) : $(split-properties) ] ;
2424                        }
2425                        renamed-target ?=
2426                            [ rename-target $(sv) : [ split-path $(s-properties[1]) ] : ] ;
2427
2428                        files += $(sv) ;
2429                        file-mode($(sv)) = $($(gTARGET_TYPE($(s-target)))MODE) ;
2430                        file-tagged($(sv)) = $(renamed-target) ;
2431                        file-subdir($(sv)) = $(s-subdir) ;
2432                    }
2433
2434                }
2435            }
2436        }
2437        else
2438        {
2439            local renamed-file ;
2440            for local rr in $(rename-rule)
2441            {
2442                renamed-file += [ $(rr) $(source) ] ;
2443            }
2444            renamed-file ?= $(source) ;
2445           
2446            files += $(source) ;
2447            file-tagged($(source)) = $(renamed-file) ;
2448        }
2449    }
2450
2451    # Generate and collect the file copy build instructions. If we
2452    # are getting defined in the dependent phase skip the actual instructions.
2453    #
2454    local destination-files = ;
2455    local result-files = ;
2456    local locate-target = $(locate) ;
2457    if $(ALL_LOCATE_TARGET)
2458    {
2459        locate-target ?= [ join-path [ split-path $(ALL_LOCATE_TARGET) ] $(SUBDIR_TOKENS) ] ;
2460    }
2461    locate-target ?= [ split-path $(SUBDIR) ] ;
2462    for local file in $(files)
2463    {
2464        local destination-file ;
2465        local destination-subdir ;
2466        if $(file:G)
2467        {
2468            destination-file = $(file-tagged($(file)):G=:D=) ;
2469            destination-subdir = $(file-subdir($(file))) ;
2470        }
2471        else
2472        {
2473            destination-file = $(file-tagged($(file)):D=) ;
2474            if $(tree-root)
2475            {
2476                destination-subdir = [ strip-initial $(tree-root) : [ split-path $(file:D) ] ] ;
2477            }
2478        }
2479        destination-file =
2480            [ grist-targets $(destination-file) : [ split-path $(stage-dir) ] $(destination-subdir) ] ;
2481        destination-files += $(destination-file) ;
2482        {
2483            local FILEMODE = $(FILEMODE) ;
2484            if $(file-mode($(file))) { FILEMODE = $(file-mode($(file))) ; }
2485            MakeLocate $(destination-file) :
2486                [ FDirName $(locate-target) [ split-path $(stage-dir) ] $(destination-subdir) ] ;
2487            for local df in $(destination-file)
2488            {
2489                result-files += $(df) ;
2490                FileClone $(df) : $(file) ;
2491            }
2492            local target = $(stage-id) $(destination-subdir) $(destination-file:G=) ;
2493            declare-fake-targets $(target:J=/) : $(destination-file) ;
2494        }
2495    }
2496
2497    # Don't expose fake targets when suppressing default builds.
2498    # But honor requirement to expose sources through given <target>.
2499    #
2500    if ! $(fake-target)
2501    {
2502        declare-fake-targets $(stage-id:G=) : $(destination-files) ;
2503    }
2504    else
2505    {
2506        if $(gSUPPRESS_FAKE_TARGETS)
2507        {
2508            declare-fake-targets $(fake-target) : $(files) ;
2509        }
2510        else
2511        {
2512            declare-fake-targets $(fake-target) : $(destination-files) ;
2513        }
2514    }
2515
2516    Clean clean : $(destination-files) ;
2517
2518    return $(result-files) ;
2519
2520    }
2521}
2522
2523# GIVEN:
2524#
2525# A bare target, either with or without grist.
2526#
2527# RETURNS:
2528#
2529# The fully qualified and gristed target ID.
2530#
2531# EXAMPLE:
2532#
2533# [ target-id-of <lib>../../sub1/sub2/test.dll ]
2534#
2535# RETURNS:
2536#
2537# <sub1!sub2>test.dll
2538#
2539rule target-id-of ( target-ref )
2540{
2541    local grist = $(target-ref:G) ;
2542    local target = $(target-ref:G=) ;
2543    while $(target:G)
2544    {
2545        grist += $(target:G) ;
2546        target = $(target:G=) ;
2547    }
2548    local path = [ directory-of $(target) ] ;
2549    if ! [ MATCH "^(@)" : $(path) ]
2550    {
2551        path = [ join @$(PROJECT) [ simplify-path-tokens [ top-relative-tokens $(path) ] ] : / ] ;
2552    }
2553    local tokens = [ split-path $(path) ] ;
2554    local project-name = [ MATCH "^@([^/\\]+)" : $(tokens[1]) ] ;
2555    if $(project-name)
2556    {
2557        tokens = $(tokens[2-]) ;
2558    }
2559    project-name ?= $(PROJECT) ;
2560    local SOURCE_GRIST = [ FGrist @$(project-name) [ simplify-path-tokens $(tokens) ] ] ;
2561    local target-id = [ FGristFiles $(target:D=) ] ;
2562    return $(target-id) ;
2563}
2564
2565#
2566#
2567rule target-path-of ( target-ref )
2568{
2569    local grist = $(target-ref:G) ;
2570    local target = $(target-ref:G=) ;
2571    while $(target:G)
2572    {
2573        grist += $(target:G) ;
2574        target = $(target:G=) ;
2575    }
2576    local path = [ directory-of $(target) ] ;
2577    if ! [ MATCH "^(@)" : $(path) ]
2578    {
2579        path = [ join @$(PROJECT) [ simplify-path-tokens [ top-relative-tokens $(path) ] ] : / ] ;
2580    }
2581    path = $(path)/$(target:D=) ;
2582    if $(grist)
2583    {
2584        path = $(grist:J="")$(path) ;
2585    }
2586    return $(path) ;
2587}
2588
2589# Common rules for generating a single tag based on the
2590# variant, build properties, and the toolset used to build.
2591# To use place this rule name in the requirementes section of
2592# a stage target.
2593#
2594# The tag is constructed as such:
2595#
2596#   [-<toolset-tag>][-<thread-tag>][-<runtime-tag>][-<version-tag>]
2597#
2598#   <toolset-tag> maps to an abbreviated name of the toolset
2599#   and when possible and applicable the version of the toolset.
2600#
2601#   <thread-tag> "mt" when multi-threading is enabled.
2602#
2603#   <runtime-tag> adds these single letter tags:
2604#       "s" when static linking to runtime
2605#       "g" when linking to debug runtime
2606#       "y" when building debug-python variants
2607#       "d" when building debug variants
2608#       "p" when building with stlport libraries
2609#       "n" when building with stlport and using native iostreams
2610#
2611# The tag added is a <tag><prefix> to allow for additional tags.
2612#
2613rule common-variant-tag ( toolset variant : properties * )
2614{
2615    local tags = ;
2616   
2617    local thread-tag = ;
2618    if <threading>multi in $(properties) { thread-tag = mt ; }
2619   
2620    local runtime-tag = ;
2621    if <runtime-link>static in $(properties) { runtime-tag += s ; }
2622    if <runtime-build>debug in $(properties) { runtime-tag += g ; }
2623    if [ MATCH .*(debug-python).* : $(variant) ] { runtime-tag += y ; }
2624    else { if [ MATCH .*(debug).* : $(variant) ] { runtime-tag += d ; } }
2625    if [ MATCH .*(stlp).* : $(toolset) ] ||
2626        [ MATCH .*(stlp).* : $(properties:G) ]
2627    { runtime-tag += p ; }
2628    if <stlport-iostream>off in $(properties) { runtime-tag += n ; }
2629   
2630    local toolset-tag = ;
2631    if ! $(gUNVERSIONED_VARIANT_TAG)
2632    {
2633        local include-minor-version = YES ;
2634        switch $(toolset)
2635        {
2636            case borland* : toolset-tag += bcb ;
2637            case como* : toolset-tag += como ;
2638            case cwpro8* : toolset-tag += cw 8 ;
2639            case cwpro9* : toolset-tag += cw 9 ;
2640            case cw-* : toolset-tag += cw ; include-minor-version = ;
2641            case darwin* : toolset-tag += ;
2642            case edg* : toolset-tag += edg ;
2643            case gcc* : toolset-tag += gcc ;
2644            case intel-linux* : toolset-tag += il ;
2645            case intel-win32* : toolset-tag += iw ;
2646            case kcc* : toolset-tag += kcc ;
2647            case kylix* : toolset-tag += bck ;
2648            case metrowerks* : toolset-tag += cw ;
2649            case mingw* : toolset-tag += mgw ;
2650            case mipspro* : toolset-tag += mp ;
2651            case msvc* : toolset-tag += vc 6 ;
2652            case sunpro* : toolset-tag += sw ;
2653            case tru64cxx* : toolset-tag += tru ;
2654            case vacpp* : toolset-tag += xlc ;
2655            case vc[678][_]* :
2656            {
2657                toolset-tag += vc ;
2658                toolset-tag += [ MATCH "vc([678])[_]([0123456789]*)" : $(toolset) ] ;
2659            }
2660            case vc[678]* :
2661            {
2662                toolset-tag += vc ;
2663                toolset-tag += [ MATCH "vc([678])" : $(toolset) ] ;
2664            }
2665            case * :
2666            toolset-tag += [ MATCH "^([^-]*)" : $(toolset) ] ;
2667        }
2668        if $(include-minor-version)
2669        {
2670            toolset-tag += [ MATCH "[-]([0123456789]+)[_.]([0123456789]*)" : $(toolset) ] ;
2671        }
2672        else
2673        {
2674            toolset-tag += [ MATCH "[-]([0123456789]+)[_.][0123456789]*" : $(toolset) ] ;
2675        }
2676       
2677        # boost/config/auto_link.hpp expects toolset tags that do not always
2678        # match the above algorithm for MSVC 6.x and 7.0.
2679        #
2680        switch $(toolset-tag:J=)
2681        {
2682            case vc6* : toolset-tag = vc 6 ;
2683            case vc70 : toolset-tag = vc 7 ;
2684        }
2685    }
2686   
2687    local version-tag = ;
2688    if ! $(gUNVERSIONED_VARIANT_TAG)
2689    {
2690        local version-number = [ get-values <version> : $(properties) ] ;
2691        version-number ?= $(BOOST_VERSION) ;
2692        version-tag = [ MATCH "^([^.]+)[.]([^.]+)[.]([^.]+)" : $(version-number[1]) ] ;
2693        if $(version-tag[3]) = 0
2694        {
2695            version-tag = $(version-tag[1-2]) ;
2696        }
2697        version-tag = $(version-tag:J="_") ;
2698    }
2699   
2700    tags += $(toolset-tag:J=) ;
2701    tags += $(thread-tag:J=) ;
2702    tags += $(runtime-tag:J=) ;
2703    tags += $(version-tag) ;
2704   
2705    if $(tags)
2706    {
2707        return $(properties) <*><*><tag><prefix>-$(tags:J=-) ;
2708    }
2709    else
2710    {
2711        return $(properties) ;
2712    }
2713}
2714
2715# Recursive version of GLOB. Builds the glob of files while
2716# also searching in the subdirectories of the given root.
2717#
2718rule glob-tree ( root : patterns * )
2719{
2720    local e ;
2721    local f = [ GLOB $(root) : $(patterns) ] ;
2722    local files ;
2723    for e in $(f)
2724    {
2725        if $(e:D=) != CVS { files += $(e) ; }
2726    }
2727    local d = [ difference [ GLOB $(root) : * ] : $(files) ] ;
2728    for e in $(d)
2729    {
2730        if ! ( $(e:D=) in . .. ) { files += [ glob-tree $(e) : $(patterns) ] ; }
2731    }
2732    return $(files) ;
2733}
2734
2735rule unless ( test * : no-value * : yes-value * )
2736{ if ! $(test) { return $(no-value) ; } else { return $(yes-value) ; } }
2737
2738rule cond ( test * : yes-value * : no-value * )
2739{ if $(test) { return $(yes-value) ; } else { return $(no-value) ; } }
2740
2741# If the toolset matches the given regex pattern, modify the
2742# subvariant-path and properties for static linking
2743rule force-NT-static-link ( pattern : toolset : subvariant-path properties * )
2744{
2745    if  $(NT) && [ MATCH $(pattern) : $(toolset) ]
2746    {
2747        properties = [ impose-requirements $(properties) :
2748            <runtime-link>static ] ;
2749    }
2750
2751    return $(subvariant-path) $(properties) ;
2752}
2753
2754# Stick this rule name in your requirements if you are building code
2755# which requires locale support.  It handles the metrowerks-specific
2756# case that locale support demands the static version of the runtime
2757# library.
2758rule std::locale-support ( toolset variant : subvariant-path properties * )
2759{
2760    return [
2761      force-NT-static-link .*(cw-8).*
2762        : $(toolset) : $(subvariant-path) $(properties)
2763          ] ;
2764}
2765
2766# Stick this rule name in your requirements if you are building code
2767# which requires facet support.  It handles the intel-win32-specific
2768# case that facet support seems to demand the static version of the
2769# runtime library.
2770rule std::facet-support ( toolset variant : subvariant-path properties * )
2771{
2772    return [
2773      force-NT-static-link .*(intel).*
2774        : $(toolset) : $(subvariant-path) $(properties)
2775          ] ;
2776}
2777
2778# load the specified modules if they haven't been loaded already.  If
2779# the module has no suffix, ".jam" is appended.  If the module name is
2780# prepended with a path, it is sought in that location relative to the
2781# current Jamfile, otherwise it is sought in BOOST_BUILD_PATH.
2782rule import ( modules + )
2783{
2784    for local name in $(modules)
2785    {
2786        local search = $(BOOST_BUILD_PATH) ;  # search here
2787        local n = $(name:D=) ;                # for this basename
2788        if ! $(n:S)
2789        {
2790            n = $(n).jam ;
2791        }
2792       
2793        # if a directory was specified
2794        local d = $(name:D) ;
2795        if $(d)
2796        {
2797            # Normalize the path relative to the invocation directory.
2798            n = [ root-paths $(n) : $(d:R=$(SUBDIR)) ] ;
2799            n = [ root-paths $(n) : [ PWD ] ] ;
2800            search = ; # no searching; the path was specified.
2801        }
2802       
2803        SEARCH on $(n) = $(search) ;
2804       
2805        if ! $($(n).included)
2806        {
2807            include $(n) ;
2808            $(n).included = true ;
2809        }
2810    }
2811}
2812
2813# Declare a project's installable sources (raw sources or built targets)
2814#
2815rule install (
2816    name # The name to refer to these set of targets/sources.
2817    type # The type of targets/sources, and therefore their install location.
2818    : sources + # The targets and sources to make available for installation.
2819    : options *
2820    )
2821{
2822    if $(gINSTALL_SOURCES)
2823    {
2824        local _include_ ;
2825        if $(gINSTALL_INCLUSIONS)
2826        {
2827            if $(name) in $(gINSTALL_INCLUSIONS)
2828            {
2829                _include_ = true ;
2830            }
2831        }
2832        else if ! $(name) in $(gINSTALL_EXCLUSIONS)
2833        {
2834            _include_ = true ;
2835        }
2836        if $(_include_)
2837        {
2838            local result ;
2839            for local source in $(sources)
2840            {
2841                result += [ target-path-of $(source) ] ;
2842            }
2843            if ! $(result) in $(gINSTALL_SOURCES($(type)))
2844            {
2845                gINSTALL_SOURCES($(type)) += $(result) ;
2846            }
2847            return $(result) ;
2848        }
2849    }
2850}
2851
2852#
2853rule install-subinclude ( jamfiles + : options * )
2854{
2855    local gINSTALL_SOURCES = TRUE ;
2856    local gIN_LIB_INCLUDE = TRUE ;
2857    local gINSTALL_EXCLUSIONS = [ get-values <exclude> : $(options) ] ;
2858    local gINSTALL_INCLUSIONS = [ get-values <include> : $(options) ] ;
2859   
2860    for local jamfile in $(jamfiles)
2861    {
2862      local sub-jamfile = [ relative-path $(jamfile) ] ;
2863      dependent-include $(sub-jamfile) ;
2864    }
2865}
2866
2867# get project installation sources of a given type
2868rule install-sources ( type )
2869{
2870    return $(gINSTALL_SOURCES($(type))) ;
2871}
2872
2873rule common-names ( )
2874{
2875    return common-variant-tag ;
2876}
2877rule common-stage-tag ( toolset variant : subvariant-path properties * )
2878{
2879    return [ common-variant-tag $(toolset) $(variant) : $(subvariant-path) $(properties) ] ;
2880}
2881
2882# Enforces toolset level requirements. This is added to all targets.
2883rule toolset::requirements ( toolset variant : subvariant-path properties * )
2884{
2885    local requirements = ;
2886    switch $(toolset)
2887    {
2888        case cwpro8* :
2889        {
2890            # dynamic runtime only comes in the multi-threading flavor
2891            if <runtime-link>dynamic in $(properties) { requirements += <threading>multi ; }
2892        }
2893        case cwpro9* :
2894        {
2895            # dynamic runtime only comes in the multi-threading flavor
2896            if <runtime-link>dynamic in $(properties) { requirements += <threading>multi ; }
2897        }
2898        case cw* :
2899        {
2900            # dynamic runtime only comes in the multi-threading flavor
2901            if <runtime-link>dynamic in $(properties) { requirements += <threading>multi ; }
2902        }
2903        case msvc* :
2904        {
2905            # dynamic runtime only comes in the multi-threading flavor
2906            if <runtime-link>dynamic in $(properties) { requirements += <threading>multi ; }
2907            if [ MATCH .*(stlp).* : $(toolset) ] ||
2908                [ MATCH .*(stlp).* : $(properties:G) ]
2909            {
2910                # STLPort doesn't have any single-threaded builds, so we're going
2911                # to force all such targets to be built with multithread support.
2912                # This is essentially a usage-requirement on the stlport library.
2913                requirements += <threading>multi ;
2914            }
2915        }
2916        case vc* :
2917        {
2918            # dynamic runtime only comes in the multi-threading flavor
2919            if <runtime-link>dynamic in $(properties) { requirements += <threading>multi ; }
2920            if [ MATCH .*(stlp).* : $(toolset) ] ||
2921                [ MATCH .*(stlp).* : $(properties:G) ]
2922            {
2923                # STLPort doesn't have any single-threaded builds, so we're going
2924                # to force all such targets to be built with multithread support.
2925                # This is essentially a usage-requirement on the stlport library.
2926                requirements += <threading>multi ;
2927                # STLPort doesn't support <stlport-iostream>off with vc7 and vc8.
2928                # This is essentially a usage-requirement on the stlport library.
2929                switch $(toolset)
2930                {
2931                    case vc7* : requirements += <stlport-iostream>on ;
2932                    case vc8* : requirements += <stlport-iostream>on ;
2933                    case vc-7* : requirements += <stlport-iostream>on ;
2934                    case vc-8* : requirements += <stlport-iostream>on ;
2935                }
2936            }
2937            # vc8 doesn't have any single threaded runtime
2938            switch $(toolset)
2939            {
2940                case vc-8* : requirements += <threading>multi ;
2941            }
2942        }
2943        case intel-win32* :
2944        {
2945            # dynamic runtime only comes in the multi-threading flavor
2946            if <runtime-link>dynamic in $(properties) { requirements += <threading>multi ; }
2947        }
2948        case iw* :
2949        {
2950            # dynamic runtime only comes in the multi-threading flavor
2951            if <runtime-link>dynamic in $(properties) { requirements += <threading>multi ; }
2952        }
2953    }
2954    if <stlport-version>5.0 in $(properties)
2955    {
2956        # STLPort-5 doesn't have any single-threaded builds, so we're going
2957        # to force all such targets to be built with multithread support.
2958        # This is essentially a usage-requirement on the stlport library.
2959        requirements += <threading>multi ;
2960    }
2961    return $(subvariant-path) [ impose-requirements $(properties) : $(requirements) ] ;
2962}
2963
2964# Utility, to impose a subset of requirements onto a property set.
2965rule impose-requirements ( properties * : requirements * )
2966{
2967    local requirements = [ unique $(requirements) ] ;
2968    local free-feature-requirements = [ segregate-free-properties properties ] ;
2969    properties =
2970        [ sort
2971            [ difference $(properties) : [ get-properties $(requirements:G) : $(properties) ] ]
2972            $(requirements)
2973            ]
2974        $(free-feature-requirements)
2975        ;
2976    return $(properties) ;
2977}
Note: See TracBrowser for help on using the repository browser.