]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/build/type.jam
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / tools / build / src / build / type.jam
1 # Copyright 2002, 2003 Dave Abrahams
2 # Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
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 # Deals with target type declaration and defines target class which supports
7 # typed targets.
8
9 import "class" : new ;
10 import feature ;
11 import generators : * ;
12 import os ;
13 import project ;
14 import property ;
15 import scanner ;
16
17 # The following import would create a circular dependency:
18 # project -> project-root -> builtin -> type -> targets -> project
19 # import targets ;
20
21 # The feature is optional so it would never get added implicitly. It is used
22 # only for internal purposes and in all cases we want to use it explicitly.
23 feature.feature target-type : : composite optional ;
24
25 feature.feature main-target-type : : optional incidental ;
26 feature.feature base-target-type : : composite optional free ;
27
28
29 # Registers a target type, possible derived from a 'base-type'. Providing a list
30 # of 'suffixes' here is a shortcut for separately calling the register-suffixes
31 # rule with the given suffixes and the set-generated-target-suffix rule with the
32 # first given suffix.
33 #
34 rule register ( type : suffixes * : base-type ? )
35 {
36 # Type names cannot contain hyphens, because when used as feature-values
37 # they would be interpreted as composite features which need to be
38 # decomposed.
39 switch $(type)
40 {
41 case *-* :
42 import errors ;
43 errors.error "type name \"$(type)\" contains a hyphen" ;
44 }
45
46 if $(type) in $(.types)
47 {
48 import errors ;
49 errors.error "Type $(type) is already registered." ;
50 }
51
52 {
53 .types += $(type) ;
54 .base.$(type) = $(base-type) ;
55 .derived.$(base-type) += $(type) ;
56 .bases.$(type) = $(type) $(.bases.$(base-type)) ;
57
58 # Store suffixes for generated targets.
59 .suffixes.$(type) = [ new property-map ] ;
60
61 # Store prefixes for generated targets (e.g. "lib" for library).
62 .prefixes.$(type) = [ new property-map ] ;
63
64 if $(suffixes)-is-defined
65 {
66 # Specify mapping from suffixes to type.
67 register-suffixes $(suffixes) : $(type) ;
68 # By default generated targets of 'type' will use the first of
69 #'suffixes'. This may be overriden.
70 set-generated-target-suffix $(type) : : $(suffixes[1]) ;
71 }
72
73 feature.extend target-type : $(type) ;
74 feature.extend main-target-type : $(type) ;
75 feature.extend base-target-type : $(type) ;
76
77 feature.compose <target-type>$(type) : $(base-type:G=<base-target-type>) ;
78 feature.compose <base-target-type>$(type) : <base-target-type>$(base-type) ;
79
80 # We used to declare the main target rule only when a 'main' parameter
81 # has been specified. However, it is hard to decide that a type will
82 # *never* need a main target rule and so from time to time we needed to
83 # make yet another type 'main'. So now a main target rule is defined for
84 # each type.
85 main-rule-name = [ type-to-rule-name $(type) ] ;
86 .main-target-type.$(main-rule-name) = $(type) ;
87 IMPORT $(__name__) : main-target-rule : : $(main-rule-name) ;
88
89 # Adding a new derived type affects generator selection so we need to
90 # make the generator selection module update any of its cached
91 # information related to a new derived type being defined.
92 generators.update-cached-information-with-a-new-type $(type) ;
93 }
94 }
95
96
97 # Given a type, returns the name of the main target rule which creates targets
98 # of that type.
99 #
100 rule type-to-rule-name ( type )
101 {
102 # Lowercase everything. Convert underscores to dashes.
103 import regex ;
104 local n = [ regex.split $(type:L) "_" ] ;
105 return $(n:J=-) ;
106 }
107
108
109 # Given a main target rule name, returns the type for which it creates targets.
110 #
111 rule type-from-rule-name ( rule-name )
112 {
113 return $(.main-target-type.$(rule-name)) ;
114 }
115
116
117 # Specifies that files with suffix from 'suffixes' be recognized as targets of
118 # type 'type'. Issues an error if a different type is already specified for any
119 # of the suffixes.
120 #
121 rule register-suffixes ( suffixes + : type )
122 {
123 for local s in $(suffixes)
124 {
125 if ! $(.type.$(s))
126 {
127 .type.$(s) = $(type) ;
128 }
129 else if $(.type.$(s)) != $(type)
130 {
131 import errors ;
132 errors.error Attempting to specify multiple types for suffix
133 \"$(s)\" : "Old type $(.type.$(s)), New type $(type)" ;
134 }
135 }
136 }
137
138
139 # Returns true iff type has been registered.
140 #
141 rule registered ( type )
142 {
143 if $(type) in $(.types)
144 {
145 return true ;
146 }
147 }
148
149
150 # Issues an error if 'type' is unknown.
151 #
152 rule validate ( type )
153 {
154 if ! [ registered $(type) ]
155 {
156 import errors ;
157 errors.error "Unknown target type $(type)" ;
158 }
159 }
160
161
162 # Sets a scanner class that will be used for this 'type'.
163 #
164 rule set-scanner ( type : scanner )
165 {
166 validate $(type) ;
167 .scanner.$(type) = $(scanner) ;
168 }
169
170
171 # Returns a scanner instance appropriate to 'type' and 'properties'.
172 #
173 rule get-scanner ( type : property-set )
174 {
175 if $(.scanner.$(type))
176 {
177 return [ scanner.get $(.scanner.$(type)) : $(property-set) ] ;
178 }
179 }
180
181
182 # Returns a base type for the given type or nothing in case the given type is
183 # not derived.
184 #
185 rule base ( type )
186 {
187 return $(.base.$(type)) ;
188 }
189
190
191 # Returns the given type and all of its base types in order of their distance
192 # from type.
193 #
194 rule all-bases ( type )
195 {
196 return $(.bases.$(type)) ;
197 }
198
199
200 # Returns the given type and all of its derived types in order of their distance
201 # from type.
202 #
203 rule all-derived ( type )
204 {
205 local result = $(type) ;
206 for local d in $(.derived.$(type))
207 {
208 result += [ all-derived $(d) ] ;
209 }
210 return $(result) ;
211 }
212
213
214 # Returns true if 'type' is equal to 'base' or has 'base' as its direct or
215 # indirect base.
216 #
217 rule is-derived ( type base )
218 {
219 if $(base) in $(.bases.$(type))
220 {
221 return true ;
222 }
223 }
224
225 # Returns true if 'type' is either derived from or is equal to 'base'.
226 #
227 # TODO: It might be that is-derived and is-subtype were meant to be different
228 # rules - one returning true for type = base and one not, but as currently
229 # implemented they are actually the same. Clean this up.
230 #
231 rule is-subtype ( type base )
232 {
233 return [ is-derived $(type) $(base) ] ;
234 }
235
236
237
238
239 # Sets a file suffix to be used when generating a target of 'type' with the
240 # specified properties. Can be called with no properties if no suffix has
241 # already been specified for the 'type'. The 'suffix' parameter can be an empty
242 # string ("") to indicate that no suffix should be used.
243 #
244 # Note that this does not cause files with 'suffix' to be automatically
245 # recognized as being of 'type'. Two different types can use the same suffix for
246 # their generated files but only one type can be auto-detected for a file with
247 # that suffix. User should explicitly specify which one using the
248 # register-suffixes rule.
249 #
250 rule set-generated-target-suffix ( type : properties * : suffix )
251 {
252 set-generated-target-ps suffix : $(type) : $(properties) : $(suffix) ;
253 }
254
255
256 # Change the suffix previously registered for this type/properties combination.
257 # If suffix is not yet specified, sets it.
258 #
259 rule change-generated-target-suffix ( type : properties * : suffix )
260 {
261 change-generated-target-ps suffix : $(type) : $(properties) : $(suffix) ;
262 }
263
264
265 # Returns the suffix used when generating a file of 'type' with the given
266 # properties.
267 #
268 rule generated-target-suffix ( type : property-set )
269 {
270 return [ generated-target-ps suffix : $(type) : $(property-set) ] ;
271 }
272
273
274 # Sets a target prefix that should be used when generating targets of 'type'
275 # with the specified properties. Can be called with empty properties if no
276 # prefix for 'type' has been specified yet.
277 #
278 # The 'prefix' parameter can be empty string ("") to indicate that no prefix
279 # should be used.
280 #
281 # Usage example: library names use the "lib" prefix on unix.
282 #
283 rule set-generated-target-prefix ( type : properties * : prefix )
284 {
285 set-generated-target-ps prefix : $(type) : $(properties) : $(prefix) ;
286 }
287
288
289 # Change the prefix previously registered for this type/properties combination.
290 # If prefix is not yet specified, sets it.
291 #
292 rule change-generated-target-prefix ( type : properties * : prefix )
293 {
294 change-generated-target-ps prefix : $(type) : $(properties) : $(prefix) ;
295 }
296
297
298 rule generated-target-prefix ( type : property-set )
299 {
300 return [ generated-target-ps prefix : $(type) : $(property-set) ] ;
301 }
302
303
304 # Common rules for prefix/suffix provisioning follow.
305
306 local rule set-generated-target-ps ( ps : type : properties * : psval )
307 {
308 $(.$(ps)es.$(type)).insert $(properties) : $(psval) ;
309 }
310
311
312 local rule change-generated-target-ps ( ps : type : properties * : psval )
313 {
314 local prev = [ $(.$(ps)es.$(type)).find-replace $(properties) : $(psval) ] ;
315 if ! $(prev)
316 {
317 set-generated-target-ps $(ps) : $(type) : $(properties) : $(psval) ;
318 }
319 }
320
321
322 # Returns either prefix or suffix (as indicated by 'ps') that should be used
323 # when generating a target of 'type' with the specified properties. Parameter
324 # 'ps' can be either "prefix" or "suffix". If no prefix/suffix is specified for
325 # 'type', returns prefix/suffix for base type, if any.
326 #
327 local rule generated-target-ps ( ps : type : property-set )
328 {
329 local result ;
330 local found ;
331 while $(type) && ! $(found)
332 {
333 result = [ $(.$(ps)es.$(type)).find $(property-set) ] ;
334 # If the prefix/suffix is explicitly set to an empty string, we consider
335 # prefix/suffix to be found. If we were not to compare with "", there
336 # would be no way to specify an empty prefix/suffix.
337 if $(result)-is-defined
338 {
339 found = true ;
340 }
341 type = $(.base.$(type)) ;
342 }
343 if $(result) = ""
344 {
345 result = ;
346 }
347 return $(result) ;
348 }
349
350
351 # Returns file type given its name. If there are several dots in filename, tries
352 # each suffix. E.g. for name of "file.so.1.2" suffixes "2", "1", and "so" will
353 # be tried.
354 #
355 rule type ( filename )
356 {
357 if [ os.name ] in NT CYGWIN
358 {
359 filename = $(filename:L) ;
360 }
361 local type ;
362 while ! $(type) && $(filename:S)
363 {
364 local suffix = $(filename:S) ;
365 type = $(.type$(suffix)) ;
366 filename = $(filename:S=) ;
367 }
368 return $(type) ;
369 }
370
371
372 # Rule used to construct all main targets. Note that this rule gets imported
373 # into the global namespace under different alias names and the exact target
374 # type to construct is selected based on the alias used to actually invoke this
375 # rule.
376 #
377 rule main-target-rule ( name : sources * : requirements * : default-build * :
378 usage-requirements * )
379 {
380 # First discover the required target type based on the exact alias used to
381 # invoke this rule.
382 local bt = [ BACKTRACE 1 ] ;
383 local rulename = $(bt[4]) ;
384 local target-type = [ type-from-rule-name $(rulename) ] ;
385
386 # This is a circular module dependency and so must be imported here.
387 import targets ;
388
389 return [ targets.create-typed-target $(target-type) : [ project.current ] :
390 $(name) : $(sources) : $(requirements) : $(default-build) :
391 $(usage-requirements) ] ;
392 }
393
394
395 rule __test__ ( )
396 {
397 import assert ;
398
399 # TODO: Add tests for all the is-derived, is-base & related type relation
400 # checking rules.
401 }