]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/build/toolset.jam
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / tools / build / src / build / toolset.jam
1 # Copyright 2003 Dave Abrahams
2 # Copyright 2005 Rene Rivera
3 # Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
4 # Distributed under the Boost Software License, Version 1.0.
5 # (See accompanying file LICENSE_1_0.txt or copy at
6 # http://www.boost.org/LICENSE_1_0.txt)
7
8 # Support for toolset definition.
9
10 import errors ;
11 import feature ;
12 import generators ;
13 import numbers ;
14 import path ;
15 import property ;
16 import regex ;
17 import sequence ;
18 import set ;
19 import property-set ;
20 import order ;
21 import "class" : new ;
22 import utility ;
23
24
25 .flag-no = 1 ;
26
27 .ignore-requirements = ;
28
29 # This is used only for testing, to make sure we do not get random extra
30 # elements in paths.
31 if --ignore-toolset-requirements in [ modules.peek : ARGV ]
32 {
33 .ignore-requirements = 1 ;
34 }
35
36
37 # Initializes an additional toolset-like module. First load the 'toolset-module'
38 # and then calls its 'init' rule with trailing arguments.
39 #
40 rule using ( toolset-module : * )
41 {
42 import $(toolset-module) ;
43 $(toolset-module).init $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9)
44 ;
45 }
46
47
48 # Expands subfeatures in each property sets, e.g. '<toolset>gcc-3.2' will be
49 # converted to '<toolset>gcc/<toolset-version>3.2'.
50 #
51 local rule normalize-condition ( property-sets * )
52 {
53 local result ;
54 for local p in $(property-sets)
55 {
56 local split = [ feature.split $(p) ] ;
57 local expanded = [ feature.expand-subfeatures [ feature.split $(p) ] ] ;
58 result += $(expanded:J=/) ;
59 }
60 return $(result) ;
61 }
62
63
64 # Specifies if the 'flags' rule should check that the invoking module is the
65 # same as the module we are setting the flag for. 'v' can be either 'checked' or
66 # 'unchecked'. Subsequent call to 'pop-checking-for-flags-module' will restore
67 # the setting that was in effect before calling this rule.
68 #
69 rule push-checking-for-flags-module ( v )
70 {
71 .flags-module-checking = $(v) $(.flags-module-checking) ;
72 }
73
74 rule pop-checking-for-flags-module ( )
75 {
76 .flags-module-checking = $(.flags-module-checking[2-]) ;
77 }
78
79
80 # Specifies features that are referenced by the action rule.
81 # This is necessary in order to detect that these features
82 # are relevant.
83 #
84 rule uses-features ( rule-or-module : features * : unchecked ? )
85 {
86 local caller = [ CALLER_MODULE ] ;
87 if ! [ MATCH ".*([.]).*" : $(rule-or-module) ]
88 && [ MATCH "(Jamfile<.*)" : $(caller) ]
89 {
90 # Unqualified rule name, used inside Jamfile. Most likely used with
91 # 'make' or 'notfile' rules. This prevents setting flags on the entire
92 # Jamfile module (this will be considered as rule), but who cares?
93 # Probably, 'flags' rule should be split into 'flags' and
94 # 'flags-on-module'.
95 rule-or-module = $(caller).$(rule-or-module) ;
96 }
97 else
98 {
99 local module_ = [ MATCH "([^.]*).*" : $(rule-or-module) ] ;
100 if $(unchecked) != unchecked
101 && $(.flags-module-checking[1]) != unchecked
102 && $(module_) != $(caller)
103 {
104 errors.error "Module $(caller) attempted to set flags for module $(module_)" ;
105 }
106 }
107 .uses-features.$(rule-or-module) += $(features) ;
108 }
109
110 # Specifies the flags (variables) that must be set on targets under certain
111 # conditions, described by arguments.
112 #
113 rule flags (
114 rule-or-module # If contains a dot, should be a rule name. The flags will
115 # be applied when that rule is used to set up build
116 # actions.
117 #
118 # If does not contain dot, should be a module name. The
119 # flag will be applied for all rules in that module. If
120 # module for rule is different from the calling module, an
121 # error is issued.
122
123 variable-name # Variable that should be set on target.
124 condition * : # A condition when this flag should be applied. Should be a
125 # set of property sets. If one of those property sets is
126 # contained in the build properties, the flag will be used.
127 # Implied values are not allowed: "<toolset>gcc" should be
128 # used, not just "gcc". Subfeatures, like in
129 # "<toolset>gcc-3.2" are allowed. If left empty, the flag
130 # will be used unconditionally.
131 #
132 # Property sets may use value-less properties ('<a>' vs.
133 # '<a>value') to match absent properties. This allows to
134 # separately match:
135 #
136 # <architecture>/<address-model>64
137 # <architecture>ia64/<address-model>
138 #
139 # Where both features are optional. Without this syntax
140 # we would be forced to define "default" values.
141
142 values * : # The value to add to variable. If <feature> is specified,
143 # then the value of 'feature' will be added.
144 unchecked ? # If value 'unchecked' is passed, will not test that flags
145 # are set for the calling module.
146 : hack-hack ? # For
147 # flags rule OPTIONS <cxx-abi> : -model ansi
148 # Treat <cxx-abi> as condition
149 # FIXME: ugly hack.
150 )
151 {
152 local caller = [ CALLER_MODULE ] ;
153 if ! [ MATCH ".*([.]).*" : $(rule-or-module) ]
154 && [ MATCH "(Jamfile<.*)" : $(caller) ]
155 {
156 # Unqualified rule name, used inside Jamfile. Most likely used with
157 # 'make' or 'notfile' rules. This prevents setting flags on the entire
158 # Jamfile module (this will be considered as rule), but who cares?
159 # Probably, 'flags' rule should be split into 'flags' and
160 # 'flags-on-module'.
161 rule-or-module = $(caller).$(rule-or-module) ;
162 }
163 else
164 {
165 local module_ = [ MATCH "([^.]*).*" : $(rule-or-module) ] ;
166 if $(unchecked) != unchecked
167 && $(.flags-module-checking[1]) != unchecked
168 && $(module_) != $(caller)
169 {
170 errors.error "Module $(caller) attempted to set flags for module $(module_)" ;
171 }
172 }
173
174 if $(condition) && ! $(condition:G=) && ! $(hack-hack)
175 {
176 # We have condition in the form '<feature>', that is, without value.
177 # That is an older syntax:
178 # flags gcc.link RPATH <dll-path> ;
179 # for compatibility, convert it to
180 # flags gcc.link RPATH : <dll-path> ;
181 values = $(condition) ;
182 condition = ;
183 }
184
185 if $(condition)
186 {
187 property.validate-property-sets $(condition) ;
188 condition = [ normalize-condition $(condition) ] ;
189 }
190
191 add-flag $(rule-or-module) : $(variable-name) : $(condition) : $(values) ;
192 }
193
194
195 # Adds a new flag setting with the specified values. Does no checking.
196 #
197 local rule add-flag ( rule-or-module : variable-name : condition * : values * )
198 {
199 .$(rule-or-module).flags += $(.flag-no) ;
200
201 # Store all flags for a module.
202 local module_ = [ MATCH "([^.]*).*" : $(rule-or-module) ] ;
203 .module-flags.$(module_) += $(.flag-no) ;
204 # Store flag-no -> rule-or-module mapping.
205 .rule-or-module.$(.flag-no) = $(rule-or-module) ;
206
207 .$(rule-or-module).variable.$(.flag-no) += $(variable-name) ;
208 .$(rule-or-module).values.$(.flag-no) += $(values) ;
209 .$(rule-or-module).condition.$(.flag-no) += $(condition) ;
210
211 .flag-no = [ numbers.increment $(.flag-no) ] ;
212 }
213
214
215 # Returns the first element of 'property-sets' which is a subset of
216 # 'properties' or an empty list if no such element exists.
217 #
218 rule find-property-subset ( property-sets * : properties * )
219 {
220 # Cut property values off.
221 local prop-keys = $(properties:G) ;
222
223 local result ;
224 for local s in $(property-sets)
225 {
226 if ! $(result)
227 {
228 # Handle value-less properties like '<architecture>' (compare with
229 # '<architecture>x86').
230
231 local set = [ feature.split $(s) ] ;
232
233 # Find the set of features that
234 # - have no property specified in required property set
235 # - are omitted in the build property set.
236 local default-props ;
237 for local i in $(set)
238 {
239 # If $(i) is a value-less property it should match default value
240 # of an optional property. See the first line in the example
241 # below:
242 #
243 # property set properties result
244 # <a> <b>foo <b>foo match
245 # <a> <b>foo <a>foo <b>foo no match
246 # <a>foo <b>foo <b>foo no match
247 # <a>foo <b>foo <a>foo <b>foo match
248 if ! ( $(i:G=) || ( $(i:G) in $(prop-keys) ) )
249 {
250 default-props += $(i) ;
251 }
252 }
253
254 if $(set) in $(properties) $(default-props)
255 {
256 result = $(s) ;
257 }
258 }
259 }
260 return $(result) ;
261 }
262
263
264 # Returns a value to be added to some flag for some target based on the flag's
265 # value definition and the given target's property set.
266 #
267 rule handle-flag-value ( value * : properties * )
268 {
269 local result ;
270 if $(value:G)
271 {
272 local matches = [ property.select $(value) : $(properties) ] ;
273 local order ;
274 for local p in $(matches)
275 {
276 local att = [ feature.attributes $(p:G) ] ;
277 if dependency in $(att)
278 {
279 # The value of a dependency feature is a target and needs to be
280 # actualized.
281 result += [ $(p:G=).actualize ] ;
282 }
283 else if path in $(att) || free in $(att)
284 {
285 local values ;
286 # Treat features with && in the value specially -- each
287 # &&-separated element is considered a separate value. This is
288 # needed to handle searched libraries or include paths, which
289 # may need to be in a specific order.
290 if ! [ MATCH (&&) : $(p:G=) ]
291 {
292 values = $(p:G=) ;
293 }
294 else
295 {
296 values = [ regex.split $(p:G=) "&&" ] ;
297 }
298 if path in $(att)
299 {
300 values = [ sequence.transform path.native : $(values) ] ;
301 }
302 result += $(values) ;
303 if $(values[2])
304 {
305 if ! $(order)
306 {
307 order = [ new order ] ;
308 }
309 local prev ;
310 for local v in $(values)
311 {
312 if $(prev)
313 {
314 $(order).add-pair $(prev) $(v) ;
315 }
316 prev = $(v) ;
317 }
318 }
319 }
320 else
321 {
322 result += $(p:G=) ;
323 }
324 }
325 if $(order)
326 {
327 result = [ $(order).order [ sequence.unique $(result) : stable ] ] ;
328 DELETE_MODULE $(order) ;
329 }
330 }
331 else
332 {
333 result += $(value) ;
334 }
335 return $(result) ;
336 }
337
338
339 # Given a rule name and a property set, returns a list of interleaved variables
340 # names and values which must be set on targets for that rule/property-set
341 # combination.
342 #
343 rule set-target-variables-aux ( rule-or-module : property-set )
344 {
345 local result ;
346 properties = [ $(property-set).raw ] ;
347 for local f in $(.$(rule-or-module).flags)
348 {
349 local variable = $(.$(rule-or-module).variable.$(f)) ;
350 local condition = $(.$(rule-or-module).condition.$(f)) ;
351 local values = $(.$(rule-or-module).values.$(f)) ;
352
353 if ! $(condition) ||
354 [ find-property-subset $(condition) : $(properties) ]
355 {
356 local processed ;
357 for local v in $(values)
358 {
359 # The value might be <feature-name> so needs special treatment.
360 processed += [ handle-flag-value $(v) : $(properties) ] ;
361 }
362 for local r in $(processed)
363 {
364 result += $(variable) $(r) ;
365 }
366 }
367 }
368
369 # Strip away last dot separated part and recurse.
370 local next = [ MATCH "^(.+)\\.([^\\.])*" : $(rule-or-module) ] ;
371 if $(next)
372 {
373 result += [ set-target-variables-aux $(next[1]) : $(property-set) ] ;
374 }
375 return $(result) ;
376 }
377
378 rule relevant-features ( rule-or-module )
379 {
380 local result ;
381 if ! $(.relevant-features.$(rule-or-module))
382 {
383 for local f in $(.$(rule-or-module).flags)
384 {
385 local condition = $(.$(rule-or-module).condition.$(f)) ;
386 local values = $(.$(rule-or-module).values.$(f)) ;
387
388 for local c in $(condition)
389 {
390 for local p in [ feature.split $(c) ]
391 {
392 if $(p:G)
393 {
394 result += $(p:G) ;
395 }
396 else
397 {
398 local temp = [ feature.expand-subfeatures $(p) ] ;
399 result += $(temp:G) ;
400 }
401 }
402 }
403
404 for local v in $(values)
405 {
406 if $(v:G)
407 {
408 result += $(v:G) ;
409 }
410 }
411 }
412
413 # Strip away last dot separated part and recurse.
414 local next = [ MATCH "^(.+)\\.([^\\.])*" : $(rule-or-module) ] ;
415 if $(next)
416 {
417 result += [ relevant-features $(next[1]) ] ;
418 }
419 result = [ sequence.unique $(result) ] ;
420 if $(result[1]) = ""
421 {
422 result = $(result) ;
423 }
424 .relevant-features.$(rule-or-module) = $(result) ;
425 return $(result) ;
426 }
427 else
428 {
429 return $(.relevant-features.$(rule-or-module)) ;
430 }
431 }
432
433 # Returns a list of all the features which were
434 # passed to uses-features.
435 local rule used-features ( rule-or-module )
436 {
437 if ! $(.used-features.$(rule-or-module))
438 {
439 local result = $(.uses-features.$(rule-or-module)) ;
440
441 # Strip away last dot separated part and recurse.
442 local next = [ MATCH "^(.+)\\.([^\\.])*" : $(rule-or-module) ] ;
443 if $(next)
444 {
445 result += [ used-features $(next[1]) ] ;
446 }
447 result = [ sequence.unique $(result) ] ;
448 if $(result[1]) = ""
449 {
450 result = $(result) ;
451 }
452 .used-features.$(rule-or-module) = $(result) ;
453 return $(result) ;
454 }
455 else
456 {
457 return $(.used-features.$(rule-or-module)) ;
458 }
459 }
460
461 rule filter-property-set ( rule-or-module : property-set )
462 {
463 local key = .filtered.property-set.$(rule-or-module).$(property-set) ;
464 if ! $($(key))
465 {
466 local relevant = [ relevant-features $(rule-or-module) ] ;
467 local result ;
468 for local p in [ $(property-set).raw ]
469 {
470 if $(p:G) in $(relevant)
471 {
472 result += $(p) ;
473 }
474 }
475 $(key) = [ property-set.create $(result) ] ;
476 }
477 return $($(key)) ;
478 }
479
480 rule set-target-variables ( rule-or-module targets + : property-set )
481 {
482 property-set = [ filter-property-set $(rule-or-module) : $(property-set) ] ;
483 local key = .stv.$(rule-or-module).$(property-set) ;
484 local settings = $($(key)) ;
485 if ! $(settings)
486 {
487 settings = [ set-target-variables-aux $(rule-or-module) :
488 $(property-set) ] ;
489
490 if ! $(settings)
491 {
492 settings = none ;
493 }
494 $(key) = $(settings) ;
495 }
496
497 if $(settings) != none
498 {
499 local var-name = ;
500 for local name-or-value in $(settings)
501 {
502 if $(var-name)
503 {
504 $(var-name) on $(targets) += $(name-or-value) ;
505 var-name = ;
506 }
507 else
508 {
509 var-name = $(name-or-value) ;
510 }
511 }
512 }
513 }
514
515
516 # Returns a property-set indicating which features are relevant
517 # for the given rule.
518 #
519 rule relevant ( rule-name )
520 {
521 if ! $(.relevant-features-ps.$(rule-name))
522 {
523 local features = [ sequence.transform utility.ungrist :
524 [ relevant-features $(rule-name) ]
525 [ used-features $(rule-name) ] ] ;
526 .relevant-features-ps.$(rule-name) =
527 [ property-set.create <relevant>$(features) ] ;
528 }
529 return $(.relevant-features-ps.$(rule-name)) ;
530 }
531
532
533 # Make toolset 'toolset', defined in a module of the same name, inherit from
534 # 'base'.
535 # 1. The 'init' rule from 'base' is imported into 'toolset' with full name.
536 # Another 'init' is called, which forwards to the base one.
537 # 2. All generators from 'base' are cloned. The ids are adjusted and <toolset>
538 # property in requires is adjusted too.
539 # 3. All flags are inherited.
540 # 4. All rules are imported.
541 #
542 rule inherit ( toolset : base )
543 {
544 import $(base) ;
545 inherit-generators $(toolset) : $(base) ;
546 inherit-flags $(toolset) : $(base) ;
547 inherit-rules $(toolset) : $(base) ;
548 }
549
550
551 rule inherit-generators ( toolset properties * : base : generators-to-ignore * )
552 {
553 properties ?= <toolset>$(toolset) ;
554 local base-generators = [ generators.generators-for-toolset $(base) ] ;
555 for local g in $(base-generators)
556 {
557 local id = [ $(g).id ] ;
558
559 if ! $(id) in $(generators-to-ignore)
560 {
561 # Some generator names have multiple periods in their name, so
562 # $(id:B=$(toolset)) does not generate the right new-id name. E.g.
563 # if id = gcc.compile.c++ then $(id:B=darwin) = darwin.c++, which is
564 # not what we want. Manually parse the base and suffix. If there is
565 # a better way to do this, I would love to see it. See also the
566 # register() rule in the generators module.
567 local base = $(id) ;
568 local suffix = "" ;
569 while $(base:S)
570 {
571 suffix = $(base:S)$(suffix) ;
572 base = $(base:B) ;
573 }
574 local new-id = $(toolset)$(suffix) ;
575
576 generators.register [ $(g).clone $(new-id) : $(properties) ] ;
577 }
578 }
579 }
580
581
582 # Brings all flag definitions from the 'base' toolset into the 'toolset'
583 # toolset. Flag definitions whose conditions make use of properties in
584 # 'prohibited-properties' are ignored. Do not confuse property and feature, for
585 # example <debug-symbols>on and <debug-symbols>off, so blocking one of them does
586 # not block the other one.
587 #
588 # The flag conditions are not altered at all, so if a condition includes a name,
589 # or version of a base toolset, it will not ever match the inheriting toolset.
590 # When such flag settings must be inherited, define a rule in base toolset
591 # module and call it as needed.
592 #
593 rule inherit-flags ( toolset : base : prohibited-properties * : prohibited-vars * )
594 {
595 for local f in $(.module-flags.$(base))
596 {
597 local rule-or-module = $(.rule-or-module.$(f)) ;
598 if ( [ set.difference
599 $(.$(rule-or-module).condition.$(f)) :
600 $(prohibited-properties) ]
601 || ! $(.$(rule-or-module).condition.$(f))
602 ) && ( ! $(.$(rule-or-module).variable.$(f)) in $(prohibited-vars) )
603 {
604 local rule_ = [ MATCH "[^.]*\.(.*)" : $(rule-or-module) ] ;
605 local new-rule-or-module ;
606 if $(rule_)
607 {
608 new-rule-or-module = $(toolset).$(rule_) ;
609 }
610 else
611 {
612 new-rule-or-module = $(toolset) ;
613 }
614
615 add-flag
616 $(new-rule-or-module)
617 : $(.$(rule-or-module).variable.$(f))
618 : $(.$(rule-or-module).condition.$(f))
619 : $(.$(rule-or-module).values.$(f)) ;
620 }
621 }
622 }
623
624
625 rule inherit-rules ( toolset : base : localize ? )
626 {
627 # It appears that "action" creates a local rule.
628 local base-generators = [ generators.generators-for-toolset $(base) ] ;
629 local rules ;
630 for local g in $(base-generators)
631 {
632 rules += [ MATCH "[^.]*\.(.*)" : [ $(g).rule-name ] ] ;
633 }
634 rules = [ sequence.unique $(rules) ] ;
635 IMPORT $(base) : $(rules) : $(toolset) : $(rules) : $(localize) ;
636 IMPORT $(toolset) : $(rules) : : $(toolset).$(rules) ;
637 }
638
639 .requirements = [ property-set.empty ] ;
640
641 # Return the list of global 'toolset requirements'. Those requirements will be
642 # automatically added to the requirements of any main target.
643 #
644 rule requirements ( )
645 {
646 return $(.requirements) ;
647 }
648
649
650 # Adds elements to the list of global 'toolset requirements'. The requirements
651 # will be automatically added to the requirements for all main targets, as if
652 # they were specified literally. For best results, all requirements added should
653 # be conditional or indirect conditional.
654 #
655 rule add-requirements ( requirements * )
656 {
657 if ! $(.ignore-requirements)
658 {
659 requirements = [ property.translate-indirect $(requirements) : [ CALLER_MODULE ] ] ;
660 requirements = [ property.expand-subfeatures-in-conditions $(requirements) ] ;
661 requirements = [ property.make $(requirements) ] ;
662 .requirements = [ $(.requirements).add-raw $(requirements) ] ;
663 }
664 }
665
666 # Returns the global toolset defaults.
667 #
668 .defaults = [ property-set.empty ] ;
669
670 rule defaults ( )
671 {
672 return $(.defaults) ;
673 }
674
675 # Add elements to the list of global toolset defaults. These properties
676 # should be conditional and will override the default value of the feature.
677 # Do not use this for non-conditionals. Use feature.set-default instead.
678 #
679 rule add-defaults ( properties * )
680 {
681 if ! $(.ignore-requirements)
682 {
683 properties = [ property.translate-indirect $(properties) : [ CALLER_MODULE ] ] ;
684 properties = [ property.expand-subfeatures-in-conditions $(properties) ] ;
685 properties = [ property.make $(properties) ] ;
686 .defaults = [ $(.defaults).add-raw $(properties) ] ;
687 }
688 }
689
690
691 rule __test__ ( )
692 {
693 import assert ;
694 local p = <b>0 <c>1 <d>2 <e>3 <f>4 ;
695 assert.result <c>1/<d>2/<e>3 : find-property-subset <c>1/<d>2/<e>3 <a>0/<b>0/<c>1 <d>2/<e>5 <a>9 : $(p) ;
696 assert.result : find-property-subset <a>0/<b>0/<c>9/<d>9/<e>5 <a>9 : $(p) ;
697
698 local p-set = <a>/<b> <a>0/<b> <a>/<b>1 <a>0/<b>1 ;
699 assert.result <a>/<b> : find-property-subset $(p-set) : ;
700 assert.result <a>0/<b> : find-property-subset $(p-set) : <a>0 <c>2 ;
701 assert.result <a>/<b>1 : find-property-subset $(p-set) : <b>1 <c>2 ;
702 assert.result <a>0/<b>1 : find-property-subset $(p-set) : <a>0 <b>1 ;
703 }