1#  Copyright (c) 2004 Vladimir Prus.
2#
3#  Use, modification and distribution is subject to the Boost Software
4#  License Version 1.0. (See accompanying file LICENSE_1_0.txt or
5#  http://www.boost.org/LICENSE_1_0.txt)
6
7#  This file implements linking semantic common to all unixes. On unix, static
8#  libraries must be specified in a fixed order on the linker command line. Generators
9#  declared there store information about the order and use it property.
10
11import feature ;
12import "class" : new ;
13import generators ;
14import type ;
15import set ;
16import order ;
17import builtin ;
18
19class unix-linking-generator : linking-generator
20{
21    import property-set ;
22    import type ;
23    import unix ;
24
25    rule __init__ ( id
26        composing ? : # Specify if generator is composing. The generator will be
27        # composing if non-empty string is passed, or parameter is
28        # not given. To make generator non-composing, pass empty
29        # string ("")
30        source-types + : target-types + :
31        requirements * )
32    {
33        composing ?= true ;
34        generator.__init__ $(id) $(composing) : $(source-types) : $(target-types) :
35          $(requirements) ;
36    }
37
38    rule run ( project name ? : property-set : sources + )
39    {
40        local result = [ linking-generator.run $(project) $(name) : $(property-set)
41          : $(sources) ] ;
42
43        unix.set-library-order $(sources) : $(property-set) : $(result[2-]) ;
44
45        return $(result) ;
46    }
47
48    rule generated-targets ( sources + : property-set : project name ? )
49    {
50        local sources2 ;
51        local libraries ;
52        for local l in $(sources)
53        {
54            if [ type.is-derived [ $(l).type ] LIB ]
55            {
56                libraries += $(l) ;
57            }
58            else
59            {
60                sources2 += $(l) ;
61            }
62        }
63
64        sources = $(sources2) [ unix.order-libraries $(libraries) ] ;
65
66        return [ linking-generator.generated-targets $(sources) : $(property-set)
67          : $(project) $(name) ] ;
68    }
69
70}
71
72class unix-archive-generator : archive-generator
73{
74    import unix ;
75
76    rule __init__ ( id composing ? : source-types + : target-types + :
77        requirements * )
78    {
79        composing ?= true ;
80        archive-generator.__init__ $(id) $(composing) : $(source-types) : $(target-types) :
81          $(requirements) ;
82    }
83
84    rule run ( project name ? : property-set : sources + )
85    {
86        local result = [ archive-generator.run $(project) $(name) : $(property-set)
87          : $(sources) ] ;
88
89        unix.set-library-order $(sources) : $(property-set) : $(result[2-]) ;
90
91        return $(result) ;
92
93    }
94}
95
96class unix-searched-lib-generator : searched-lib-generator
97{
98    import unix ;
99    rule __init__ ( * : * )
100    {
101        generator.__init__
102          $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
103    }
104
105    rule optional-properties ( )
106    {
107        return $(self.requirements) ;
108    }
109
110    rule run ( project name ? : property-set : sources * )
111    {
112        local result = [ searched-lib-generator.run $(project) $(name)
113          : $(property-set) : $(sources) ] ;
114
115        unix.set-library-order $(sources) : $(property-set) : $(result[2-]) ;
116
117        return $(result) ;
118    }
119}
120
121class unix-prebuilt-lib-generator : generator
122{
123    import unix ;
124    rule __init__ ( * : * )
125    {
126        generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
127    }
128
129    rule run ( project name ? : property-set : sources * )
130    {
131        local f = [ $(property-set).get <file> ] ;
132        unix.set-library-order-aux $(f) : $(sources) ;
133        return $(f) $(sources) ;
134    }
135}
136
137generators.register
138  [ new unix-prebuilt-lib-generator unix.prebuilt : : LIB
139      : <file> <toolset>unix ] ;
140
141generators.override unix.prebuilt : builtin.lib-generator ;
142
143
144# Declare generators
145generators.register [ new unix-linking-generator unix.link : LIB OBJ : EXE
146    : <toolset>unix ] ;
147
148generators.register [ new unix-archive-generator unix.archive : OBJ : STATIC_LIB
149    : <toolset>unix ] ;
150
151generators.register [ new unix-linking-generator unix.link.dll : LIB OBJ : SHARED_LIB
152    : <toolset>unix ] ;
153
154generators.register [ new unix-searched-lib-generator
155   unix.searched-lib-generator : : SEARCHED_LIB : <toolset>unix ] ;
156
157
158# The derived toolset must specify their own actions.
159actions link {
160}
161
162actions link.dll {
163}
164
165actions archive {
166}
167
168actions searched-lib-generator {
169}
170
171actions prebuilt {
172}
173
174
175
176
177
178.order = [ new order ] ;
179
180rule set-library-order-aux ( from * : to * )
181{
182    for local f in $(from)
183    {
184        for local t in $(to)
185        {
186            if $(f) != $(t)
187            {
188                $(.order).add-pair $(f) $(t) ;
189            }
190        }
191    }
192}
193
194rule set-library-order ( sources * : property-set : result * )
195{
196    local used-libraries ;
197    local deps = [ $(property-set).dependency ] ;
198    for local l in $(sources) $(deps:G=)
199    {
200        if [ $(l).type ] && [ type.is-derived [ $(l).type ] LIB ]
201        {
202            used-libraries += $(l) ;
203        }
204    }
205
206    local created-libraries ;
207    for local l in $(result)
208    {
209        if [ $(l).type ] && [ type.is-derived [ $(l).type ] LIB ]
210        {
211            created-libraries += $(l) ;
212        }
213    }
214
215    created-libraries = [ set.difference $(created-libraries) : $(used-libraries) ] ;
216    set-library-order-aux $(created-libraries) : $(used-libraries) ;
217}
218
219rule order-libraries ( libraries * )
220{
221    local r = [ $(.order).order $(libraries) ] ;
222    return $(r) ;
223}
224