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