]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/tools/builtin.jam
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / tools / build / src / tools / builtin.jam
1 # Copyright 2002, 2003, 2004, 2005 Dave Abrahams
2 # Copyright 2002, 2005, 2006, 2007, 2010 Rene Rivera
3 # Copyright 2006 Juergen Hunold
4 # Copyright 2005 Toon Knapen
5 # Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
6 # Distributed under the Boost Software License, Version 1.0.
7 # (See accompanying file LICENSE_1_0.txt or copy at
8 # http://www.boost.org/LICENSE_1_0.txt)
9
10 # Defines standard features and rules.
11
12 import alias ;
13 import "class" : new ;
14 import errors ;
15 import feature ;
16 import generators ;
17 import numbers ;
18 import os ;
19 import path ;
20 import print ;
21 import project ;
22 import property ;
23 import regex ;
24 import scanner ;
25 import sequence ;
26 import stage ;
27 import symlink ;
28 import toolset ;
29 import type ;
30 import targets ;
31 import types/register ;
32 import utility ;
33 import virtual-target ;
34 import message ;
35 import convert ;
36
37 # FIXME: the following generate module import is not needed here but removing it
38 # too hastily will break using code (e.g. the main Boost library Jamroot file)
39 # that forgot to import the generate module before calling the generate rule.
40 import generate ;
41
42
43 .os-names = aix android appletv bsd cygwin darwin freebsd haiku hpux iphone linux netbsd
44 openbsd osf qnx qnxnto sgi solaris unix unixware windows vms
45 elf # Not actually an OS -- used for targeting bare metal where object
46 # format is ELF. This catches both -elf and -eabi gcc targets and well
47 # as other compilers targeting ELF. It is not clear how often we need
48 # the 'elf' key as opposed to other bare metal targets, but let us
49 # stick with gcc naming.
50 ;
51
52 # Feature used to determine which OS we're on. New <target-os> and <host-os>
53 # features should be used instead.
54 local os = [ modules.peek : OS ] ;
55 feature.feature os : $(os) : propagated link-incompatible ;
56
57
58 # Translates from bjam current OS to the os tags used in host-os and target-os,
59 # i.e. returns the running host-os.
60 #
61 local rule default-host-os ( )
62 {
63 local host-os ;
64 if [ os.name ] in $(.os-names:U)
65 {
66 host-os = [ os.name ] ;
67 }
68 else
69 {
70 switch [ os.name ]
71 {
72 case NT : host-os = windows ;
73 case AS400 : host-os = unix ;
74 case MINGW : host-os = windows ;
75 case BSDI : host-os = bsd ;
76 case COHERENT : host-os = unix ;
77 case DRAGONFLYBSD : host-os = bsd ;
78 case IRIX : host-os = sgi ;
79 case HAIKU : host-os = haiku ;
80 case MACOSX : host-os = darwin ;
81 case KFREEBSD : host-os = freebsd ;
82 case LINUX : host-os = linux ;
83 case VMS : host-os = vms ;
84 case SUNOS :
85 ECHO "SunOS is not a supported operating system." ;
86 ECHO "We believe last version of SunOS was released in 1992, " ;
87 ECHO "so if you get this message, something is very wrong with configuration logic. " ;
88 ECHO "Please report this as a bug. " ;
89 EXIT ;
90 case * : host-os = unix ;
91 }
92 }
93 return $(host-os:L) ;
94 }
95
96
97 # The two OS features define a known set of abstract OS names. The host-os is
98 # the OS under which bjam is running. Even though this should really be a fixed
99 # property we need to list all the values to prevent unknown value errors. Both
100 # set the default value to the current OS to account for the default use case of
101 # building on the target OS.
102 feature.feature host-os : $(.os-names) ;
103 feature.set-default host-os : [ default-host-os ] ;
104
105 feature.feature target-os : $(.os-names) : propagated link-incompatible ;
106 feature.set-default target-os : [ default-host-os ] ;
107
108
109 feature.feature toolset : : implicit propagated symmetric ;
110 feature.feature stdlib : native : propagated composite ;
111 feature.feature link : shared static : propagated ;
112 feature.feature runtime-link : shared static : propagated ;
113 feature.feature runtime-debugging : on off : propagated ;
114 feature.feature optimization : off speed space : propagated ;
115 feature.feature profiling : off on : propagated ;
116 feature.feature inlining : off on full : propagated ;
117 feature.feature threading : single multi : propagated ;
118 feature.feature rtti : on off : propagated ;
119 feature.feature exception-handling : on off : propagated ;
120
121 # Whether there is support for asynchronous EH (e.g. catching SEGVs).
122 feature.feature asynch-exceptions : off on : propagated ;
123
124 # Whether all extern "C" functions are considered nothrow by default.
125 feature.feature extern-c-nothrow : off on : propagated ;
126
127 feature.feature debug-symbols : on off : propagated ;
128 # Controls whether the binary should be stripped -- that is have
129 # everything not necessary to running removed. This option should
130 # not be very often needed. Also, this feature will show up in
131 # target paths of everything, not just binaries. Should fix that
132 # when implementing feature relevance.
133 feature.feature strip : off on : propagated ;
134 feature.feature define : : free ;
135 feature.feature undef : : free ;
136 feature.feature "include" : : free path ; #order-sensitive ;
137 feature.feature cflags : : free ;
138 feature.feature cxxflags : : free ;
139 feature.feature fflags : : free ;
140 feature.feature asmflags : : free ;
141 feature.feature linkflags : : free ;
142 feature.feature archiveflags : : free ;
143 feature.feature version : : free ;
144 feature.feature mflags : : free ;
145 feature.feature mmflags : : free ;
146
147 # Generic, i.e. non-language specific, flags for tools.
148 feature.feature flags : : free ;
149 feature.feature location-prefix : : free ;
150
151
152 # The following features are incidental since they have no effect on built
153 # products. Not making them incidental will result in problems in corner cases,
154 # e.g.:
155 #
156 # unit-test a : a.cpp : <use>b ;
157 # lib b : a.cpp b ;
158 #
159 # Here, if <use> is not incidental, we would decide we have two targets for
160 # a.obj with different properties and complain about it.
161 #
162 # Note that making a feature incidental does not mean it is ignored. It may be
163 # ignored when creating a virtual target, but the rest of build process will use
164 # them.
165 feature.feature use : : free dependency incidental ;
166 feature.feature dependency : : free dependency incidental ;
167 feature.feature implicit-dependency : : free dependency incidental ;
168
169 feature.feature warnings :
170 on # Enable default/"reasonable" warning level for the tool.
171 all # Enable all possible warnings issued by the tool.
172 off # Disable all warnings issued by the tool.
173 : incidental propagated ;
174
175 feature.feature warnings-as-errors :
176 off # Do not fail the compilation if there are warnings.
177 on # Fail the compilation if there are warnings.
178 : incidental propagated ;
179
180 # Feature that allows us to configure the maximal template instantiation depth
181 # level allowed by a C++ compiler. Applies only to C++ toolsets whose compilers
182 # actually support this configuration setting.
183 #
184 # Note that Boost Build currently does not allow defining features that take any
185 # positive integral value as a parameter, which is what we need here, so we just
186 # define some of the values here and leave it up to the user to extend this set
187 # as he needs using the feature.extend rule.
188 #
189 # TODO: This should be upgraded as soon as Boost Build adds support for custom
190 # validated feature values or at least features allowing any positive integral
191 # value. See related Boost Build related trac ticket #194.
192 #
193 feature.feature c++-template-depth
194 :
195 [ numbers.range 64 1024 : 64 ]
196 [ numbers.range 20 1000 : 10 ]
197 # Maximum template instantiation depth guaranteed for ANSI/ISO C++
198 # conforming programs.
199 17
200 :
201 incidental optional propagated ;
202
203 feature.feature source : : free dependency incidental ;
204 feature.feature library : : free dependency incidental ;
205 feature.feature file : : free dependency incidental ;
206 feature.feature find-shared-library : : free ; #order-sensitive ;
207 feature.feature find-static-library : : free ; #order-sensitive ;
208 feature.feature library-path : : free path ; #order-sensitive ;
209
210 # Internal feature.
211 feature.feature library-file : : free dependency ;
212
213 feature.feature name : : free ;
214 feature.feature tag : : free ;
215 feature.feature search : : free path ; #order-sensitive ;
216 feature.feature location : : free path ;
217 feature.feature dll-path : : free path ;
218 feature.feature hardcode-dll-paths : true false : incidental ;
219
220
221 # An internal feature that holds the paths of all dependency shared libraries.
222 # On Windows, it is needed so that we can add all those paths to PATH when
223 # running applications. On Linux, it is needed to add proper -rpath-link command
224 # line options.
225 feature.feature xdll-path : : free path ;
226
227 # Provides means to specify def-file for windows DLLs.
228 feature.feature def-file : : free dependency ;
229
230 feature.feature suppress-import-lib : false true : incidental ;
231
232 # Internal feature used to store the name of a bjam action to call when building
233 # a target.
234 feature.feature action : : free ;
235
236 # This feature is used to allow specific generators to run. For example, QT
237 # tools can only be invoked when QT library is used. In that case, <allow>qt
238 # will be in usage requirement of the library.
239 feature.feature allow : : free ;
240
241 # The addressing model to generate code for. Currently a limited set only
242 # specifying the bit size of pointers.
243 feature.feature address-model : 16 32 64 32_64 : propagated optional ;
244
245 # Type of CPU architecture to compile for.
246 feature.feature architecture :
247 # x86 and x86-64
248 x86
249
250 # ia64
251 ia64
252
253 # Sparc
254 sparc
255
256 # RS/6000 & PowerPC
257 power
258
259 # MIPS/SGI
260 mips1 mips2 mips3 mips4 mips32 mips32r2 mips64
261
262 # HP/PA-RISC
263 parisc
264
265 # Advanced RISC Machines
266 arm
267
268 # Combined architectures for platforms/toolsets that support building for
269 # multiple architectures at once. "combined" would be the default multi-arch
270 # for the toolset.
271 combined
272 combined-x86-power
273
274 : propagated optional ;
275
276 # The specific instruction set in an architecture to compile.
277 feature.feature instruction-set :
278 # x86 and x86-64
279 native i486 i586 i686 pentium pentium-mmx pentiumpro pentium2 pentium3
280 pentium3m pentium-m pentium4 pentium4m prescott nocona core2 corei7 corei7-avx core-avx-i
281 conroe conroe-xe conroe-l allendale merom merom-xe kentsfield kentsfield-xe penryn wolfdale
282 yorksfield nehalem sandy-bridge ivy-bridge haswell k6 k6-2 k6-3 athlon athlon-tbird athlon-4 athlon-xp
283 athlon-mp k8 opteron athlon64 athlon-fx k8-sse3 opteron-sse3 athlon64-sse3 amdfam10 barcelona
284 bdver1 bdver2 bdver3 btver1 btver2 winchip-c6 winchip2 c3 c3-2 atom
285
286 # ia64
287 itanium itanium1 merced itanium2 mckinley
288
289 # Sparc
290 v7 cypress v8 supersparc sparclite hypersparc sparclite86x f930 f934
291 sparclet tsc701 v9 ultrasparc ultrasparc3
292
293 # RS/6000 & PowerPC
294 401 403 405 405fp 440 440fp 505 601 602 603 603e 604 604e 620 630 740 7400
295 7450 750 801 821 823 860 970 8540 power-common ec603e g3 g4 g5 power power2
296 power3 power4 power5 powerpc powerpc64 rios rios1 rsc rios2 rs64a
297
298 # MIPS
299 4kc 4kp 5kc 20kc m4k r2000 r3000 r3900 r4000 r4100 r4300 r4400 r4600 r4650
300 r6000 r8000 rm7000 rm9000 orion sb1 vr4100 vr4111 vr4120 vr4130 vr4300
301 vr5000 vr5400 vr5500
302
303 # HP/PA-RISC
304 700 7100 7100lc 7200 7300 8000
305
306 # Advanced RISC Machines
307 armv2 armv2a armv3 armv3m armv4 armv4t armv5 armv5t armv5te armv6 armv6j iwmmxt ep9312
308 armv7 armv7s
309
310 : propagated optional ;
311
312 # Used to select a specific variant of C++ ABI if the compiler supports several.
313 feature.feature c++abi : : propagated optional ;
314
315 feature.feature conditional : : incidental free ;
316
317 # The value of 'no' prevents building of a target.
318 feature.feature build : yes no : optional ;
319
320 # Windows-specific features
321
322 feature.feature user-interface : console gui wince native auto ;
323
324 feature.feature variant : : implicit composite propagated symmetric ;
325
326
327 # Declares a new variant.
328 #
329 # First determines explicit properties for this variant, by refining parents'
330 # explicit properties with the passed explicit properties. The result is
331 # remembered and will be used if this variant is used as parent.
332 #
333 # Second, determines the full property set for this variant by adding to the
334 # explicit properties default values for all missing non-symmetric properties.
335 #
336 # Lastly, makes appropriate value of 'variant' property expand to the full
337 # property set.
338 #
339 rule variant ( name # Name of the variant
340 : parents-or-properties * # Specifies parent variants, if
341 # 'explicit-properties' are given, and
342 # explicit-properties or parents otherwise.
343 : explicit-properties * # Explicit properties.
344 )
345 {
346 local parents ;
347 if ! $(explicit-properties)
348 {
349 if $(parents-or-properties[1]:G)
350 {
351 explicit-properties = $(parents-or-properties) ;
352 }
353 else
354 {
355 parents = $(parents-or-properties) ;
356 }
357 }
358 else
359 {
360 parents = $(parents-or-properties) ;
361 }
362
363 # The problem is that we have to check for conflicts between base variants.
364 if $(parents[2])
365 {
366 errors.error "multiple base variants are not yet supported" ;
367 }
368
369 local inherited ;
370 # Add explicitly specified properties for parents.
371 for local p in $(parents)
372 {
373 # TODO: This check may be made stricter.
374 if ! [ feature.is-implicit-value $(p) ]
375 {
376 errors.error "Invalid base variant" $(p) ;
377 }
378
379 inherited += $(.explicit-properties.$(p)) ;
380 }
381 property.validate $(explicit-properties) ;
382 explicit-properties = [ property.refine $(inherited)
383 : $(explicit-properties) ] ;
384
385 # Record explicitly specified properties for this variant. We do this after
386 # inheriting parents' properties so they affect other variants derived from
387 # this one.
388 .explicit-properties.$(name) = $(explicit-properties) ;
389
390 feature.extend variant : $(name) ;
391 feature.compose <variant>$(name) : $(explicit-properties) ;
392 }
393 IMPORT $(__name__) : variant : : variant ;
394
395
396 variant debug : <optimization>off <debug-symbols>on <inlining>off
397 <runtime-debugging>on ;
398 variant release : <optimization>speed <debug-symbols>off <inlining>full
399 <runtime-debugging>off <define>NDEBUG ;
400 variant profile : release : <profiling>on <debug-symbols>on ;
401
402
403 class searched-lib-target : abstract-file-target
404 {
405 rule __init__ ( name
406 : project
407 : shared ?
408 : search *
409 : action
410 )
411 {
412 abstract-file-target.__init__ $(name) : SEARCHED_LIB : $(project)
413 : $(action) : ;
414
415 self.shared = $(shared) ;
416 self.search = $(search) ;
417 }
418
419 rule shared ( )
420 {
421 return $(self.shared) ;
422 }
423
424 rule search ( )
425 {
426 return $(self.search) ;
427 }
428
429 rule actualize-location ( target )
430 {
431 NOTFILE $(target) ;
432 }
433
434 rule path ( )
435 {
436 }
437 }
438
439
440 # The generator class for libraries (target type LIB). Depending on properties
441 # it will request building of the appropriate specific library type --
442 # -- SHARED_LIB, STATIC_LIB or SHARED_LIB.
443 #
444 class lib-generator : generator
445 {
446 rule __init__ ( * : * )
447 {
448 generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8)
449 : $(9) : $(10) : $(11) : $(12) : $(13) : $(14) : $(15) : $(16) :
450 $(17) : $(18) : $(19) ;
451 }
452
453 rule run ( project name ? : property-set : sources * )
454 {
455 # The lib generator is composing, and can be only invoked with an
456 # explicit name. This check is present in generator.run (and so in
457 # builtin.linking-generator) but duplicated here to avoid doing extra
458 # work.
459 if $(name)
460 {
461 local properties = [ $(property-set).raw ] ;
462 # Determine the needed target type.
463 local actual-type ;
464 # <source>files can be generated by <conditional>@rule feature
465 # in which case we do not consider it a SEARCHED_LIB type.
466 if ! <source> in $(properties:G) &&
467 ( <search> in $(properties:G) || <name> in $(properties:G) )
468 {
469 actual-type = SEARCHED_LIB ;
470 }
471 else if <file> in $(properties:G)
472 {
473 actual-type = LIB ;
474 }
475 else if <link>shared in $(properties)
476 {
477 actual-type = SHARED_LIB ;
478 }
479 else
480 {
481 actual-type = STATIC_LIB ;
482 }
483 property-set = [ $(property-set).add-raw <main-target-type>LIB ] ;
484 # Construct the target.
485 return [ generators.construct $(project) $(name) : $(actual-type)
486 : $(property-set) : $(sources) ] ;
487 }
488 }
489
490 rule viable-source-types ( )
491 {
492 return * ;
493 }
494 }
495
496
497 generators.register [ new lib-generator builtin.lib-generator : : LIB ] ;
498
499
500 # The implementation of the 'lib' rule. Beyond standard syntax that rule allows
501 # simplified: "lib a b c ;".
502 #
503 rule lib ( names + : sources * : requirements * : default-build * :
504 usage-requirements * )
505 {
506 if $(names[2])
507 {
508 if <name> in $(requirements:G)
509 {
510 errors.user-error "When several names are given to the 'lib' rule" :
511 "it is not allowed to specify the <name> feature." ;
512 }
513 if $(sources)
514 {
515 errors.user-error "When several names are given to the 'lib' rule" :
516 "it is not allowed to specify sources." ;
517 }
518 }
519
520 # This is a circular module dependency so it must be imported here.
521 import targets ;
522
523 local project = [ project.current ] ;
524 local result ;
525
526 for local name in $(names)
527 {
528 local r = $(requirements) ;
529 # Support " lib a ; " and " lib a b c ; " syntax.
530 if ! $(sources) && ! <name> in $(requirements:G)
531 && ! <file> in $(requirements:G)
532 {
533 r += <name>$(name) ;
534 }
535 result += [ targets.main-target-alternative
536 [ new typed-target $(name) : $(project) : LIB
537 : [ targets.main-target-sources $(sources) : $(name) ]
538 : [ targets.main-target-requirements $(r) : $(project) ]
539 : [ targets.main-target-default-build $(default-build) : $(project) ]
540 : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
541 ] ] ;
542 }
543 return $(result) ;
544 }
545 IMPORT $(__name__) : lib : : lib ;
546
547
548 class searched-lib-generator : generator
549 {
550 import property-set ;
551
552 rule __init__ ( )
553 {
554 # The requirements cause the generators to be tried *only* when we are
555 # building a lib target with a 'search' feature. This seems ugly --- all
556 # we want is to make sure searched-lib-generator is not invoked deep
557 # inside transformation search to produce intermediate targets.
558 generator.__init__ searched-lib-generator : : SEARCHED_LIB ;
559 }
560
561 rule run ( project name ? : property-set : sources * )
562 {
563 if $(name)
564 {
565 # If 'name' is empty, it means we have not been called to build a
566 # top-level target. In this case, we just fail immediately, because
567 # searched-lib-generator cannot be used to produce intermediate
568 # targets.
569
570 local properties = [ $(property-set).raw ] ;
571 local shared ;
572 if <link>shared in $(properties)
573 {
574 shared = true ;
575 }
576
577 local search = [ feature.get-values <search> : $(properties) ] ;
578
579 local a = [ new null-action $(property-set) ] ;
580 local lib-name = [ feature.get-values <name> : $(properties) ] ;
581 lib-name ?= $(name) ;
582 local t = [ new searched-lib-target $(lib-name) : $(project)
583 : $(shared) : $(search) : $(a) ] ;
584 # We return sources for a simple reason. If there is
585 # lib png : z : <name>png ;
586 # the 'z' target should be returned, so that apps linking to 'png'
587 # will link to 'z', too.
588 return [ property-set.create <xdll-path>$(search) ]
589 [ virtual-target.register $(t) ] $(sources) ;
590 }
591 }
592 }
593
594 generators.register [ new searched-lib-generator ] ;
595
596
597 class prebuilt-lib-generator : generator
598 {
599 rule __init__ ( * : * )
600 {
601 generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8)
602 : $(9) : $(10) : $(11) : $(12) : $(13) : $(14) : $(15) : $(16) :
603 $(17) : $(18) : $(19) ;
604 }
605
606 rule run ( project name ? : property-set : sources * )
607 {
608 local f = [ $(property-set).get <file> ] ;
609 return $(f) $(sources) ;
610 }
611 }
612
613 generators.register
614 [ new prebuilt-lib-generator builtin.prebuilt : : LIB : <file> ] ;
615
616 generators.override builtin.prebuilt : builtin.lib-generator ;
617
618 class preprocessed-target-class : basic-target
619 {
620 import generators ;
621 rule construct ( name : sources * : property-set )
622 {
623 local result = [ generators.construct [ project ]
624 $(name) : PREPROCESSED_CPP : $(property-set) : $(sources) ] ;
625 if ! $(result)
626 {
627 result = [ generators.construct [ project ]
628 $(name) : PREPROCESSED_C : $(property-set) : $(sources) ] ;
629 }
630 if ! $(result)
631 {
632 local s ;
633 for x in $(sources)
634 {
635 s += [ $(x).name ] ;
636 }
637 local p = [ project ] ;
638 errors.user-error
639 "In project" [ $(p).name ] :
640 "Could not construct preprocessed file \"$(name)\" from $(s:J=, )." ;
641 }
642 return $(result) ;
643 }
644 }
645
646 rule preprocessed ( name : sources * : requirements * : default-build * :
647 usage-requirements * )
648 {
649 local project = [ project.current ] ;
650 return [ targets.main-target-alternative
651 [ new preprocessed-target-class $(name) : $(project)
652 : [ targets.main-target-sources $(sources) : $(name) ]
653 : [ targets.main-target-requirements $(requirements) : $(project) ]
654 : [ targets.main-target-default-build $(default-build) : $(project) ]
655 : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
656 ] ] ;
657 }
658
659 IMPORT $(__name__) : preprocessed : : preprocessed ;
660
661 class compile-action : action
662 {
663 import sequence ;
664
665 rule __init__ ( targets * : sources * : action-name : properties * )
666 {
667 action.__init__ $(targets) : $(sources) : $(action-name) : $(properties) ;
668 }
669
670 # For all virtual targets for the same dependency graph as self, i.e. which
671 # belong to the same main target, add their directories to the include path.
672 #
673 rule adjust-properties ( property-set )
674 {
675 local s = [ $(self.targets[1]).creating-subvariant ] ;
676 if $(s)
677 {
678 return [ $(property-set).add-raw
679 [ $(s).implicit-includes "include" : H ] ] ;
680 }
681 else
682 {
683 return $(property-set) ;
684 }
685 }
686 }
687
688
689 # Declare a special compiler generator. The only thing it does is changing the
690 # type used to represent 'action' in the constructed dependency graph to
691 # 'compile-action'. That class in turn adds additional include paths to handle
692 # cases when a source file includes headers which are generated themselves.
693 #
694 class C-compiling-generator : generator
695 {
696 rule __init__ ( id : source-types + : target-types + : requirements *
697 : optional-properties * )
698 {
699 generator.__init__ $(id) : $(source-types) : $(target-types) :
700 $(requirements) : $(optional-properties) ;
701 }
702
703 rule action-class ( )
704 {
705 return compile-action ;
706 }
707 }
708
709
710 rule register-c-compiler ( id : source-types + : target-types + : requirements *
711 : optional-properties * )
712 {
713 generators.register [ new C-compiling-generator $(id) : $(source-types) :
714 $(target-types) : $(requirements) : $(optional-properties) ] ;
715 }
716
717 # FIXME: this is ugly, should find a better way (we would like client code to
718 # register all generators as "generators.some-rule" instead of
719 # "some-module.some-rule".)
720 #
721 IMPORT $(__name__) : register-c-compiler : : generators.register-c-compiler ;
722
723
724 # The generator class for handling EXE and SHARED_LIB creation.
725 #
726 class linking-generator : generator
727 {
728 import path ;
729 import project ;
730 import property-set ;
731 import type ;
732
733 rule __init__ ( id
734 composing ? : # The generator will be composing if a non-empty
735 # string is passed or the parameter is not given. To
736 # make the generator non-composing, pass an empty
737 # string ("").
738 source-types + :
739 target-types + :
740 requirements * )
741 {
742 composing ?= true ;
743 generator.__init__ $(id) $(composing) : $(source-types)
744 : $(target-types) : $(requirements) ;
745 }
746
747 rule run ( project name ? : property-set : sources + )
748 {
749 sources += [ $(property-set).get <library> ] ;
750
751 # Add <library-path> properties for all searched libraries.
752 local extra ;
753 for local s in $(sources)
754 {
755 if [ $(s).type ] = SEARCHED_LIB
756 {
757 local search = [ $(s).search ] ;
758 extra += <library-path>$(search) ;
759 }
760 }
761
762 # It is possible that sources include shared libraries that did not came
763 # from 'lib' targets, e.g. .so files specified as sources. In this case
764 # we have to add extra dll-path properties and propagate extra xdll-path
765 # properties so that application linking to us will get xdll-path to
766 # those libraries.
767 local extra-xdll-paths ;
768 for local s in $(sources)
769 {
770 if [ type.is-derived [ $(s).type ] SHARED_LIB ] && ! [ $(s).action ]
771 {
772 # Unfortunately, we do not have a good way to find the path to a
773 # file, so use this nasty approach.
774 #
775 # TODO: This needs to be done better. One thing that is really
776 # broken with this is that it does not work correctly with
777 # projects having multiple source locations.
778 local p = [ $(s).project ] ;
779 local location = [ path.root [ $(s).name ]
780 [ $(p).get source-location ] ] ;
781 extra-xdll-paths += [ path.parent $(location) ] ;
782 }
783 }
784
785 # Hardcode DLL paths only when linking executables.
786 # Pros: do not need to relink libraries when installing.
787 # Cons: "standalone" libraries (plugins, python extensions) can not
788 # hardcode paths to dependent libraries.
789 if [ $(property-set).get <hardcode-dll-paths> ] = true
790 && [ type.is-derived $(self.target-types[1]) EXE ]
791 {
792 local xdll-path = [ $(property-set).get <xdll-path> ] ;
793 extra += <dll-path>$(xdll-path) <dll-path>$(extra-xdll-paths) ;
794 }
795
796 if $(extra)
797 {
798 property-set = [ $(property-set).add-raw $(extra) ] ;
799 }
800
801 local result = [ generator.run $(project) $(name) : $(property-set)
802 : $(sources) ] ;
803
804 local ur ;
805 if $(result)
806 {
807 ur = [ extra-usage-requirements $(result) : $(property-set) ] ;
808 ur = [ $(ur).add
809 [ property-set.create <xdll-path>$(extra-xdll-paths) ] ] ;
810 }
811 return $(ur) $(result) ;
812 }
813
814 rule extra-usage-requirements ( created-targets * : property-set )
815 {
816 local result = [ property-set.empty ] ;
817 local extra ;
818
819 # Add appropriate <xdll-path> usage requirements.
820 local raw = [ $(property-set).raw ] ;
821 if <link>shared in $(raw)
822 {
823 local paths ;
824 local pwd = [ path.pwd ] ;
825 for local t in $(created-targets)
826 {
827 if [ type.is-derived [ $(t).type ] SHARED_LIB ]
828 {
829 paths += [ path.root [ path.make [ $(t).path ] ] $(pwd) ] ;
830 }
831 }
832 extra += $(paths:G=<xdll-path>) ;
833 }
834
835 # We need to pass <xdll-path> features that we've got from sources,
836 # because if a shared library is built, exe using it needs to know paths
837 # to other shared libraries this one depends on in order to be able to
838 # find them all at runtime.
839
840 # Just pass all features in property-set, it is theoretically possible
841 # that we will propagate <xdll-path> features explicitly specified by
842 # the user, but then the user is to blame for using an internal feature.
843 local values = [ $(property-set).get <xdll-path> ] ;
844 extra += $(values:G=<xdll-path>) ;
845
846 if $(extra)
847 {
848 result = [ property-set.create $(extra) ] ;
849 }
850 return $(result) ;
851 }
852
853 rule generated-targets ( sources + : property-set : project name ? )
854 {
855 local sources2 ; # Sources to pass to inherited rule.
856 local properties2 ; # Properties to pass to inherited rule.
857 local libraries ; # Library sources.
858
859 # Searched libraries are not passed as arguments to the linker but via
860 # some option. So, we pass them to the action using a property.
861 properties2 = [ $(property-set).raw ] ;
862 local fsa ;
863 local fst ;
864 for local s in $(sources)
865 {
866 if [ type.is-derived [ $(s).type ] SEARCHED_LIB ]
867 {
868 local name = [ $(s).name ] ;
869 if [ $(s).shared ]
870 {
871 fsa += $(name) ;
872 }
873 else
874 {
875 fst += $(name) ;
876 }
877 }
878 else
879 {
880 sources2 += $(s) ;
881 }
882 }
883 properties2 += <find-shared-library>$(fsa:J=&&)
884 <find-static-library>$(fst:J=&&) ;
885
886 return [ generator.generated-targets $(sources2)
887 : [ property-set.create $(properties2) ] : $(project) $(name) ] ;
888 }
889 }
890
891
892 rule register-linker ( id composing ? : source-types + : target-types +
893 : requirements * )
894 {
895 generators.register [ new linking-generator $(id) $(composing)
896 : $(source-types) : $(target-types) : $(requirements) ] ;
897 }
898
899
900 # The generator class for handling STATIC_LIB creation.
901 #
902 class archive-generator : generator
903 {
904 import property-set ;
905
906 rule __init__ ( id composing ? : source-types + : target-types +
907 : requirements * )
908 {
909 composing ?= true ;
910 generator.__init__ $(id) $(composing) : $(source-types)
911 : $(target-types) : $(requirements) ;
912 }
913
914 rule run ( project name ? : property-set : sources + )
915 {
916 sources += [ $(property-set).get <library> ] ;
917
918 local result = [ generator.run $(project) $(name) : $(property-set)
919 : $(sources) ] ;
920
921 # For static linking, if we get a library in source, we can not directly
922 # link to it so we need to cause our dependencies to link to that
923 # library. There are two approaches:
924 # - adding the library to the list of returned targets.
925 # - using the <library> usage requirements.
926 # The problem with the first is:
927 #
928 # lib a1 : : <file>liba1.a ;
929 # lib a2 : a2.cpp a1 : <link>static ;
930 # install dist : a2 ;
931 #
932 # here we will try to install 'a1', even though it is not necessary in
933 # the general case. With the second approach, even indirect dependants
934 # will link to the library, but it should not cause any harm. So, return
935 # all LIB sources together with created targets, so that dependants link
936 # to them.
937 local usage-requirements ;
938 if [ $(property-set).get <link> ] = static
939 {
940 for local t in $(sources)
941 {
942 if [ type.is-derived [ $(t).type ] LIB ]
943 {
944 usage-requirements += <library>$(t) ;
945 }
946 }
947 }
948
949 usage-requirements = [ property-set.create $(usage-requirements) ] ;
950
951 return $(usage-requirements) $(result) ;
952 }
953 }
954
955
956 rule register-archiver ( id composing ? : source-types + : target-types +
957 : requirements * )
958 {
959 generators.register [ new archive-generator $(id) $(composing)
960 : $(source-types) : $(target-types) : $(requirements) ] ;
961 }
962
963
964 # Generator that accepts everything and produces nothing. Useful as a general
965 # fallback for toolset-specific actions like PCH generation.
966 #
967 class dummy-generator : generator
968 {
969 import property-set ;
970
971 rule run ( project name ? : property-set : sources + )
972 {
973 return [ property-set.empty ] ;
974 }
975 }
976
977 IMPORT $(__name__) : register-linker register-archiver
978 : : generators.register-linker generators.register-archiver ;