1 | #~ Copyright 2002-2004 Rene Rivera. |
---|
2 | #~ Copyright 2001-2004 David Abrahams. |
---|
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 | # (C) Copyright David Abrahams and Carlos Pinto Coelho 2001. Permission to |
---|
7 | # copy, use, modify, sell and distribute this software is granted provided this |
---|
8 | # copyright notice appears in all copies. This software is provided "as is" |
---|
9 | # without express or implied warranty, and with no claim as to its suitability |
---|
10 | # for any purpose. |
---|
11 | # |
---|
12 | # Jamrules file by David Abrahams (abrahams@mediaone.net) and Carlos Pinto |
---|
13 | # Coelho (cfspc@altrabroadband.com). |
---|
14 | |
---|
15 | # Notes on the design of the system: |
---|
16 | # |
---|
17 | # This system is designed to support building the "same" targets with multiple |
---|
18 | # build tool suites (e.g. msvc, gcc,...) and build variants (e.g. debug, |
---|
19 | # release...). Although it currently varies across two dimensions, it should |
---|
20 | # trivially support extension to three or more, e.g. in case of cross-platform |
---|
21 | # builds. The word "same" is written in quotes above because internally, |
---|
22 | # separate targets are generated for each unique toolset/build-variant |
---|
23 | # combination. |
---|
24 | # |
---|
25 | # Specifics of build tool suites are specified in files with names of the form |
---|
26 | # "<name>-tools.jam", where <name> is the name used to identify the tool suite. |
---|
27 | |
---|
28 | # Workarounds for Jam limitations: |
---|
29 | # |
---|
30 | # 1. Jam supports something like the setting of attributes on targets using the |
---|
31 | # syntax: |
---|
32 | # <name> on <target> = <expression> |
---|
33 | # |
---|
34 | # This facility is used to control build actions for individual targets |
---|
35 | # (target-specific variables take precedence over global ones when build |
---|
36 | # actions # are executed). An obvious approach would be to use target |
---|
37 | # attributes to hold # properties of build tools (e.g. where to find the |
---|
38 | # standard includes). # Unfortunately, although you can write target |
---|
39 | # attributes, there is no way to # read them. Instead, we take advantage of |
---|
40 | # two properties of Jam: |
---|
41 | # |
---|
42 | # a. A variable name can be formed by evaluating an expression. For example, |
---|
43 | # the following rule, appends FOOBAR to its first argument to form the |
---|
44 | # name of a new variable, which is given the value "baz" |
---|
45 | # |
---|
46 | # rule X { $(1)FOOBAR = baz ; } |
---|
47 | # |
---|
48 | # b. Any character is allowed in a variable name. So, although they are |
---|
49 | # actually global variables, we can form names like <name>.c++-flags thus: |
---|
50 | # |
---|
51 | # C++FLAGS = $($(1).c++-flags) # Get the c++-flags "attribute" from $(1) |
---|
52 | # |
---|
53 | # 2. There is no way to call a rule based on the value of a variable |
---|
54 | # other than by using a switch statement. Because that approach requires |
---|
55 | # intrusive changes to rules when the system is extended, we have avoided |
---|
56 | # it. Instead, we have taken advantage of two "features" of Jam: |
---|
57 | # |
---|
58 | # a. The name of a file to be included can be computed from an |
---|
59 | # expression. For example, the following includes a file whose name is |
---|
60 | # formed by concatenating $(1) and "-tools.jam": |
---|
61 | # |
---|
62 | # include $(1)-tools.jam |
---|
63 | # |
---|
64 | # b. A rule can be redefined any number of times. Its latest definition is |
---|
65 | # the one invoked. For example, the following prints "#2". |
---|
66 | # |
---|
67 | # rule X { ECHO #1 ; } |
---|
68 | # rule X { ECHO #2 ; } |
---|
69 | # X ; |
---|
70 | # |
---|
71 | # Together, these facts allow us to select tool-suite-specific actions for |
---|
72 | # building specific target types by repeatedly redefining the generalized |
---|
73 | # build actions in the various <build-tools>-tools.jam files |
---|
74 | |
---|
75 | if $(NT) |
---|
76 | { |
---|
77 | TOOLS ?= vc-7_1 ; |
---|
78 | } |
---|
79 | else if $(UNIX) |
---|
80 | { |
---|
81 | switch $(JAMUNAME) |
---|
82 | { |
---|
83 | case Darwin* : |
---|
84 | { |
---|
85 | TOOLS ?= darwin ; |
---|
86 | } |
---|
87 | |
---|
88 | case * : |
---|
89 | { |
---|
90 | TOOLS ?= gcc ; |
---|
91 | } |
---|
92 | } |
---|
93 | } |
---|
94 | else |
---|
95 | { |
---|
96 | TOOLS ?= gcc ; |
---|
97 | } |
---|
98 | |
---|
99 | SHARED_TYPES = DLL ; |
---|
100 | STATIC_TYPES = LIB ; |
---|
101 | |
---|
102 | # detect-build-tools <tools-name> : <detection-command> |
---|
103 | # |
---|
104 | # Declares a pseudotarget for the specified build tools which is built by |
---|
105 | # the given <detection-command>. |
---|
106 | # |
---|
107 | # Although not currently implemented, the plan is to make compilation of |
---|
108 | # tool-specific targets dependent on this pseudotarget. That way, we will never |
---|
109 | # even attempt to build targets for tools that don't exist. |
---|
110 | rule detect-build-tools |
---|
111 | { |
---|
112 | detection-command on $(<) = $($(<).bin-directory)$(>) ; |
---|
113 | } |
---|
114 | |
---|
115 | # lib: generator function |
---|
116 | # |
---|
117 | rule library-file ( target : sources + ) |
---|
118 | { |
---|
119 | LibraryFromObjects $(<) : [ Objects $(>) ] ; |
---|
120 | } |
---|
121 | |
---|
122 | # exe: generator function |
---|
123 | # |
---|
124 | rule executable-file ( target : sources + ) |
---|
125 | { |
---|
126 | type-DEPENDS exe : $(<) ; |
---|
127 | main-from-objects $(<) : [ Objects $(>) ] : EXE ; |
---|
128 | } |
---|
129 | |
---|
130 | # dll: generator function |
---|
131 | # |
---|
132 | rule dll-files ( module implib ? : sources * : target-type ? ) |
---|
133 | { |
---|
134 | type-DEPENDS dll : $(<) ; |
---|
135 | |
---|
136 | # Set up the import library dependency on Windows |
---|
137 | if $(<[2]) |
---|
138 | { |
---|
139 | INCLUDES $(<[1]) : $(<[2-]) ; |
---|
140 | INCLUDES $(<[2-]) : $(<[1]) ; |
---|
141 | } |
---|
142 | |
---|
143 | target-type ?= DLL ; |
---|
144 | if [ MATCH ^(CRAY).* : $(JAMUNAME[-1]) ] # no shared libs on cray |
---|
145 | { |
---|
146 | NOTFILE $(<) ; |
---|
147 | } |
---|
148 | else |
---|
149 | { |
---|
150 | main-from-objects $(<) : [ Objects $(>) ] : $(target-type) ; |
---|
151 | } |
---|
152 | } |
---|
153 | |
---|
154 | # template: modifier function |
---|
155 | # |
---|
156 | # The target specs are modified by adding those previously specified in a template source. |
---|
157 | # Any specs containing paths are rerooted to correctly reference the dependee locations. |
---|
158 | # |
---|
159 | rule template-modifier ( target : source ) |
---|
160 | { |
---|
161 | local source-dir = [ directory-of $(source:G=) ] ; |
---|
162 | local source-id = [ target-id-of $(source) ] ; |
---|
163 | |
---|
164 | # Make sure it's defined. |
---|
165 | # |
---|
166 | if ! $(gTARGET_TYPE($(source-id))) |
---|
167 | { |
---|
168 | dependent-include $(source:G=) ; |
---|
169 | } |
---|
170 | |
---|
171 | # Copy the base specs into the target specs, adjust any paths |
---|
172 | # |
---|
173 | gTARGET_SOURCES($(target)) += |
---|
174 | [ root-paths $(gTARGET_SOURCES($(source-id))) : $(source-dir) ] ; |
---|
175 | gTARGET_DEPS($(target)) += |
---|
176 | [ root-paths $(gTARGET_DEPS($(source-id))) : $(source-dir) ] ; |
---|
177 | gTARGET_REQUIREMENTS($(target)) += |
---|
178 | [ fixup-path-properties $(gTARGET_REQUIREMENTS($(source-id))) : $(source-dir) ] ; |
---|
179 | gTARGET_DEFAULT_BUILD($(target)) += |
---|
180 | $(gTARGET_DEFAULT_BUILD($(source-id))) ; |
---|
181 | } |
---|
182 | |
---|
183 | # main-from-objects exe-target : obj-target... : ("EXE"|"DLL") |
---|
184 | # |
---|
185 | # generate instructions to build the given "main" target from the given object |
---|
186 | # files given in the 2nd parameter. The 3rd parameter should be EXE for an |
---|
187 | # executable, or DLL for a shared library. |
---|
188 | rule main-from-objects ( targets * : objects * : type ) |
---|
189 | { |
---|
190 | # make compiled sources a dependency of target |
---|
191 | |
---|
192 | MakeLocate $(targets) : $(LOCATE_TARGET) ; |
---|
193 | |
---|
194 | Clean clean : $(targets) ; |
---|
195 | |
---|
196 | MODE on $(targets) = $($(type)MODE) ; |
---|
197 | local link-function = Link-$(type) ; |
---|
198 | local extra-files = [ $(link-function) $(targets) : $(objects) : $(type) ] ; |
---|
199 | Chmod $(targets[1]) ; |
---|
200 | DEPENDS $(targets) : $(objects) ; |
---|
201 | |
---|
202 | # locate and attach the extra files generated |
---|
203 | if $(extra-files) |
---|
204 | { |
---|
205 | MakeLocate $(extra-files) : $(LOCATE_TARGET) ; |
---|
206 | DEPENDS $(targets) : $(extra-files) ; |
---|
207 | } |
---|
208 | |
---|
209 | gFILES($(targets[1])) = $(targets) $(extra-files) ; |
---|
210 | } |
---|
211 | |
---|
212 | rule .do-link ( targets + : sources + : type ) |
---|
213 | { |
---|
214 | # Prepare NEEDLIBS for use by the toolsets' link action (e.g. for |
---|
215 | # invoking with-command-file) |
---|
216 | local NEEDLIBS = [ on $(<) return $(NEEDLIBS) ] ; |
---|
217 | |
---|
218 | return [ Link-action $(targets) : $(sources) : $(type) ] ; |
---|
219 | } |
---|
220 | |
---|
221 | rule Link-EXE |
---|
222 | { |
---|
223 | # N.B. By the time this rule is invoked, we had better have gRUN_PATH completely set. |
---|
224 | |
---|
225 | local extra-files = [ .do-link $(<) : $(>) : EXE ] ; |
---|
226 | RUN_PATH on $(<) = [ join [ unique $(gRUN_PATH($(<))) $(gTOOLSET_LIB_PATH) ] : $(SPLITPATH) ] ; |
---|
227 | if $(UNIX) |
---|
228 | { |
---|
229 | LINK_LIBPATH on $(<) = [ join $(gRUN_LD_LIBRARY_PATH($(<))) : $(SPLITPATH) ] ; |
---|
230 | } |
---|
231 | |
---|
232 | return $(extra-files) ; |
---|
233 | } |
---|
234 | |
---|
235 | rule Link-DLL |
---|
236 | { |
---|
237 | gRUN_LD_LIBRARY_PATH($(<)) += $(gLOCATE($(<[1]))) $(gTOOLSET_LIB_PATH) ; |
---|
238 | if $(UNIX) |
---|
239 | { |
---|
240 | LINK_LIBPATH on $(<) = [ join $(gRUN_LD_LIBRARY_PATH($(<))) : $(SPLITPATH) ] ; |
---|
241 | } |
---|
242 | |
---|
243 | return [ .do-link $(<) : $(>) : DLL ] ; |
---|
244 | } |
---|
245 | |
---|
246 | # store the shell's PATH again, just in case someone uses PATH. |
---|
247 | # This also allows the user to customize the base path for running built |
---|
248 | # products from the command-line |
---|
249 | RUN_PATH ?= $(PATH) ; |
---|
250 | if $(UNIX) |
---|
251 | { |
---|
252 | LINK_LIBPATH ?= $($(gSHELL_LIBPATH)) ; |
---|
253 | gAPPEND_LD_LIBRARY_PATH = ":$"$(gSHELL_LIBPATH) ; |
---|
254 | gAPPEND_PATH = ":$"PATH ; |
---|
255 | } |
---|
256 | if $(NT) |
---|
257 | { |
---|
258 | # Try some other likely spellings |
---|
259 | RUN_PATH ?= $(Path) ; |
---|
260 | RUN_PATH ?= $(path) ; |
---|
261 | gAPPEND_LD_LIBRARY_PATH = ";%LD_LIBRARY_PATH%" ; |
---|
262 | gAPPEND_PATH = ;\"%PATH%\" ; |
---|
263 | } |
---|
264 | |
---|
265 | # Now set this, just in case someone tries to use it. |
---|
266 | PATH = $(RUN_PATH) ; |
---|
267 | if $(UNIX) |
---|
268 | { |
---|
269 | $(gSHELL_LIBPATH) = $(LINK_LIBPATH) ; |
---|
270 | } |
---|
271 | |
---|
272 | DOLLAR = "$" ; |
---|
273 | |
---|
274 | # bubble variable-name |
---|
275 | # |
---|
276 | # Helper function for sort, below |
---|
277 | # Removes the greatest element from $(variable-name) and returns it. |
---|
278 | rule bubble # |
---|
279 | { |
---|
280 | local result = ; |
---|
281 | local last = $($(<)[1]) ; |
---|
282 | for x in $($(<)[2-]) |
---|
283 | { |
---|
284 | if $(last) <= $(x) |
---|
285 | { |
---|
286 | result += $(last) ; |
---|
287 | last = $(x) ; |
---|
288 | } |
---|
289 | else |
---|
290 | { |
---|
291 | result += $(x) ; |
---|
292 | } |
---|
293 | } |
---|
294 | $(<) = $(result) ; |
---|
295 | return $(last) ; |
---|
296 | } |
---|
297 | |
---|
298 | # sort args |
---|
299 | # |
---|
300 | # return args sorted in lexicographic order. |
---|
301 | rule sort |
---|
302 | { |
---|
303 | local _all = $(<) ; |
---|
304 | local _result = ; |
---|
305 | local _count ; |
---|
306 | for _count in $(<) |
---|
307 | { |
---|
308 | _result = [ bubble _all ] $(_result) ; |
---|
309 | } |
---|
310 | return $(_result) ; |
---|
311 | } |
---|
312 | |
---|
313 | # min args |
---|
314 | # |
---|
315 | # return the lexicographic minimum element of args |
---|
316 | rule min |
---|
317 | { |
---|
318 | local result = ; |
---|
319 | local x ; |
---|
320 | for x in $(<) |
---|
321 | { |
---|
322 | if ! $(result) || ( $(x) < $(result) ) |
---|
323 | { |
---|
324 | result = $(x) ; |
---|
325 | } |
---|
326 | } |
---|
327 | return $(result) ; |
---|
328 | } |
---|
329 | |
---|
330 | # difference listB : listA |
---|
331 | # returns the elements of B that are not in A |
---|
332 | rule difference |
---|
333 | { |
---|
334 | local result = ; |
---|
335 | local element ; |
---|
336 | for element in $(<) |
---|
337 | { |
---|
338 | if ! ( $(element) in $(>) ) |
---|
339 | { |
---|
340 | result += $(element) ; |
---|
341 | } |
---|
342 | } |
---|
343 | return $(result) ; |
---|
344 | } |
---|
345 | |
---|
346 | # replace list : old-value new-value |
---|
347 | # |
---|
348 | # returns list with occurrences of old-value replaced by new-value |
---|
349 | rule replace |
---|
350 | { |
---|
351 | local result = ; |
---|
352 | local x ; |
---|
353 | for x in $(<) |
---|
354 | { |
---|
355 | if $(x) = $(>[1]) |
---|
356 | { |
---|
357 | result += $(>[2]) ; |
---|
358 | } |
---|
359 | else |
---|
360 | { |
---|
361 | result += $(x) ; |
---|
362 | } |
---|
363 | } |
---|
364 | return $(result) ; |
---|
365 | } |
---|
366 | |
---|
367 | # select-ungristed list... |
---|
368 | # |
---|
369 | # Returns the elements of list that have no grist |
---|
370 | rule select-ungristed |
---|
371 | { |
---|
372 | local result x ; |
---|
373 | for x in $(<) |
---|
374 | { |
---|
375 | if ! $(x:G) |
---|
376 | { |
---|
377 | result += $(x) ; |
---|
378 | } |
---|
379 | } |
---|
380 | return $(result) ; |
---|
381 | } |
---|
382 | |
---|
383 | rule select-gristed ( list * ) |
---|
384 | { |
---|
385 | local result ; |
---|
386 | for local x in $(list) |
---|
387 | { |
---|
388 | if $(x:G) |
---|
389 | { |
---|
390 | result += $(x) ; |
---|
391 | } |
---|
392 | } |
---|
393 | return $(result) ; |
---|
394 | } |
---|
395 | |
---|
396 | # Returns grist without "<"/">" for elements matching "<.*>", |
---|
397 | # and ignores other elements. |
---|
398 | rule ungrist ( names * ) |
---|
399 | { |
---|
400 | local result ; |
---|
401 | for local name in $(names) |
---|
402 | { |
---|
403 | local stripped = [ MATCH ^<(.*)>$ : $(name) ] ; |
---|
404 | result += $(stripped) ; |
---|
405 | } |
---|
406 | return $(result) ; |
---|
407 | } |
---|
408 | |
---|
409 | |
---|
410 | # Split a qualified property into 3 elements. |
---|
411 | # |
---|
412 | # Grammar description of qualified-property : |
---|
413 | # [[<toolset>]<variant>]property |
---|
414 | # |
---|
415 | # returns <toolset> <variant> property |
---|
416 | # missing <toolset> or <variant> are treated as <*> |
---|
417 | rule split-qualified-property |
---|
418 | { |
---|
419 | local grist1 = $(<:G) ; |
---|
420 | local ungrist1 = $(<:G=) ; |
---|
421 | local grist2 = $(ungrist1:G) ; |
---|
422 | local ungrist2 = $(ungrist1:G=) ; |
---|
423 | local grist3 = $(ungrist2:G) ; |
---|
424 | local ungrist3 = $(ungrist2:G=) ; |
---|
425 | if $(grist3) |
---|
426 | { |
---|
427 | return $(grist1) $(grist2) $(grist3)$(ungrist3) ; |
---|
428 | } |
---|
429 | else if $(grist2) |
---|
430 | { |
---|
431 | return <*> $(grist1) $(grist2)$(ungrist2) ; |
---|
432 | } |
---|
433 | else |
---|
434 | { |
---|
435 | return <*> <*> $(<) ; |
---|
436 | } |
---|
437 | } |
---|
438 | |
---|
439 | rule unique # list |
---|
440 | { |
---|
441 | local result = ; |
---|
442 | local f ; |
---|
443 | for f in $(<) |
---|
444 | { |
---|
445 | if ! $(f) in $(result) |
---|
446 | { |
---|
447 | result += $(f) ; |
---|
448 | } |
---|
449 | } |
---|
450 | return $(result) ; |
---|
451 | } |
---|
452 | |
---|
453 | # get-properties features : properties |
---|
454 | # |
---|
455 | # Given a list of gristed features and a list of properties, returns the |
---|
456 | # properties matching the given features. |
---|
457 | rule get-properties |
---|
458 | { |
---|
459 | local result = ; |
---|
460 | local property ; |
---|
461 | for property in $(>) |
---|
462 | { |
---|
463 | if $(property:G) in $(<) |
---|
464 | { |
---|
465 | result += $(property) ; |
---|
466 | } |
---|
467 | } |
---|
468 | return $(result) ; |
---|
469 | } |
---|
470 | |
---|
471 | # get-values features : properties |
---|
472 | # |
---|
473 | # Given a list of gristed feature names and a list of properties, returns the |
---|
474 | # value(s) of the given features. |
---|
475 | rule get-values |
---|
476 | { |
---|
477 | local _properties = [ get-properties $(<) : $(>) ] ; |
---|
478 | return $(_properties:G=) ; |
---|
479 | } |
---|
480 | |
---|
481 | rule replace-properties ( property-set * : new-properties * ) |
---|
482 | { |
---|
483 | local result = ; |
---|
484 | for local x in $(property-set) |
---|
485 | { |
---|
486 | if $(x:G) in $(new-properties:G) |
---|
487 | { |
---|
488 | if ! $(x:G) in $(result:G) |
---|
489 | { |
---|
490 | result += [ get-properties $(x:G) : $(new-properties) ] ; |
---|
491 | } |
---|
492 | |
---|
493 | } |
---|
494 | else |
---|
495 | { |
---|
496 | result += $(x) ; |
---|
497 | } |
---|
498 | } |
---|
499 | return $(result) ; |
---|
500 | } |
---|
501 | |
---|
502 | |
---|
503 | # normalize-properties properties |
---|
504 | # |
---|
505 | # Normalizes a set of (possibly qualified) properties by prepending <*> as many |
---|
506 | # times as necessary to ensure that each property has at least 3 gristed elements. |
---|
507 | rule normalize-properties |
---|
508 | { |
---|
509 | local property ; |
---|
510 | local result ; |
---|
511 | for property in $(<) |
---|
512 | { |
---|
513 | switch $(property) |
---|
514 | { |
---|
515 | case <*><*><tag>* : result += $(property) ; |
---|
516 | case <*><tag>* : result += <*>$(property) ; |
---|
517 | case <tag>* : result += <*><*>$(property) ; |
---|
518 | |
---|
519 | case <*><*><*><default>* : result += $(property) ; |
---|
520 | case <*><*><default><*>* : result += <*>$(property) ; |
---|
521 | case <*><*><default>* : result += $(property) ; |
---|
522 | case <*><default><*>* : result += <*><*>$(property) ; |
---|
523 | case <*><default>* : result += <*>$(property) ; |
---|
524 | case <default><*>* : result += <*><*><*>$(property) ; |
---|
525 | case <default>* : result += <*><*>$(property) ; |
---|
526 | |
---|
527 | case <*><*><*><*@*>* : result += $(property) ; |
---|
528 | case <*><*><*@*>* : result += <*>$(property) ; |
---|
529 | case <*><*@*>* : result += <*><*>$(property) ; |
---|
530 | case <*@*>* : result += <*><*><*>$(property) ; |
---|
531 | |
---|
532 | case <*><*><*>* : result += $(property) ; |
---|
533 | case <*><*>* : result += <*>$(property) ; |
---|
534 | case <*>* : result += <*><*>$(property) ; |
---|
535 | case * : result += <*><*><*>$(property) ; |
---|
536 | } |
---|
537 | } |
---|
538 | return $(result) ; |
---|
539 | } |
---|
540 | |
---|
541 | # intersection set1 : set2 |
---|
542 | # |
---|
543 | # Removes from set1 any items which don't appear in set2 and returns the result. |
---|
544 | rule intersection |
---|
545 | { |
---|
546 | local result v ; |
---|
547 | for v in $(<) |
---|
548 | { |
---|
549 | if $(v) in $(>) |
---|
550 | { |
---|
551 | result += $(v) ; |
---|
552 | } |
---|
553 | } |
---|
554 | return $(result) ; |
---|
555 | } |
---|
556 | |
---|
557 | # subset sub : super |
---|
558 | # |
---|
559 | # Returns true iff sub is a subset of super, empty otherwise |
---|
560 | rule is-subset |
---|
561 | { |
---|
562 | if [ intersection $(<) : $(>) ] = $(<) |
---|
563 | { |
---|
564 | return true ; |
---|
565 | } |
---|
566 | } |
---|
567 | |
---|
568 | # distribute-feature <feature>value1[/value2...] |
---|
569 | # |
---|
570 | # Distribute the given feature across the slash-separated set of values, i.e. |
---|
571 | # returns <feature>value1[ <feature>/value2...] |
---|
572 | rule distribute-feature |
---|
573 | { |
---|
574 | local g = $(<:G) ; |
---|
575 | local result = [ split-path $(<:G=) ] ; |
---|
576 | return $(g)$(result) ; |
---|
577 | } |
---|
578 | |
---|
579 | # set-insert variable-name : value... ; |
---|
580 | # |
---|
581 | # Appends the given values to the list designated by variable-name if they are |
---|
582 | # not already present. |
---|
583 | rule set-insert |
---|
584 | { |
---|
585 | local v ; |
---|
586 | for v in $(>) |
---|
587 | { |
---|
588 | if ! ( $(v) in $($(<)) ) |
---|
589 | { |
---|
590 | $(<) += $(v) ; |
---|
591 | } |
---|
592 | } |
---|
593 | } |
---|
594 | |
---|
595 | # equal-sets set1 : set2 |
---|
596 | # |
---|
597 | # Returns true iff set1 contains the same elements as set2. |
---|
598 | # Not sensitive to the same element appearing multiple times |
---|
599 | rule equal-sets |
---|
600 | { |
---|
601 | if ( ! [ difference $(<) : $(>) ] ) && ( ! [ difference $(>) : $(<) ] ) |
---|
602 | { |
---|
603 | return true ; |
---|
604 | } |
---|
605 | } |
---|
606 | |
---|
607 | # feature name : [values...] |
---|
608 | # |
---|
609 | # Declares a feature with the given name, and the given allowed values. |
---|
610 | rule feature |
---|
611 | { |
---|
612 | if $(<) in $(gFEATURES) |
---|
613 | { |
---|
614 | EXIT feature $(<) : $(gFEATURE_VALUES(<$(<)>) redeclared as $(<) : $(>) ; |
---|
615 | } |
---|
616 | gFEATURES += <$(<)> ; |
---|
617 | gUNGRISTED(<$(<)>) = $(<) ; |
---|
618 | gFEATURE_VALUES(<$(<)>) = $(>) ; |
---|
619 | } |
---|
620 | |
---|
621 | rule free-feature |
---|
622 | { |
---|
623 | feature $(<) : $(>) ; |
---|
624 | gFREE_FEATURES += <$(<)> ; |
---|
625 | if $(>) |
---|
626 | { |
---|
627 | gSINGLE_VALUED_FREE_FEATURES += <$(<)> ; |
---|
628 | } |
---|
629 | } |
---|
630 | |
---|
631 | rule path-feature |
---|
632 | { |
---|
633 | free-feature $(<) : $(>) ; |
---|
634 | gPATH_FEATURES += <$(<)> ; |
---|
635 | } |
---|
636 | |
---|
637 | rule dependency-feature |
---|
638 | { |
---|
639 | path-feature $(<) : $(>) ; |
---|
640 | gDEPENDENCY_FEATURES += <$(<)> ; |
---|
641 | } |
---|
642 | |
---|
643 | # feature-default <feature>... |
---|
644 | # |
---|
645 | # return the default properties corresponding to the given feature(s) |
---|
646 | rule feature-default |
---|
647 | { |
---|
648 | local result f ; |
---|
649 | for f in $(<) |
---|
650 | { |
---|
651 | result += $(f)$(gFEATURE_VALUES($(f))[1]) ; |
---|
652 | } |
---|
653 | return $(result) ; |
---|
654 | } |
---|
655 | |
---|
656 | # flags tools-name variable-name condition [: value(s)] |
---|
657 | # |
---|
658 | # Declare command-line settings for a given toolset. |
---|
659 | # toolset: the name of the toolset |
---|
660 | # variable-name: the name of a global variable which can be used to carry |
---|
661 | # information to a command-line |
---|
662 | # condition: One of the following: |
---|
663 | # 1. zero or more property-sets of the form: |
---|
664 | # <feature>value[/<feature>value...] |
---|
665 | # 2. one or more <feature>[/<feature>...] |
---|
666 | # |
---|
667 | # This rule appends to the specified variable, depending on a target's build |
---|
668 | # configuration and the form of condition. |
---|
669 | # |
---|
670 | # 1. if any specified property-set is a subset of the target's build properties or if |
---|
671 | # condition is empty, the values specified in $(3) will be appended once to |
---|
672 | # /variable-name/. |
---|
673 | # |
---|
674 | # 2. The value of each specified feature that participates in the target's |
---|
675 | # build properaties is appended to /variable-name/. |
---|
676 | # |
---|
677 | # The variable will be set "on" the target so it may be used in its build actions. |
---|
678 | rule flags |
---|
679 | { |
---|
680 | local toolset = $(gCURRENT_TOOLSET) ; |
---|
681 | local variable = $(<[2]) ; |
---|
682 | local condition = $(<[3-]) ; |
---|
683 | |
---|
684 | # record the names of all variables used so they can be set on targets |
---|
685 | if ! ( $(variable) in $(gTARGET_VARIABLES) ) |
---|
686 | { |
---|
687 | gTARGET_VARIABLES += $(variable) ; |
---|
688 | $(variable) = ; |
---|
689 | } |
---|
690 | |
---|
691 | local found = ; |
---|
692 | local x ; |
---|
693 | for x in $(condition) |
---|
694 | { |
---|
695 | x = [ split-path $(x) ] ; |
---|
696 | |
---|
697 | # Add each feature to the set of features relevant to the toolset |
---|
698 | gRELEVANT_FEATURES($(toolset)) += $(x:G) ; |
---|
699 | |
---|
700 | # is it a property set? |
---|
701 | if $(x:G=) |
---|
702 | { |
---|
703 | # if this property_set is a subset of the current build-properties |
---|
704 | if ( ! $(found) ) && [ is-subset $(x) : $(gBUILD_PROPERTIES) ] |
---|
705 | { |
---|
706 | found = true ; |
---|
707 | $(variable) += $(>) ; |
---|
708 | } |
---|
709 | } |
---|
710 | else |
---|
711 | { |
---|
712 | $(variable) += [ get-values $(x) : $(gBUILD_PROPERTIES) ] ; |
---|
713 | if $(x:G) in $(gDEPENDENCY_FEATURES) |
---|
714 | { |
---|
715 | gDEPENDENCY_VARIABLES($(toolset)) += $(variable) ; |
---|
716 | } |
---|
717 | } |
---|
718 | } |
---|
719 | if ! $(condition) |
---|
720 | { |
---|
721 | $(variable) += $(>) ; |
---|
722 | } |
---|
723 | } |
---|
724 | |
---|
725 | # include-tools toolset |
---|
726 | # |
---|
727 | # Unconditionally process the specification file for the given toolset. It is |
---|
728 | # necessary to do this for each target built with that toolset, since the |
---|
729 | # toolset will invoke the flags rule to set global variables based on the build |
---|
730 | # properties of the target. |
---|
731 | rule include-tools |
---|
732 | { |
---|
733 | if ! $(gIN_INCLUDE_TOOLS) |
---|
734 | { |
---|
735 | gCURRENT_TOOLSET = $(<) ; |
---|
736 | gRELEVANT_FEATURES($(<)) = ; # clear relevant feature set |
---|
737 | gDEPENDENCY_VARIABLES($(<)) = ; |
---|
738 | |
---|
739 | # clear any lingering target variables that may have been declared |
---|
740 | $(gTARGET_VARIABLES) = ; |
---|
741 | gTARGET_VARIABLES = NEEDLIBS NEEDIMPS ; # start over from the beginning |
---|
742 | gTOOLSET_LIB_PATH = ; |
---|
743 | } |
---|
744 | |
---|
745 | { |
---|
746 | local gIN_INCLUDE_TOOLS = true ; |
---|
747 | SEARCH on <jam-module>$(<)-tools.jam = $(BOOST_BUILD_PATH) ; |
---|
748 | include <jam-module>$(<)-tools.jam ; |
---|
749 | } |
---|
750 | |
---|
751 | # Always maintain the list of relevant features as unique |
---|
752 | if ! $(gIN_INCLUDE_TOOLS) |
---|
753 | { |
---|
754 | gRELEVANT_FEATURES($(<)) = [ |
---|
755 | unique $(gRELEVANT_FEATURES($(<))) |
---|
756 | $(gALWAYS_RELEVANT) |
---|
757 | ] ; |
---|
758 | } |
---|
759 | |
---|
760 | gINCLUDED(<jam-module>$(<)-tools.jam) = TRUE ; |
---|
761 | } |
---|
762 | |
---|
763 | # extends-toolset toolset |
---|
764 | # |
---|
765 | # Used in a toolset definition file; Declares that the toolset currently being |
---|
766 | # defined is an extension of the given toolset. |
---|
767 | rule extends-toolset |
---|
768 | { |
---|
769 | include-tools $(<) ; |
---|
770 | } |
---|
771 | |
---|
772 | # relevant-features toolset |
---|
773 | # |
---|
774 | # Returns the set of unique features relevant to the given toolset; includes the |
---|
775 | # toolset description file as a side-effect if necessary. |
---|
776 | rule relevant-features # name |
---|
777 | { |
---|
778 | if ! $(gRELEVANT_FEATURES($(<))) |
---|
779 | { |
---|
780 | include-tools $(<) ; |
---|
781 | } |
---|
782 | return $(gRELEVANT_FEATURES($(<))) ; |
---|
783 | } |
---|
784 | |
---|
785 | # variant name [ : parents... ] : [<toolset>]<feature>value... |
---|
786 | # |
---|
787 | # Declare a build variant, whose configuration is given by the given (optionally |
---|
788 | # toolset-qualified) properties. |
---|
789 | rule variant ( name : parents-or-properties * : tool-properties * ) |
---|
790 | { |
---|
791 | gALL_VARIANTS += $(name) ; |
---|
792 | local parents ; |
---|
793 | if ! $(tool-properties) |
---|
794 | { |
---|
795 | if $(parents-or-properties[1]:G) |
---|
796 | { |
---|
797 | tool-properties = $(parents-or-properties) ; |
---|
798 | } |
---|
799 | else |
---|
800 | { |
---|
801 | parents = $(parents-or-properties) ; |
---|
802 | } |
---|
803 | } |
---|
804 | else |
---|
805 | { |
---|
806 | parents = $(parents-or-properties) ; |
---|
807 | } |
---|
808 | local toolset ; |
---|
809 | for toolset in $(TOOLS) |
---|
810 | { |
---|
811 | # We hijack select-properties to do our dirty work here. |
---|
812 | # Because properties in a variant declaration are only qualified with |
---|
813 | # toolset and not variant, we specify the toolset where |
---|
814 | # select-properties expects a variant name. The first toolset parameter |
---|
815 | # is necessary to get the relevant-features correctly set. We supply |
---|
816 | # the variant name as the target name, so that error messages will look |
---|
817 | # coherent. |
---|
818 | local name-properties |
---|
819 | = [ select-properties $(toolset) $(toolset) $(name) : $(tool-properties) ] ; |
---|
820 | if $(parents) |
---|
821 | { |
---|
822 | local parent ; |
---|
823 | for parent in $(parents) |
---|
824 | { |
---|
825 | local parent-properties |
---|
826 | = $(gBASE_PROPERTIES($(toolset),$(parent))) ; |
---|
827 | local inherited-features |
---|
828 | = [ unique |
---|
829 | [ difference $(parent-properties:G) : $(name-properties:G) ] |
---|
830 | $(gFREE_FEATURES) |
---|
831 | $(gPATH_FEATURES) |
---|
832 | $(gDEPENDENCY_FEATURES ] ; |
---|
833 | local inherited-properties |
---|
834 | = [ get-properties $(inherited-features) : $(parent-properties) ] ; |
---|
835 | name-properties |
---|
836 | += $(inherited-properties) ; |
---|
837 | } |
---|
838 | } |
---|
839 | gBASE_PROPERTIES($(toolset),$(name)) = [ sort $(name-properties) ] ; |
---|
840 | } |
---|
841 | } |
---|
842 | |
---|
843 | # select-properties toolset variant target : qualified-properties... |
---|
844 | # |
---|
845 | # Returns |
---|
846 | rule select-properties ( toolset variant target ? : qualified-properties * ) |
---|
847 | { |
---|
848 | local relevant_features = [ relevant-features $(toolset) ] ; |
---|
849 | local normalized = [ normalize-properties $(>) ] ; |
---|
850 | |
---|
851 | # Classify properties by the specificity of their qualification. |
---|
852 | # First, grab those that apply to this toolset, or all toolsets |
---|
853 | local this_toolset = [ get-values <$(toolset)> : $(normalized) ] ; |
---|
854 | local all_toolsets = [ get-values <*> : $(normalized) ] ; |
---|
855 | |
---|
856 | local 0-stars = [ get-values <$(variant)> : $(this_toolset) ] ; |
---|
857 | local 1-stars = [ get-values <*> : $(this_toolset) ] [ get-values <$(variant)> : $(all_toolsets) ] ; |
---|
858 | local 2-stars = [ get-values <*> : $(all_toolsets) ] ; |
---|
859 | |
---|
860 | # Select feature names from the features relevant to the toolset. |
---|
861 | local features = [ intersection $(relevant_features) |
---|
862 | : $(0-stars:G) $(1-stars:G) $(2-stars:G) ] ; |
---|
863 | |
---|
864 | local result f ; |
---|
865 | for f in $(features) |
---|
866 | { |
---|
867 | local is_free = [ intersection $(f) : $(gFREE_FEATURES) ] ; |
---|
868 | |
---|
869 | # Go through the $(n-stars) lists from most- to least- specific; |
---|
870 | # collect the best set of values of a simple feature, and /all/ |
---|
871 | # values of a free feature. |
---|
872 | local r n ; |
---|
873 | for n in 0 1 2 |
---|
874 | { |
---|
875 | if ! $(r) || $(is_free) |
---|
876 | { |
---|
877 | r += [ get-values $(f) : $($(n)-stars) ] ; |
---|
878 | } |
---|
879 | } |
---|
880 | |
---|
881 | r = [ unique $(r) ] ; |
---|
882 | if $(r[2]) && ! $(is_free) # Check for conflicting simple-feature requests |
---|
883 | { |
---|
884 | EXIT "Error: Ambiguous properties requested for" |
---|
885 | $(target) <$(toolset)><$(variant)> ":" $(f)$(r) ; |
---|
886 | } |
---|
887 | result += $(f)$(r) ; |
---|
888 | } |
---|
889 | return $(result) ; |
---|
890 | } |
---|
891 | # get toolset features |
---|
892 | SEARCH on <jam-module>features.jam = $(BOOST_BUILD_PATH) ; |
---|
893 | include <jam-module>features.jam ; |
---|
894 | |
---|
895 | # ungrist-properties properties... |
---|
896 | # |
---|
897 | # Transforms a list of properties of the form: |
---|
898 | # <feature1>value1 [<feature2>value2... ] |
---|
899 | # into a list of the form: |
---|
900 | # feature1-value1 feature2-value2 |
---|
901 | # suitable for use as directory path elements |
---|
902 | # |
---|
903 | rule ungrist-properties |
---|
904 | { |
---|
905 | local property ; |
---|
906 | local result = ; |
---|
907 | for property in $(<) |
---|
908 | { |
---|
909 | result += $(gUNGRISTED($(property:G)))-$(property:G=) ; |
---|
910 | } |
---|
911 | return $(result) ; |
---|
912 | } |
---|
913 | |
---|
914 | # set-target-variables target |
---|
915 | # |
---|
916 | # attach global build tool settings to the given file-target, so that they can be |
---|
917 | # used in build actions. |
---|
918 | rule set-target-variables ( targets * ) |
---|
919 | { |
---|
920 | local s ; |
---|
921 | for s in $(gTARGET_VARIABLES) |
---|
922 | { |
---|
923 | $(s) on $(targets) = $($(s)) ; |
---|
924 | |
---|
925 | # set up dependencies if the target is a "top-level" target |
---|
926 | if ( $(s) in $(gDEPENDENCY_VARIABLES($(gCURRENT_TOOLSET))) ) && $(gTARGET_TYPE($(<))) |
---|
927 | { |
---|
928 | DEPENDS $(targets) : $($(s)) ; |
---|
929 | } |
---|
930 | } |
---|
931 | local libpath = [ get-properties <library-path> : $(gBUILD_PROPERTIES) ] ; |
---|
932 | gRUN_PATH($(targets)) += $(libpath:G=) ; |
---|
933 | gRUN_LD_LIBRARY_PATH($(targets)) += $(libpath:G=) ; |
---|
934 | } |
---|
935 | |
---|
936 | # For path properties, add a relative path prefix to the value as |
---|
937 | # necessary to locate the path relative to the given subproject |
---|
938 | # directory. |
---|
939 | rule fixup-path-properties ( properties * : subproject-directory ? ) |
---|
940 | { |
---|
941 | local result ; |
---|
942 | |
---|
943 | for local p in $(properties) |
---|
944 | { |
---|
945 | if $(p:G) in $(gPATH_FEATURES) |
---|
946 | { |
---|
947 | # If the path property value is project-relative, re-root |
---|
948 | # it appropriately for that project |
---|
949 | local parse-project = [ MATCH ^@([^/$(SLASH)]+)[/$(SLASH)]?(.*) : $(p:G=) ] ; |
---|
950 | if $(parse-project) |
---|
951 | { |
---|
952 | local project = $(parse-project[1]) ; |
---|
953 | local subproject = $(parse-project[2]) ; |
---|
954 | p = [ root-paths $(subproject:G=$(p:G)) : $(gPROJECT($(project))) ] ; |
---|
955 | } |
---|
956 | else if $(subproject-directory) # re-root it relative to this directory |
---|
957 | { |
---|
958 | p = [ root-paths $(p) : $(subproject-directory) ] ; |
---|
959 | } |
---|
960 | } |
---|
961 | |
---|
962 | result += $(p) ; |
---|
963 | } |
---|
964 | |
---|
965 | return $(result) ; |
---|
966 | } |
---|
967 | |
---|
968 | # remove-incompatible-builds requirements... : build-request... : target-name |
---|
969 | # |
---|
970 | # If any element of requirements has the same grist but a different ungristed |
---|
971 | # part as any element of build-request, exits with an error report about target-name |
---|
972 | rule remove-incompatible-builds ( requirements * : build-request * : target-name + ) |
---|
973 | { |
---|
974 | local all-properties = [ unique $(<) $(>) ] ; |
---|
975 | local all-features = $(all-properties:G) ; |
---|
976 | local unique-features = [ unique $(all-features) ] ; |
---|
977 | if $(all-features) != $(unique-features) |
---|
978 | { |
---|
979 | local result ; |
---|
980 | local skip ; |
---|
981 | for local p in $(build-request) |
---|
982 | { |
---|
983 | # if a feature of the build request is also in the |
---|
984 | # requirements, but with differing value(s) |
---|
985 | if ( $(p:G) in $(requirements:G) ) |
---|
986 | && ! ( $(p) in $(requirements) ) |
---|
987 | { |
---|
988 | # decide what to do. |
---|
989 | local value = [ get-values $(p:G) : $(requirements) ] ; |
---|
990 | if $(value[2]) |
---|
991 | { |
---|
992 | EXIT Unexpectedly found multiple build requests |
---|
993 | for feature $(p:G) with values $(values) ; |
---|
994 | } |
---|
995 | |
---|
996 | local requested = [ split-path $(p:G=) ] ; |
---|
997 | if $(requested[2]) |
---|
998 | { |
---|
999 | local skipped = [ difference $(requested) : $(value) ] ; |
---|
1000 | |
---|
1001 | if ! $(gNOWARN_INCOMPATIBLE_BUILDS) |
---|
1002 | { |
---|
1003 | ECHO $(target-name) requires $(p:G)$(value), |
---|
1004 | skipping requested build configuration(s) $(p:G)$(skipped). ; |
---|
1005 | } |
---|
1006 | |
---|
1007 | result += $(p:G)$(value) ; |
---|
1008 | } |
---|
1009 | else |
---|
1010 | { |
---|
1011 | if ! $(gNOWARN_INCOMPATIBLE_BUILDS) |
---|
1012 | { |
---|
1013 | ECHO skipping $(target-name) due to incompatible |
---|
1014 | build requirements $(p:G)$(value). ; |
---|
1015 | } |
---|
1016 | skip = true ; |
---|
1017 | } |
---|
1018 | } |
---|
1019 | else |
---|
1020 | { |
---|
1021 | result += $(p) ; |
---|
1022 | } |
---|
1023 | } |
---|
1024 | |
---|
1025 | if $(skip) |
---|
1026 | { |
---|
1027 | build-request = SKIP ; |
---|
1028 | } |
---|
1029 | else |
---|
1030 | { |
---|
1031 | build-request = $(result) ; |
---|
1032 | } |
---|
1033 | } |
---|
1034 | return $(build-request) ; |
---|
1035 | } |
---|
1036 | |
---|
1037 | # multiply-property-sets [<feature>value1[/value2...] ]... |
---|
1038 | # |
---|
1039 | # Expands a set of (possibly multi-valued) properties into all the combinations |
---|
1040 | # that include every feature in the set. Each combination is given as a path, |
---|
1041 | # with the slash separating the properties, sorted in feature order. |
---|
1042 | rule multiply-property-sets |
---|
1043 | { |
---|
1044 | local result p ; |
---|
1045 | for p in [ sort $(<) ] |
---|
1046 | { |
---|
1047 | # expand any multi-valued simple features from the default build |
---|
1048 | local multiple = [ distribute-feature $(p) ] ; |
---|
1049 | |
---|
1050 | # concatenation produces a product, so the tree branches for each |
---|
1051 | # multi-valued simple feature. |
---|
1052 | result = $(result)/$(multiple) ; |
---|
1053 | result ?= $(multiple) ; # this trick allows us to get started |
---|
1054 | } |
---|
1055 | return $(result) ; |
---|
1056 | } |
---|
1057 | |
---|
1058 | # Return a list consisting of all the elements of properties which |
---|
1059 | # aren't the defaults for their features. |
---|
1060 | rule remove-default-properties ( properties * ) |
---|
1061 | { |
---|
1062 | return [ difference $(properties) : [ feature-default $(properties:G) ] ] ; |
---|
1063 | } |
---|
1064 | |
---|
1065 | # make-path-property-sets base-path : common-properties : property-sets |
---|
1066 | # |
---|
1067 | # Returns a list of paths where the initial ungristed part of each element is a |
---|
1068 | # relative path to a subvariant directory from a target's build root and the |
---|
1069 | # rest of the element is a slash-separated property set describing the |
---|
1070 | # properties of the target to be built. |
---|
1071 | # |
---|
1072 | # Each path returned is base-path extended by one of the ungristed property-sets |
---|
1073 | # (or just the base-path if no property-sets are supplied). Each property set |
---|
1074 | # returned is formed by extending common-properties with one of the property-sets. |
---|
1075 | # |
---|
1076 | # For example, |
---|
1077 | # |
---|
1078 | # make-path-property-sets gcc/release : <p1>v1 : <p2>v2/<p3>v3 |
---|
1079 | # |
---|
1080 | # returns this single-element list: |
---|
1081 | # |
---|
1082 | # gcc/release/p2-v2/p3-v3/<p1>v1/<p2>v2/<p3>v3 |
---|
1083 | # |<-- subvariant path -->|<-- property-set -->| |
---|
1084 | rule make-path-property-sets ( base-path : common-properties * : property-sets * ) |
---|
1085 | { |
---|
1086 | local result ; |
---|
1087 | local s ; |
---|
1088 | for s in $(property-sets) |
---|
1089 | { |
---|
1090 | local x = |
---|
1091 | # directory components |
---|
1092 | $(base-path) |
---|
1093 | [ ungrist-properties |
---|
1094 | [ remove-default-properties [ split-path $(s) ] ] |
---|
1095 | ] |
---|
1096 | # properties |
---|
1097 | $(common-properties) $(s) |
---|
1098 | ; |
---|
1099 | |
---|
1100 | result += $(x:J=$(SLASH)) ; |
---|
1101 | } |
---|
1102 | |
---|
1103 | # if there were no overrides, just add the base variant and properties |
---|
1104 | if ! $(result) |
---|
1105 | { |
---|
1106 | result = [ join $(base-path) $(common-properties) : $(SLASH) ] ; |
---|
1107 | } |
---|
1108 | return $(result) ; |
---|
1109 | } |
---|
1110 | |
---|
1111 | # segregate-overrides override-var base-var |
---|
1112 | # |
---|
1113 | # removes elements of $(base-var) from $(override-var), and removes elements |
---|
1114 | # whose grist is in $(override-var:G) from $(base-var). |
---|
1115 | rule segregate-overrides |
---|
1116 | { |
---|
1117 | $(<) = [ difference $($(<)) : $($(>)) ] ; |
---|
1118 | |
---|
1119 | # Which features, and thus properties, of the base variant are we keeping? |
---|
1120 | local kept-features = [ difference $($(>):G) : $($(<):G) ] ; |
---|
1121 | $(>) = [ get-properties $(kept-features) : $($(>)) ] ; |
---|
1122 | } |
---|
1123 | |
---|
1124 | # If any single-valued free-feature appears more than once in free-property..., |
---|
1125 | # exit with an appropriate error message. |
---|
1126 | rule report-free-property-conflicts ( free-property * : target + ) |
---|
1127 | { |
---|
1128 | local p = [ get-properties $(gSINGLE_VALUED_FREE_FEATURES) : $(free-property) ] ; |
---|
1129 | local f = [ unique $(p:G) ] ; |
---|
1130 | if $(p:G) != $(f) |
---|
1131 | { |
---|
1132 | EXIT $(>): multiple values for single-valued free feature(s) |
---|
1133 | [ difference $(p:G) $(f) ] requested ; |
---|
1134 | } |
---|
1135 | } |
---|
1136 | |
---|
1137 | # Returns a list of path-property-sets (see make-path-property-sets above) for |
---|
1138 | # all build configurations based on the given toolset, requirements, and |
---|
1139 | # build-request. Target-name is just used for error reporting. |
---|
1140 | rule expand-build-request ( toolset variant target : raw-requirements * : raw-build-request * ) |
---|
1141 | { |
---|
1142 | # grab the requirements and BUILD-request relevant to this toolset and variant |
---|
1143 | local requirements = [ select-properties $(toolset) $(variant) : $(raw-requirements) ] ; |
---|
1144 | local build-request = [ select-properties $(toolset) $(variant) : $(raw-build-request) ] ; |
---|
1145 | |
---|
1146 | # Separate the free features (e.g. <define>, <undef>, <include>) from the others |
---|
1147 | local free-properties = [ segregate-free-properties requirements build-request ] ; |
---|
1148 | |
---|
1149 | # Check for conflicts |
---|
1150 | report-free-property-conflicts $(free-properties) : $(target) ; |
---|
1151 | build-request = [ remove-incompatible-builds $(requirements) |
---|
1152 | : $(build-request) : $(target) ] ; |
---|
1153 | |
---|
1154 | if $(build-request) != SKIP |
---|
1155 | { |
---|
1156 | # Get the base variant for the toolset. Includes free features |
---|
1157 | local base-properties = $(gBASE_PROPERTIES($(toolset),$(variant))) ; |
---|
1158 | |
---|
1159 | # Which properties will override settings in the base variant? |
---|
1160 | local override-properties = [ unique $(requirements) $(build-request) ] ; |
---|
1161 | segregate-overrides override-properties : base-properties ; |
---|
1162 | |
---|
1163 | # Which features will pick up a default value because they are not in |
---|
1164 | # the base variant or in the overrides? |
---|
1165 | local relevant-features = [ relevant-features $(toolset) ] ; |
---|
1166 | local override-free-features = [ intersection $(gSINGLE_VALUED_FREE_FEATURES) |
---|
1167 | : $(free-properties:G) ] ; |
---|
1168 | local defaulted-features = [ difference $(relevant-features) |
---|
1169 | : $(override-properties:G) $(base-properties:G) |
---|
1170 | $(override-free-features) |
---|
1171 | ] ; |
---|
1172 | |
---|
1173 | local defaulted-properties = [ feature-default $(defaulted-features) ] ; |
---|
1174 | |
---|
1175 | # VP: defaulted-properties have the form <feature>value and there's 1 value. |
---|
1176 | # Hence, each element of defaulted-properties will be part of each |
---|
1177 | # component of override-sets and will be a part of each property-set |
---|
1178 | # returned. By segregating them, the result is changed in only one |
---|
1179 | # way: free properties does not show up in target path. |
---|
1180 | local defaulted-free-properties = [ segregate-free-properties defaulted-properties ] ; |
---|
1181 | |
---|
1182 | # |
---|
1183 | # Allow <default> properties and rules to take effect. |
---|
1184 | # |
---|
1185 | local default-requirements = [ get-values <default> : $(free-properties) ] ; |
---|
1186 | |
---|
1187 | defaulted-properties = [ replace-properties $(defaulted-properties) |
---|
1188 | : [ select-gristed $(default-requirements) ] ] ; |
---|
1189 | |
---|
1190 | local non-defaults = $(requirements) $(build-request) $(free-properties) ; |
---|
1191 | |
---|
1192 | for local r in [ select-ungristed $(default-requirements) ] |
---|
1193 | { |
---|
1194 | local x = [ $(r) $(toolset) $(variant) : $(non-defaults) ] ; |
---|
1195 | # ECHO $(r) yields $(x) ; |
---|
1196 | # ECHO defaulted-properties= $(defaulted-properties) ; |
---|
1197 | defaulted-properties = [ |
---|
1198 | replace-properties $(defaulted-properties) : $(x) ] ; |
---|
1199 | } |
---|
1200 | |
---|
1201 | # In case any defaults should conflict with the requirements, |
---|
1202 | # force them to match up. |
---|
1203 | defaulted-properties = [ replace-properties $(defaulted-properties) : $(requirements) ] ; |
---|
1204 | |
---|
1205 | # form override property sets of the form (property1[/property2...] )+, |
---|
1206 | # sorted in feature order. These represent the properties of subvariants |
---|
1207 | # that differ from the base variant |
---|
1208 | local override-sets |
---|
1209 | = [ multiply-property-sets $(override-properties) $(defaulted-properties) ] ; |
---|
1210 | |
---|
1211 | # return path-property-sets corresponding to each (sub)variant build |
---|
1212 | # described. |
---|
1213 | return [ make-path-property-sets |
---|
1214 | $(toolset)$(SLASH)$(variant) |
---|
1215 | : [ fixup-path-properties |
---|
1216 | $(base-properties) |
---|
1217 | $(free-properties) |
---|
1218 | $(defaulted-free-properties) |
---|
1219 | : $(RELATIVE_SUBDIR) |
---|
1220 | ] |
---|
1221 | : $(override-sets) |
---|
1222 | ] ; |
---|
1223 | } |
---|
1224 | } |
---|
1225 | |
---|
1226 | # split-path-at-grist path |
---|
1227 | # |
---|
1228 | # Breaks path at each $(SLASH) that is followed by grist. This can be used to |
---|
1229 | # break apart property sets, particularly where the <include> feature is used, |
---|
1230 | # since its value is typically a path. |
---|
1231 | rule split-path-at-grist |
---|
1232 | { |
---|
1233 | local full-split = [ split-path $(<) ] ; |
---|
1234 | local last ; |
---|
1235 | local result x ; |
---|
1236 | for x in $(full-split) |
---|
1237 | { |
---|
1238 | if $(x:G) |
---|
1239 | { |
---|
1240 | result += $(last) ; |
---|
1241 | last = $(x) ; |
---|
1242 | } |
---|
1243 | else |
---|
1244 | { |
---|
1245 | last = $(last)$(SLASH)$(x) ; |
---|
1246 | last ?= $(x) ; |
---|
1247 | } |
---|
1248 | } |
---|
1249 | return $(result) $(last) ; |
---|
1250 | } |
---|
1251 | |
---|
1252 | # |
---|
1253 | # GIVEN: |
---|
1254 | # |
---|
1255 | # A set of dependency sources with grist to indicate the types |
---|
1256 | # (<dll>*, <lib>*, etc) |
---|
1257 | # |
---|
1258 | # RESULT: |
---|
1259 | # |
---|
1260 | # Will use the type, basename, and SUF*/PRE* to expand the name |
---|
1261 | # of the sources to their fully specific target name. |
---|
1262 | # |
---|
1263 | # EXAMPLE: |
---|
1264 | # |
---|
1265 | # [ expand-source-names <lib>test <dll>test <exe>test README.txt <pyd>test ] |
---|
1266 | # |
---|
1267 | # RETURNS: |
---|
1268 | # |
---|
1269 | # <lib>libtest.a <dll>libtest.so <exe>test.app README.TXT <pyd>test.so |
---|
1270 | # |
---|
1271 | rule expand-source-names ( sources * ) |
---|
1272 | { |
---|
1273 | local x-sources = ; |
---|
1274 | for local source in $(sources) |
---|
1275 | { |
---|
1276 | local grist = [ ungrist $(source:G) ] ; |
---|
1277 | local type = $(gTARGET_TYPE_ID($(grist))) ; |
---|
1278 | if $(type) |
---|
1279 | { |
---|
1280 | local p = "" ; if $(source:B=:S=:G=) { p = "/" ; } |
---|
1281 | local prefix = "" ; |
---|
1282 | local suffix = "" ; |
---|
1283 | if $(PRE$(type)[1]) { prefix = $(PRE$(type)[1]) ; } |
---|
1284 | if $(SUF$(type)[1]) { suffix = $(SUF$(type)[1]) ; } |
---|
1285 | x-sources += $(source:B=:S=)$(p)$(prefix)$(source:B:S=)$(suffix) ; |
---|
1286 | } |
---|
1287 | else |
---|
1288 | { |
---|
1289 | x-sources += $(source) ; |
---|
1290 | } |
---|
1291 | } |
---|
1292 | return $(x-sources) ; |
---|
1293 | } |
---|
1294 | |
---|
1295 | # |
---|
1296 | # GIVEN: |
---|
1297 | # |
---|
1298 | # A set of targets and a single target type for all the targets |
---|
1299 | # (DLL, LIB, etc.) |
---|
1300 | # |
---|
1301 | # RESULT: |
---|
1302 | # |
---|
1303 | # Will use the type, basename, and SUF*/PRE* to expand the name |
---|
1304 | # of the targets to their fully specific target name. |
---|
1305 | # |
---|
1306 | # EXAMPLE: |
---|
1307 | # |
---|
1308 | # [ expand-targets-names foo bar : DLL ] |
---|
1309 | # |
---|
1310 | # RETURNS: |
---|
1311 | # |
---|
1312 | # libfoo.a libbar.so |
---|
1313 | # |
---|
1314 | rule expand-target-names ( targets + : target-type ) |
---|
1315 | { |
---|
1316 | local x-targets = ; |
---|
1317 | for local target in $(targets) |
---|
1318 | { |
---|
1319 | local prefix = "" ; |
---|
1320 | local suffix = "" ; |
---|
1321 | if $(PRE$(target-type)[1]) { prefix = $(PRE$(target-type)[1]) ; } |
---|
1322 | if $(SUF$(target-type)[1]) { suffix = $(SUF$(target-type)[1]) ; } |
---|
1323 | x-targets += $(prefix)$(target)$(suffix) ; |
---|
1324 | } |
---|
1325 | return $(x-targets) ; |
---|
1326 | } |
---|
1327 | |
---|
1328 | # declare-local-target name : sources : requirements : local-BUILD : target-type |
---|
1329 | # |
---|
1330 | # declares a subproject-local target of the given name and target-type. This is |
---|
1331 | # all top-level rules which declare targets should eventually go through here. |
---|
1332 | # |
---|
1333 | # RETURNS: the a list of target names for the files built by the target. |
---|
1334 | rule declare-local-target ( target : sources * : requirements * : default-build * : target-type ) |
---|
1335 | { |
---|
1336 | # We expand out the name of the target |
---|
1337 | local x-target = [ expand-target-names $(target) : $(target-type) ] ; |
---|
1338 | |
---|
1339 | # We add SOURCE_GRIST the base target name here because we're referring the |
---|
1340 | # abstract target which generates all of the actual builds. We need a way to |
---|
1341 | # distinguish targets of the same name from different subprojects. |
---|
1342 | local target-id = [ FGristFiles $(x-target) ] ; |
---|
1343 | |
---|
1344 | if ! $(target-type) |
---|
1345 | { |
---|
1346 | EXIT No target type given for "$(x-target)" ; |
---|
1347 | } |
---|
1348 | |
---|
1349 | # Define the specifications of the target. |
---|
1350 | gTARGET_NAME($(target-id)) = $(target) ; |
---|
1351 | |
---|
1352 | # Declare the basic target. |
---|
1353 | declare-basic-target $(target-id) : $(sources) : $(requirements) : $(default-build) : $(target-type) ; |
---|
1354 | |
---|
1355 | # Generate build instructions, but only if the target has a generator. |
---|
1356 | # |
---|
1357 | if $(gGENERATOR_FUNCTION($(gTARGET_TYPE($(target-id))))) |
---|
1358 | { |
---|
1359 | # Supress the regular build of this target |
---|
1360 | local suppress = [ get-values <suppress> : $(default-build) ] ; |
---|
1361 | local gSUPPRESS_FAKE_TARGETS = $(suppress[1]) ; |
---|
1362 | |
---|
1363 | declare-fake-targets $(target) : $(target-id) ; |
---|
1364 | |
---|
1365 | # Just gather information if we are including a library's Jamfile for a |
---|
1366 | # dependent target. Don't generate build instructions here. |
---|
1367 | if ! $(gIN_LIB_INCLUDE) |
---|
1368 | { |
---|
1369 | main-target $(target-id) : $(gTARGET_DEFAULT_BUILD($(target-id))) ; |
---|
1370 | } |
---|
1371 | } |
---|
1372 | |
---|
1373 | return $(gTARGET_FILES($(target-id))) ; |
---|
1374 | } |
---|
1375 | |
---|
1376 | # declare-basic-target target-id : sources : requirements : local-BUILD : target-type |
---|
1377 | # |
---|
1378 | # Declares a basic target for the given target-id and target-type. |
---|
1379 | # All target generation should go through here to ensure all vars are set |
---|
1380 | # for the targets. |
---|
1381 | # |
---|
1382 | # WARNING: This only declares, no build instructions are generated here. |
---|
1383 | rule declare-basic-target ( target-id : sources * : requirements * : default-build * : target-type ) |
---|
1384 | { |
---|
1385 | # We expand out the name of the sources |
---|
1386 | local x-sources = [ expand-source-names $(sources) ] ; |
---|
1387 | |
---|
1388 | # Define the specifications of the target, but only if we haven't already. |
---|
1389 | # |
---|
1390 | if ! $(gTARGET_TYPE($(target-id))) |
---|
1391 | { |
---|
1392 | # Save basic information about the target. |
---|
1393 | # |
---|
1394 | gTARGET_TYPE($(target-id)) = $(target-type) ; |
---|
1395 | |
---|
1396 | # Add the specified requirements to any requirements given by the target |
---|
1397 | # type, and the corresponding <target-type> property. |
---|
1398 | # |
---|
1399 | gTARGET_REQUIREMENTS($(target-id)) |
---|
1400 | = toolset::requirements $(requirements) $(gTARGET_TYPE_REQUIREMENTS($(target-type))) ; |
---|
1401 | if ! $(gNO_TARGET_TYPE_REQUIREMENT($(target-type))) |
---|
1402 | { |
---|
1403 | gTARGET_REQUIREMENTS($(target-id)) += <target-type>$(target-type) ; |
---|
1404 | } |
---|
1405 | |
---|
1406 | # Collect the recognized dependencies to other targets. |
---|
1407 | # |
---|
1408 | local dependencies ; |
---|
1409 | for local source in [ select-gristed $(x-sources) ] |
---|
1410 | { |
---|
1411 | local dependency-type = [ ungrist $(source:G:L) ] ; |
---|
1412 | local dependency-type-id = $(gTARGET_TYPE_ID($(dependency-type))) ; |
---|
1413 | if $(gIS_DEPENDENCY($(dependency-type-id))) |
---|
1414 | { |
---|
1415 | gTARGET_DEPS($(target-id)) += $(source:G=$(dependency-type-id)) ; |
---|
1416 | } |
---|
1417 | } |
---|
1418 | |
---|
1419 | # Sources that aren't recognized as targets, are considered raw sources. |
---|
1420 | # |
---|
1421 | gTARGET_SOURCES($(target-id)) |
---|
1422 | = [ FGristFiles |
---|
1423 | [ difference $(x-sources:G=) : $(gTARGET_DEPS($(target-id)):G=) ] ] ; |
---|
1424 | |
---|
1425 | # Save the default builds. |
---|
1426 | # |
---|
1427 | gTARGET_DEFAULT_BUILD($(target-id)) = $(default-build) ; |
---|
1428 | |
---|
1429 | # Apply any modifiers to the target specs. |
---|
1430 | # |
---|
1431 | for local mod in $(gTARGET_DEPS($(target-id))) |
---|
1432 | { |
---|
1433 | local dependency-type-id = [ ungrist $(mod:G) ] ; |
---|
1434 | local modifier-function = $(gMODIFIER_FUNCTION($(dependency-type-id))) ; |
---|
1435 | if $(modifier-function) |
---|
1436 | { |
---|
1437 | # Remove and apply the modifier. |
---|
1438 | gTARGET_DEPS($(target-id)) = [ difference $(gTARGET_DEPS($(target-id))) : $(mod) ] ; |
---|
1439 | local ignored = [ $(modifier-function) $(target-id) : $(mod) ] ; |
---|
1440 | } |
---|
1441 | } |
---|
1442 | } |
---|
1443 | # Trying to define the same specific target with a different type. |
---|
1444 | # |
---|
1445 | else if $(gTARGET_TYPE($(target-id))) != $(target-type) |
---|
1446 | { |
---|
1447 | EXIT conflicting target types for "$(x-target)": |
---|
1448 | "$(gTARGET_TYPE($(target-id)))" "$(target-type)" ; |
---|
1449 | } |
---|
1450 | } |
---|
1451 | |
---|
1452 | # directory-of files... |
---|
1453 | # |
---|
1454 | # Returns a list of the directories containing each element of files |
---|
1455 | rule directory-of |
---|
1456 | { |
---|
1457 | local result d ; |
---|
1458 | for d in $(<:D) |
---|
1459 | { |
---|
1460 | if $(d) = "" |
---|
1461 | { |
---|
1462 | result += $(DOT) ; |
---|
1463 | } |
---|
1464 | else |
---|
1465 | { |
---|
1466 | result += $(d) ; |
---|
1467 | } |
---|
1468 | } |
---|
1469 | return $(result) ; |
---|
1470 | } |
---|
1471 | |
---|
1472 | # top-relative-tokens path |
---|
1473 | # |
---|
1474 | # Returns a list of path elements which form the relative path from TOP to path, |
---|
1475 | # which is expected to be given relative to the current subproject. |
---|
1476 | rule top-relative-tokens |
---|
1477 | { |
---|
1478 | return [ simplify-path-tokens $(SUBDIR_TOKENS) [ split-path $(<) ] ] ; |
---|
1479 | } |
---|
1480 | |
---|
1481 | .project-root-tokens = [ split-path $(.boost-build-file:D) ] ; |
---|
1482 | |
---|
1483 | # try to make a potentially absolute path relative to the project |
---|
1484 | # root. Only works for paths below the project root right now; others |
---|
1485 | # will remain absolute. |
---|
1486 | rule relative-path ( path ) |
---|
1487 | { |
---|
1488 | local path-tokens = [ split-path $(path) ] ; |
---|
1489 | |
---|
1490 | # try to strip the project root |
---|
1491 | local r = $(.project-root-tokens) ; |
---|
1492 | local p = $(path-tokens) ; |
---|
1493 | while $(r) && ( $(r[1]) = $(p[1]) ) |
---|
1494 | { |
---|
1495 | p = $(p[2-]) ; |
---|
1496 | r = $(r[2-]) ; |
---|
1497 | } |
---|
1498 | |
---|
1499 | # if successful, use the stripped project root |
---|
1500 | if ! $(r) |
---|
1501 | { |
---|
1502 | path-tokens = $(p) ; |
---|
1503 | } |
---|
1504 | |
---|
1505 | return [ tokens-to-simple-path $(path-tokens) ] ; |
---|
1506 | } |
---|
1507 | |
---|
1508 | # dependent-include target-path... |
---|
1509 | # |
---|
1510 | # For each target-path, ensure that the appropriate Jamfile has been |
---|
1511 | # included. Used when a target declares its dependency on another target. |
---|
1512 | rule dependent-include |
---|
1513 | { |
---|
1514 | local target ; |
---|
1515 | for target in $(<) |
---|
1516 | { |
---|
1517 | { |
---|
1518 | local .project-path = [ target-path-of $(target) ] ; |
---|
1519 | .project-path = $(.project-path:D) ; |
---|
1520 | |
---|
1521 | # load the file as a dependent. |
---|
1522 | local gIN_LIB_INCLUDE = TRUE ; |
---|
1523 | |
---|
1524 | # |
---|
1525 | local [ protect-subproject ] ; |
---|
1526 | local .project-name-and-subdir = [ enter-subproject $(.project-path) ] ; |
---|
1527 | local .project-name = $(.project-name-and-subdir[1]) ; |
---|
1528 | local .project-subdir = $(.project-name-and-subdir[2]) ; |
---|
1529 | local .jamfile-path = [ root-paths $(JAMFILE) : [ root-paths $(.project-subdir) : $(TOP) ] ] ; |
---|
1530 | |
---|
1531 | load-jamfiles $(.jamfile-path) ; |
---|
1532 | } |
---|
1533 | } |
---|
1534 | } |
---|
1535 | |
---|
1536 | # segregate-free-properties variable1 variable2... |
---|
1537 | # |
---|
1538 | # returns the and removes the unique list of free properties from |
---|
1539 | # $(variable1) $(variable2)... |
---|
1540 | rule segregate-free-properties |
---|
1541 | { |
---|
1542 | local free-properties = [ unique [ get-properties $(gFREE_FEATURES) : $($(<)) ] ] ; |
---|
1543 | local v ; |
---|
1544 | for v in $(<) |
---|
1545 | { |
---|
1546 | $(v) = [ difference $($(v)) : $(free-properties) ] ; |
---|
1547 | } |
---|
1548 | return $(free-properties) ; |
---|
1549 | } |
---|
1550 | |
---|
1551 | # is-link-compatible feature : value1 : value2 |
---|
1552 | # |
---|
1553 | # return non-empty iff a library built with <feature>value1 can be linked into a |
---|
1554 | # target with <feature>value2, empty otherwise |
---|
1555 | rule is-link-compatible ( feature : value1 : value2 ) |
---|
1556 | { |
---|
1557 | return [ intersection |
---|
1558 | $(feature) $(value1:G=$(feature)) |
---|
1559 | $(value1:G=$(feature))$(SLASH)$(value12:G=$(feature)) |
---|
1560 | $(value2:G=$(feature)) |
---|
1561 | : $(gLINK_COMPATIBLE) ] ; |
---|
1562 | } |
---|
1563 | |
---|
1564 | # find-compatible-subvariant main-target : toolset variant : dependent-simple-properties |
---|
1565 | rule find-compatible-subvariant ( main-target : toolset variant : dependent-simple-properties * ) |
---|
1566 | { |
---|
1567 | # calculate the subvariant only of what is requested |
---|
1568 | # the subvariant requested... |
---|
1569 | local sv-request = |
---|
1570 | [ multiply-property-sets |
---|
1571 | [ get-properties $(BUILD:G) : $(dependent-simple-properties) ] ] ; |
---|
1572 | # the available build requests... |
---|
1573 | local build-requests = |
---|
1574 | [ multiply-property-sets [ select-gristed $(BUILD) ] ] ; |
---|
1575 | # the build requst we want to build... |
---|
1576 | local sv-build = |
---|
1577 | [ intersection $(sv-request) : $(build-requests) ] ; |
---|
1578 | sv-build ?= "" ; |
---|
1579 | local BUILD = $(variant) [ split-path $(sv-build) ] ; |
---|
1580 | local gTARGET_DEFAULT_BUILD($(main-target)) = ; |
---|
1581 | # the full subvariant to build... |
---|
1582 | local subvariant = [ expand-target-subvariants $(main-target) : $(variant) : $(toolset) ] ; |
---|
1583 | |
---|
1584 | local sv-target = ; local sv-properties = ; local sv-toolset = ; local sv-variant = ; |
---|
1585 | split-target-subvariant sv-target sv-properties sv-toolset sv-variant : $(subvariant) ; |
---|
1586 | local sv-overrides = |
---|
1587 | [ difference $(dependent-simple-properties) : [ select-gristed $(sv-properties) ] ] ; |
---|
1588 | sv-overrides += |
---|
1589 | [ get-properties |
---|
1590 | [ difference $(dependent-simple-properties:G) : $(sv-overrides:G) ] : $(sv-properties) ] ; |
---|
1591 | |
---|
1592 | if ! $(gTARGET_TYPE($(main-target))) |
---|
1593 | { |
---|
1594 | EXIT unknown dependent target $(main-target) ; |
---|
1595 | } |
---|
1596 | |
---|
1597 | # check to make sure we can link against the subvariant |
---|
1598 | local target-requirements |
---|
1599 | = [ select-gristed $(gTARGET_REQUIREMENTS($(main-target))) ] ; |
---|
1600 | local override-conflicts |
---|
1601 | = [ get-properties $(target-requirements:G) $(gALWAYS_RELEVANT) : $(sv-overrides) ] ; |
---|
1602 | for local sv-override in $(override-conflicts) |
---|
1603 | { |
---|
1604 | local sv-required = [ get-values $(sv-override:G) : $(sv-properties) ] ; |
---|
1605 | if $(sv-override:G=) != $(sv-required) && |
---|
1606 | ! [ is-link-compatible $(sv-override:G) : $(sv-override:G=) : $(sv-required) ] |
---|
1607 | { |
---|
1608 | EXIT $(main-target): required property $(sv-override:G)$(sv-required) |
---|
1609 | incompatible with $(sv-override) ; |
---|
1610 | } |
---|
1611 | } |
---|
1612 | |
---|
1613 | # now that we have a mostly (or completely) compatible subvariant do the overrides |
---|
1614 | local gTARGET_REQUIREMENTS($(main-target)) = |
---|
1615 | # property rules... |
---|
1616 | [ select-ungristed $(gTARGET_REQUIREMENTS($(main-target))) ] |
---|
1617 | # always relevant properties to target... |
---|
1618 | [ difference |
---|
1619 | $(target-requirements) : |
---|
1620 | [ get-properties [ difference $(sv-overrides:G) : $(gALWAYS_RELEVANT) ] : $(target-requirements) ] ] |
---|
1621 | # link compatible properties, on the target... |
---|
1622 | [ get-properties |
---|
1623 | [ difference $(sv-overrides:G) : $(gALWAYS_RELEVANT) ] : $(target-requirements) ] |
---|
1624 | # overrides from dependent... |
---|
1625 | [ get-properties |
---|
1626 | [ difference $(sv-overrides:G) : $(override-conflicts:G) ] : $(dependent-simple-properties) ] |
---|
1627 | ; |
---|
1628 | subvariant = [ expand-target-subvariants $(sv-target) : $(sv-variant) : $(sv-toolset) ] ; |
---|
1629 | split-target-subvariant sv-target sv-properties sv-toolset sv-variant : $(subvariant) ; |
---|
1630 | |
---|
1631 | return $(sv-properties) ; |
---|
1632 | } |
---|
1633 | |
---|
1634 | |
---|
1635 | # For each target specified in libs, generate build instructions |
---|
1636 | # for a subvariant that can be linked with a dependent target with |
---|
1637 | # dependent-properties, returning a list of all generated targets. |
---|
1638 | rule link-libraries ( libs * : toolset variant : dependent-simple-properties * ) |
---|
1639 | { |
---|
1640 | local lib-path result ; |
---|
1641 | |
---|
1642 | for lib-path in $(libs) |
---|
1643 | { |
---|
1644 | local lib-path = [ target-path-of $(lib-path) ] ; |
---|
1645 | local lib-target = [ target-id-of $(lib-path) ] ; |
---|
1646 | |
---|
1647 | # Enter the dependee subproject |
---|
1648 | local [ protect-subproject ] ; |
---|
1649 | enter-subproject [ directory-of $(lib-path) ] ; |
---|
1650 | |
---|
1651 | local lib-subvariant = [ |
---|
1652 | find-compatible-subvariant $(lib-target) |
---|
1653 | : $(toolset) $(variant) |
---|
1654 | : $(dependent-simple-properties) ] ; |
---|
1655 | |
---|
1656 | # Generate build instructions for the library target |
---|
1657 | result += [ subvariant-target $(lib-target) : $(lib-subvariant) : $(toolset) $(variant) ] ; |
---|
1658 | } |
---|
1659 | return $(result) ; |
---|
1660 | } |
---|
1661 | |
---|
1662 | # Which configuration(s) to build if nothing is explicitly specified |
---|
1663 | DEFAULT_BUILD ?= debug ; |
---|
1664 | |
---|
1665 | # get-BUILD [target-default-build] |
---|
1666 | # |
---|
1667 | # pick the first of ($(BUILD), $(>), $(DEFAULT_BUILD)) which is set. If it |
---|
1668 | # contains no variants, add variants from $(DEFAULT_BUILD). |
---|
1669 | rule get-BUILD |
---|
1670 | { |
---|
1671 | local build = $(BUILD) ; |
---|
1672 | build ?= $(<) ; |
---|
1673 | build ?= $(DEFAULT_BUILD) ; |
---|
1674 | local variants = [ select-ungristed $(build) ] ; |
---|
1675 | if ! $(variants) |
---|
1676 | { |
---|
1677 | build += [ select-ungristed $(DEFAULT_BUILD) ] ; |
---|
1678 | } |
---|
1679 | return $(build) ; |
---|
1680 | } |
---|
1681 | |
---|
1682 | # declare-fake-targets abstract-target : target-file |
---|
1683 | # |
---|
1684 | # |
---|
1685 | rule declare-fake-targets |
---|
1686 | { |
---|
1687 | # make a fake target so that it can be built without knowing the suffix |
---|
1688 | # Since executables under *NIX have no suffix, we'd better check |
---|
1689 | if $(>) != $(<) |
---|
1690 | { |
---|
1691 | DEPENDS $(<) : $(>) ; |
---|
1692 | NOTFILE $(<) ; |
---|
1693 | } |
---|
1694 | |
---|
1695 | # The following checks that we're in the subdirectory of Jam's invocation |
---|
1696 | # so that we can arrange for ungristed target names to be built from the |
---|
1697 | # command-line. |
---|
1698 | if $(<:G) && [ in-invocation-subdir ] |
---|
1699 | { |
---|
1700 | DEPENDS $(<:G=) : $(<) ; # allows $(<:G=) to be used to build all variants |
---|
1701 | NOTFILE $(<:G=) ; |
---|
1702 | } |
---|
1703 | } |
---|
1704 | |
---|
1705 | # declare-target-type TYPE : [[<compiler>]<variant>]<feature>value... |
---|
1706 | rule declare-target-type |
---|
1707 | { |
---|
1708 | gTARGET_TYPE_REQUIREMENTS($(<)) = $(>) ; |
---|
1709 | } |
---|
1710 | |
---|
1711 | declare-target-type DLL : <shared-linkable>true ; |
---|
1712 | |
---|
1713 | if $(NT) |
---|
1714 | { |
---|
1715 | gIMPORT_SUFFIX(DLL) = .lib ; |
---|
1716 | gIMPORT_SUFFIX(LIB) = .lib ; |
---|
1717 | gEXPORT_SUFFIX(DLL) = .lib ; |
---|
1718 | } |
---|
1719 | else |
---|
1720 | { |
---|
1721 | gIMPORT_SUFFIX(DLL) = .so ; |
---|
1722 | gIMPORT_SUFFIX(LIB) = .a ; |
---|
1723 | } |
---|
1724 | |
---|
1725 | # |
---|
1726 | # prepare path constants |
---|
1727 | # |
---|
1728 | { |
---|
1729 | # The names of path variables that are set on targets |
---|
1730 | .run-path-vars = LD_LIBRARY_PATH PATH PYTHONPATH ; |
---|
1731 | |
---|
1732 | for local v in $(.run-path-vars) |
---|
1733 | { |
---|
1734 | .shell-var($(v)) = $(v) ; |
---|
1735 | } |
---|
1736 | |
---|
1737 | # Dynamic libraries are actually found on PATH |
---|
1738 | if $(NT) || ( $(UNIX) = CYGWIN ) |
---|
1739 | { |
---|
1740 | .shell-var(LD_LIBRARY_PATH) = PATH ; |
---|
1741 | } |
---|
1742 | |
---|
1743 | # Dynamic libraries search path var is loader, and hence system, dependant. |
---|
1744 | else |
---|
1745 | { |
---|
1746 | .shell-var(LD_LIBRARY_PATH) = $(gSHELL_LIBPATH) ; |
---|
1747 | } |
---|
1748 | |
---|
1749 | # The names of path variables in the shell |
---|
1750 | .run-path-shell-vars = [ unique $(.shell-var($(.run-path-vars))) ] ; |
---|
1751 | |
---|
1752 | # Record the original value of each shell variable |
---|
1753 | for local v in $(.run-path-shell-vars) |
---|
1754 | { |
---|
1755 | .run-path-shell-var-value($(v)) = $($(v)) ; |
---|
1756 | } |
---|
1757 | |
---|
1758 | if $(NT) |
---|
1759 | { |
---|
1760 | .env-prefix = % ; |
---|
1761 | .env-suffix = % ; |
---|
1762 | } |
---|
1763 | else |
---|
1764 | { |
---|
1765 | .env-prefix = "$" ; |
---|
1766 | .env-suffix = "" ; |
---|
1767 | } |
---|
1768 | } |
---|
1769 | |
---|
1770 | |
---|
1771 | |
---|
1772 | # Helper |
---|
1773 | rule depend-on-libs ( targets + : libs * ) |
---|
1774 | { |
---|
1775 | LIBPATH on $(<) += [ unique $(gLOCATE($(>))) ] ; |
---|
1776 | DEPENDS $(<) : $(>) ; |
---|
1777 | library-dependencies on $(<) += $(>) ; |
---|
1778 | |
---|
1779 | # To run these targets, we need everything needed to run the libraries |
---|
1780 | for local v in $(.run-path-vars) |
---|
1781 | { |
---|
1782 | gRUN_$(v)($(<)) = [ unique $(gRUN_$(v)($(<))) $(gRUN_$(v)($(>))) ] ; |
---|
1783 | } |
---|
1784 | } |
---|
1785 | |
---|
1786 | rule depend-on-static ( targets + : static-libs * ) |
---|
1787 | { |
---|
1788 | local NEEDLIBS = [ unique $(NEEDLIBS) $(>) ] ; |
---|
1789 | NEEDLIBS on $(<) = [ on $(<) return [ unique $(NEEDLIBS) $(>) ] ] ; |
---|
1790 | depend-on-libs $(targets) : $(static-libs) ; |
---|
1791 | } |
---|
1792 | |
---|
1793 | rule depend-on-shared ( targets + : dlls-and-import-libs * ) |
---|
1794 | { |
---|
1795 | local linkable ; |
---|
1796 | |
---|
1797 | # collect the linkable elements of the source libs into the appropriate variables |
---|
1798 | for local f in $(dlls-and-import-libs) |
---|
1799 | { |
---|
1800 | local v = $(gLINK_VARIABLE($(f:S))) ; |
---|
1801 | $(v) += $(f) ; |
---|
1802 | $(v) on $(targets) += $(f) ; |
---|
1803 | if $(v) |
---|
1804 | { |
---|
1805 | linkable += $(f) ; |
---|
1806 | } |
---|
1807 | } |
---|
1808 | |
---|
1809 | FINDLIBS on $(<) += [ unique $(gTARGET_BASENAME($(gTARGET_SUBVARIANT($(>))))) ] ; |
---|
1810 | |
---|
1811 | depend-on-libs $(targets) : $(dlls-and-import-libs) ; |
---|
1812 | } |
---|
1813 | |
---|
1814 | # Given build properties, returns the normalised version of the <tag> features for |
---|
1815 | # use by rename-targets. |
---|
1816 | rule get-tag-features ( variant : build-properties * ) |
---|
1817 | { |
---|
1818 | local result = ; |
---|
1819 | local tags = [ get-properties <tag> : $(build-properties) ] ; |
---|
1820 | for local tag in $(tags) |
---|
1821 | { |
---|
1822 | tag = $(tag:G=) ; |
---|
1823 | if $(tag:G) |
---|
1824 | { |
---|
1825 | result += <tag>$(tag) ; |
---|
1826 | } |
---|
1827 | else |
---|
1828 | { |
---|
1829 | result += <tag><$(variant)>$(tag) ; |
---|
1830 | } |
---|
1831 | } |
---|
1832 | return $(result) ; |
---|
1833 | } |
---|
1834 | |
---|
1835 | rule generate-dependencies ( main-target : subvariant-targets + ) |
---|
1836 | { |
---|
1837 | local dependencies = $(gTARGET_DEPS($(main-target))) ; |
---|
1838 | { |
---|
1839 | # Protect target variables against modification while lib dependencies |
---|
1840 | # are built. They will be made empty here, and restored when this scope exits |
---|
1841 | local $(gTARGET_VARIABLES) ; |
---|
1842 | |
---|
1843 | # extract the simple properties from dependent-properties |
---|
1844 | local p = $(gBUILD_PROPERTIES) ; |
---|
1845 | segregate-free-properties p ; |
---|
1846 | |
---|
1847 | # generate library build instructions |
---|
1848 | local BUILD = $(BUILD) ; |
---|
1849 | BUILD ?= $(gTARGET_DEFAULT_BUILD($(main-target))) ; |
---|
1850 | |
---|
1851 | for t in static shared |
---|
1852 | { |
---|
1853 | local lib-main-targets = [ get-values <$($(t:U)_TYPES)> : $(dependencies) ] ; |
---|
1854 | |
---|
1855 | local lib-targets |
---|
1856 | = [ link-libraries $(lib-main-targets) |
---|
1857 | : $(gCURRENT_TOOLSET) $(variant) : $(p) |
---|
1858 | ] ; |
---|
1859 | depend-on-$(t) $(subvariant-targets) : $(lib-targets) ; |
---|
1860 | } |
---|
1861 | } |
---|
1862 | } |
---|
1863 | |
---|
1864 | # Given main-target, a main target name gristed with $(SOURCE_GRIST), generate build |
---|
1865 | # instructions for a subvariant target using the given toolset, variant, etc. |
---|
1866 | # |
---|
1867 | # RETURNS: the a list of target names for the files built by the subvariant. If |
---|
1868 | # the main-target is a library, the first filename is the one that should be linked |
---|
1869 | # into a dependent target. |
---|
1870 | rule subvariant-target ( main-target : subvariant-id build-properties * : toolset variant ) |
---|
1871 | { |
---|
1872 | # SOURCE_GRIST identifies the subproject directory; TARGET_GRIST will identify |
---|
1873 | # the target and subvariant, since unique versions of files will be built for |
---|
1874 | # that combination. |
---|
1875 | local property-tags = [ get-tag-features $(variant) : $(build-properties) ] ; |
---|
1876 | local tags = [ get-properties <tag> : $(gIMPOSED_REQUIREMENTS($(main-target))) ] $(property-tags) ; |
---|
1877 | local TARGET_GRIST = [ join-path $(SOURCE_GRIST) $(main-target:G=) $(subvariant-id) ] ; |
---|
1878 | local subvariant = $(main-target:G=$(TARGET_GRIST)) ; |
---|
1879 | |
---|
1880 | # Keep track of the generated targets. |
---|
1881 | if ! $(TARGET_GRIST) in $(gDECLARED_TARGETS) |
---|
1882 | { |
---|
1883 | gDECLARED_TARGETS += $(TARGET_GRIST) ; |
---|
1884 | } |
---|
1885 | |
---|
1886 | # Make sure we know how to generate these types of targets. |
---|
1887 | local target-type = $(gTARGET_TYPE($(main-target))) ; |
---|
1888 | if ! $(target-type) |
---|
1889 | { |
---|
1890 | EXIT unknown target type for $(main-target) ; |
---|
1891 | } |
---|
1892 | |
---|
1893 | gTARGET_TYPE($(subvariant)) = $(target-type) ; |
---|
1894 | |
---|
1895 | # LOCATE_TARGET affects where built targets are generated. We move it |
---|
1896 | # relative to the default location based on the subvariant |
---|
1897 | local LOCATE_TARGET |
---|
1898 | = [ join-path $(LOCATE_TARGET) $(main-target:G=) $(subvariant-id) ] ; |
---|
1899 | |
---|
1900 | # The renamed base name of the target. Only considers the tags defined directly |
---|
1901 | # on the target. |
---|
1902 | if $(gTARGET_NAME($(main-target))) |
---|
1903 | { |
---|
1904 | gTARGET_BASENAME($(main-target)) = |
---|
1905 | [ rename-target $(gTARGET_NAME($(main-target))) : [ split-path [ ungrist $(subvariant:G) ] ] : $(property-tags) ] ; |
---|
1906 | } |
---|
1907 | |
---|
1908 | # First order names have the suffix, if any according to the platform. |
---|
1909 | local target-files = [ FAppendSuffix $(subvariant) : $(SUF$(target-type)) ] ; |
---|
1910 | # Second order names have any tags as imposed from stage target contexts. |
---|
1911 | target-files = [ rename-target $(target-files) : [ split-path [ ungrist $(subvariant:G) ] ] : $(tags) ] ; |
---|
1912 | # Third order names are customized as determined by a rename rule on the target type. |
---|
1913 | if $(gNAME_ADJUST($(target-type))) |
---|
1914 | { |
---|
1915 | target-files = [ |
---|
1916 | $(gNAME_ADJUST($(target-type))) $(target-files) |
---|
1917 | : $(subvariant-id) $(build-properties) |
---|
1918 | : $(toolset) $(variant) ] ; |
---|
1919 | gTARGET_TYPE($(target-files[1])) = $(target-type) ; |
---|
1920 | } |
---|
1921 | |
---|
1922 | # Do nothing if we already have the build instructions for the specific |
---|
1923 | # target files of this subvariant target. |
---|
1924 | if ! $(target-files) in $(gTARGET_FILES($(main-target))) |
---|
1925 | { |
---|
1926 | gTARGET_SUBVARIANT($(target-files)) = $(main-target) ; |
---|
1927 | |
---|
1928 | ###gTARGET_FILES($(subvariant)) = $(target-files) ; |
---|
1929 | gTARGET_FILES($(main-target)) += $(target-files) ; |
---|
1930 | |
---|
1931 | # Remember the path from the build root to the subvariant directory |
---|
1932 | gSUBVARIANT_PATH($(subvariant)) = $(subvariant-id) ; |
---|
1933 | |
---|
1934 | # Add target suppression if <suppress> was in the requirements |
---|
1935 | local gSUPPRESS_FAKE_TARGETS = [ get-values <suppress> : $(gTARGET_REQUIREMENTS($(main-target))) ] $(gSUPPRESS_FAKE_TARGETS) ; |
---|
1936 | |
---|
1937 | declare-fake-targets $(main-target) : $(target-files) ; |
---|
1938 | |
---|
1939 | # set up gBUILD_PROPERTIES for include-tools (below) |
---|
1940 | local gBUILD_PROPERTIES = $(build-properties) ; |
---|
1941 | |
---|
1942 | # Include the toolset specification. This will set up the global flags |
---|
1943 | # variables in a way appropriate to this build. |
---|
1944 | |
---|
1945 | include-tools $(toolset) ; |
---|
1946 | |
---|
1947 | # headers should be identified specific to the target, since search paths |
---|
1948 | # may differ for different subvariants. The same header name or relative |
---|
1949 | # path may refer to different files. |
---|
1950 | local HDRGRIST = [ join $(SOURCE_GRIST) $(STDHDRS) $(SYSHDRS) $(HDRS) "" : "#" ] ; |
---|
1951 | |
---|
1952 | # transfer target variables to the target file. |
---|
1953 | set-target-variables $(target-files) ; |
---|
1954 | |
---|
1955 | local dependencies |
---|
1956 | = [ get-values <$(STATIC_TYPES)> <$(SHARED_TYPES)> |
---|
1957 | : $(gTARGET_DEPS($(main-target))) |
---|
1958 | ] ; |
---|
1959 | |
---|
1960 | if $(dependencies) |
---|
1961 | { |
---|
1962 | # include each jamfile describing a dependee target. |
---|
1963 | dependent-include $(dependencies) ; |
---|
1964 | generate-dependencies $(main-target) : $(target-files) ; |
---|
1965 | } |
---|
1966 | |
---|
1967 | local generator = $(gGENERATOR_FUNCTION($(target-type))) ; |
---|
1968 | local sources = $(gTARGET_SOURCES($(main-target))) ; |
---|
1969 | $(generator) $(target-files) : $(sources) ; |
---|
1970 | |
---|
1971 | $(gTARGET_VARIABLES) = ; # Be sure that we don't mask bugs with lingering target variables |
---|
1972 | } |
---|
1973 | return $(target-files) ; |
---|
1974 | } |
---|
1975 | |
---|
1976 | # Generate the expanded subvariants of a target. |
---|
1977 | # |
---|
1978 | rule expand-target-subvariants ( target : local-build * : tools + : ) |
---|
1979 | { |
---|
1980 | local BUILD = [ get-BUILD $(local-build) ] ; |
---|
1981 | local variants = [ select-ungristed $(BUILD) ] ; |
---|
1982 | local build-request = [ difference $(BUILD) : $(variants) ] ; |
---|
1983 | |
---|
1984 | local subvariants = ; |
---|
1985 | for local toolset in $(tools) |
---|
1986 | { |
---|
1987 | for local variant in $(variants) |
---|
1988 | { |
---|
1989 | local rules = [ select-ungristed |
---|
1990 | $(gTARGET_REQUIREMENTS($(target))) |
---|
1991 | $(gIMPOSED_REQUIREMENTS($(target))) ] ; |
---|
1992 | local requirements = [ select-gristed |
---|
1993 | $(gTARGET_REQUIREMENTS($(target))) |
---|
1994 | $(gIMPOSED_REQUIREMENTS($(target))) ] ; |
---|
1995 | |
---|
1996 | local expanded |
---|
1997 | = [ expand-build-request $(toolset) $(variant) $(target) |
---|
1998 | : $(requirements) : $(build-request) ] ; |
---|
1999 | |
---|
2000 | local gNOWARN_INCOMPATIBLE_BUILDS = TRUE ; |
---|
2001 | |
---|
2002 | for local instance in $(expanded) |
---|
2003 | { |
---|
2004 | local properties = [ split-path-at-grist $(instance) ] ; |
---|
2005 | for local r in $(rules) |
---|
2006 | { |
---|
2007 | properties = [ $(r) $(toolset) $(variant) : $(properties) ] ; |
---|
2008 | } |
---|
2009 | |
---|
2010 | if ! ( <build>no in $(properties) ) |
---|
2011 | { |
---|
2012 | # the rules may have modified the build request, reconstruct it |
---|
2013 | properties = [ expand-build-request $(toolset) $(variant) $(target) |
---|
2014 | : $(properties[2-]) : $(build-request) ] ; |
---|
2015 | |
---|
2016 | subvariants += $(target)|$(properties)|$(toolset)|$(variant) ; |
---|
2017 | } |
---|
2018 | else if --dump-unbuilt |
---|
2019 | { |
---|
2020 | ECHO **** skipping build of $(target); toolset= $(toolset) variant= $(variant) **** ; |
---|
2021 | } |
---|
2022 | } |
---|
2023 | } |
---|
2024 | } |
---|
2025 | return [ unique $(subvariants) ] ; |
---|
2026 | } |
---|
2027 | |
---|
2028 | # Given an expanded subvariant of a terget, sets the various variables accordingly. |
---|
2029 | # |
---|
2030 | rule split-target-subvariant ( target-var properties-var toolset-var variant-var : subvariant ) |
---|
2031 | { |
---|
2032 | local subvariant-items = [ MATCH (.*)[|](.*)[|](.*)[|](.*) : $(subvariant) ] ; |
---|
2033 | $(target-var) = $(subvariant-items[1]) ; |
---|
2034 | $(properties-var) = [ split-path-at-grist $(subvariant-items[2]) ] ; |
---|
2035 | $(toolset-var) = $(subvariant-items[3]) ; |
---|
2036 | $(variant-var) = $(subvariant-items[4]) ; |
---|
2037 | return $((target-var)) ; |
---|
2038 | } |
---|
2039 | |
---|
2040 | # main-target target : local-build |
---|
2041 | # |
---|
2042 | # Generates requested subvariant build instructions for the given main target |
---|
2043 | rule main-target |
---|
2044 | { |
---|
2045 | local subvariants = [ expand-target-subvariants $(<) : $(>) : $(TOOLS) ] ; |
---|
2046 | |
---|
2047 | # include each jamfile describing a dependee target. |
---|
2048 | dependent-include [ get-values <$(STATIC_TYPES)> <$(SHARED_TYPES)> : $(gTARGET_DEPS($(<))) ] ; |
---|
2049 | |
---|
2050 | for local subvariant in $(subvariants) |
---|
2051 | { |
---|
2052 | local target = ; |
---|
2053 | local properties = ; |
---|
2054 | local toolset = ; |
---|
2055 | local variant = ; |
---|
2056 | split-target-subvariant target properties toolset variant : $(subvariant) ; |
---|
2057 | subvariant-target $(target) : $(properties) : $(toolset) $(variant) ; |
---|
2058 | } |
---|
2059 | } |
---|
2060 | |
---|
2061 | # Declare an executable target. |
---|
2062 | # |
---|
2063 | gTARGET_TYPE_ID(exe) = EXE ; |
---|
2064 | gGENERATOR_FUNCTION(EXE) = executable-file ; |
---|
2065 | rule exe ( target : sources + : requirements * : default-build * ) |
---|
2066 | { |
---|
2067 | declare-local-target $(target) : $(sources) : $(requirements) : $(default-build) : EXE ; |
---|
2068 | } |
---|
2069 | |
---|
2070 | # Declare a shared library target. |
---|
2071 | # |
---|
2072 | gTARGET_TYPE_ID(dll) = DLL ; |
---|
2073 | gGENERATOR_FUNCTION(DLL) = dll-files ; |
---|
2074 | gIS_DEPENDENCY(DLL) = TRUE ; |
---|
2075 | rule dll ( target : sources + : requirements * : default-build * ) |
---|
2076 | { |
---|
2077 | if $(JAMUNAME[1]) = OpenBSD |
---|
2078 | { |
---|
2079 | if ! [ get-values <dllversion> : $(requirements) ] |
---|
2080 | { |
---|
2081 | requirements += <dllversion>0.0 ; |
---|
2082 | } |
---|
2083 | } |
---|
2084 | declare-local-target $(target) : $(sources) : $(requirements) : $(default-build) : DLL ; |
---|
2085 | } |
---|
2086 | |
---|
2087 | # Declare a statically-linked library target. |
---|
2088 | # |
---|
2089 | gTARGET_TYPE_ID(lib) = LIB ; |
---|
2090 | gGENERATOR_FUNCTION(LIB) = library-file ; |
---|
2091 | gIS_DEPENDENCY(LIB) = TRUE ; |
---|
2092 | rule lib ( target : sources + : requirements * : default-build * ) |
---|
2093 | { |
---|
2094 | declare-local-target $(target) : $(sources) : $(requirements) : $(default-build) : LIB ; |
---|
2095 | } |
---|
2096 | |
---|
2097 | # Declare a template target for other targets. This is a modifier only. It |
---|
2098 | # Adds the specs specified here to any other target it's a dependee of. |
---|
2099 | # |
---|
2100 | gTARGET_TYPE_ID(template) = TEMPLATE ; |
---|
2101 | gMODIFIER_FUNCTION(TEMPLATE) = template-modifier ; |
---|
2102 | gIS_DEPENDENCY(TEMPLATE) = TRUE ; |
---|
2103 | gNO_TARGET_TYPE_REQUIREMENT(TEMPLATE) = TRUE ; |
---|
2104 | rule template ( target : sources * : requirements * : default-build * ) |
---|
2105 | { |
---|
2106 | declare-local-target $(target) : $(sources) : $(requirements) : $(default-build) : TEMPLATE ; |
---|
2107 | } |
---|
2108 | |
---|
2109 | # Declare an executable target, to be run by tests. |
---|
2110 | rule unit-test ( target + : sources + : requirements * : default-build * : cmd-line * ) |
---|
2111 | { |
---|
2112 | if ! $(.testing.jam-included) |
---|
2113 | { |
---|
2114 | SEARCH on testing.jam = $(BOOST_BUILD_PATH) ; |
---|
2115 | include testing.jam ; |
---|
2116 | } |
---|
2117 | |
---|
2118 | DEPENDS all |
---|
2119 | : [ run $(sources) |
---|
2120 | : $(cmd-line) |
---|
2121 | : # input-files |
---|
2122 | : $(requirements) |
---|
2123 | : $(target) |
---|
2124 | : $(default-build) |
---|
2125 | ] |
---|
2126 | ; |
---|
2127 | } |
---|
2128 | |
---|
2129 | # Used to build command files from a list of sources. |
---|
2130 | rule build-command-file ( command : sources * : prefix ? line-break ? ) |
---|
2131 | { |
---|
2132 | # Clean up after ourselves |
---|
2133 | Clean clean : $(command) ; |
---|
2134 | |
---|
2135 | DEPENDS $(command) : $(sources) ; |
---|
2136 | |
---|
2137 | PREFIX on $(command) = $(prefix:E=) ; |
---|
2138 | |
---|
2139 | local ' _ = "" ; |
---|
2140 | |
---|
2141 | if ! $(NT) |
---|
2142 | { |
---|
2143 | ' = ' ; |
---|
2144 | _ = " " ; |
---|
2145 | } |
---|
2146 | |
---|
2147 | ' on $(command) = $(') ; |
---|
2148 | _ on $(command) = $(_) ; |
---|
2149 | |
---|
2150 | EOL on $(command) = \"$(line-break:E=)$(')$(_)>>$(_)\" ; |
---|
2151 | BOL on $(command) = "\" |
---|
2152 | echo $(')$(prefix:E=)\"" ; |
---|
2153 | |
---|
2154 | # Check whether there's anything to dump, so that we don't end up |
---|
2155 | # executing a line of the form: |
---|
2156 | # |
---|
2157 | # echo >> file.CMD |
---|
2158 | # |
---|
2159 | # on Windows this writes "echo is on." into the command-file, |
---|
2160 | # which then breaks the link. |
---|
2161 | |
---|
2162 | if $(sources) |
---|
2163 | { |
---|
2164 | # Handle the first target specially, so that the first source file |
---|
2165 | # will clear the command file |
---|
2166 | command-file-dump $(command) : $(sources) ; |
---|
2167 | } |
---|
2168 | } |
---|
2169 | |
---|
2170 | # Quietly delete $(x) if it exists with $(RM1)"$(x)" |
---|
2171 | if $(NT) |
---|
2172 | { |
---|
2173 | RM1 = "IF EXIST " "DEL " ; |
---|
2174 | } |
---|
2175 | else |
---|
2176 | { |
---|
2177 | RM1 = "$(RM) " ; |
---|
2178 | } |
---|
2179 | |
---|
2180 | # Build the command-file |
---|
2181 | actions quietly command-file-dump |
---|
2182 | { |
---|
2183 | $(RM1)"$(<)" |
---|
2184 | echo $(')$(PREFIX)"$(>:J=$(EOL)$(<)$(BOL))"$(')$(_)>>$(_)$(<) |
---|
2185 | } |
---|
2186 | |
---|
2187 | # Clean up the temporary COMMAND-FILE used to build TARGETS. |
---|
2188 | rule remove-command-file ( targets + : command-file ) |
---|
2189 | { |
---|
2190 | TEMPORARY $(command-file) ; |
---|
2191 | Clean clean : $(command-file) ; # Mark the file for removal via clean |
---|
2192 | } |
---|
2193 | actions ignore quietly piecemeal together remove-command-file |
---|
2194 | { |
---|
2195 | $(RM) $(>) |
---|
2196 | } |
---|
2197 | |
---|
2198 | # build TARGETS from SOURCES using a command-file, where RULE-NAME is |
---|
2199 | # used to generate the build instructions from the command-file to |
---|
2200 | # TARGETS |
---|
2201 | rule with-command-file ( rule-name targets * : sources * : prefix ? line-break ? ) |
---|
2202 | { |
---|
2203 | # create a command-file target and place it where the first target |
---|
2204 | # will be built |
---|
2205 | local command-file = $(targets[1]:S=.CMD) ; |
---|
2206 | LOCATE on $(command-file) = $(gLOCATE($(targets[1]))) ; |
---|
2207 | build-command-file $(command-file) : $(sources) : $(prefix) $(line-break) ; |
---|
2208 | |
---|
2209 | # Build the targets from the command-file instead of the sources |
---|
2210 | DEPENDS $(targets) : $(command-file) ; |
---|
2211 | local result = [ $(rule-name) $(targets) : $(command-file) ] ; |
---|
2212 | |
---|
2213 | # clean up afterwards |
---|
2214 | # Can't really do this until <find-library> arguments are accounted for. |
---|
2215 | # remove-command-file $(targets) : $(command-file) ; |
---|
2216 | return $(result) ; |
---|
2217 | } |
---|
2218 | |
---|
2219 | TAG(prefix) = "" ; |
---|
2220 | TAG(postfix) = "" ; |
---|
2221 | |
---|
2222 | # GIVEN: |
---|
2223 | # |
---|
2224 | # A target subvariant, the subvariant info, and a set of rename tags. |
---|
2225 | # |
---|
2226 | # RESULT: |
---|
2227 | # |
---|
2228 | # Uses the rename tags, and the global TAG map, to append a tag to the |
---|
2229 | # target basename. The new subvariant target is returned. The tag for |
---|
2230 | # the target is composed from the subvariant info and the corresponding |
---|
2231 | # entry in the tags. This creates the tag in the order as given by the |
---|
2232 | # subvariant info. |
---|
2233 | # |
---|
2234 | # EXAMPLE: |
---|
2235 | # |
---|
2236 | # [ rename-target <gcc/debug>libtest.so : gcc debug : <tag><gcc>_gcc <tag><debug>_debug ] |
---|
2237 | # |
---|
2238 | # RETURNS: |
---|
2239 | # |
---|
2240 | # <gcc/debug>libtest_gcc_debug.so |
---|
2241 | # |
---|
2242 | rule rename-target ( target + : subvariant * : tags * ) |
---|
2243 | { |
---|
2244 | local tag-values = ; |
---|
2245 | for local tag in $(tags) |
---|
2246 | { |
---|
2247 | local tag-tokens = [ MATCH (<)(.*)(>)(.*) : $(tag:G=) ] ; |
---|
2248 | tag-tokens = $(tag-tokens[2]) $(tag-tokens[4]) ; |
---|
2249 | tag-values += $(tag-tokens[2]:G=$(tag-tokens[1])) ; |
---|
2250 | } |
---|
2251 | |
---|
2252 | local tag-text = "" ; |
---|
2253 | |
---|
2254 | # the prefix of the tag... |
---|
2255 | # |
---|
2256 | local prefix-tag = [ get-values <prefix> : $(tag-values) $(TAG(prefix):G=prefix) ] ; |
---|
2257 | tag-text = $(prefix-tag[1]) ; |
---|
2258 | |
---|
2259 | # the subvariant tags... |
---|
2260 | # |
---|
2261 | for local sv in $(subvariant) |
---|
2262 | { |
---|
2263 | local sv-tag = [ get-values <$(sv)> : $(tag-values) $(TAG($(sv)):G=$(sv)) ] ; |
---|
2264 | if $(sv-tag) |
---|
2265 | { |
---|
2266 | tag-text = $(tag-text)$(sv-tag[1]) ; |
---|
2267 | } |
---|
2268 | } |
---|
2269 | |
---|
2270 | # the postfix of the tag... |
---|
2271 | # |
---|
2272 | local postfix-tag = [ get-values <postfix> : $(tag-values) $(TAG(postfix):G=postfix) ] ; |
---|
2273 | tag-text = $(tag-text)$(postfix-tag[1]) ; |
---|
2274 | |
---|
2275 | local renamed-target = ; |
---|
2276 | for local t in $(target) |
---|
2277 | { |
---|
2278 | local B-S = [ MATCH ([^\\.]*)(.*) : $(t:G=) ] ; |
---|
2279 | local B = $(B-S[1]) ; B ?= "" ; |
---|
2280 | local S = $(B-S[2]) ; S ?= "" ; |
---|
2281 | local new-name = $(B)$(tag-text)$(S) ; new-name = $(new-name:G=$(t:G)) ; |
---|
2282 | renamed-target += $(new-name) ; |
---|
2283 | } |
---|
2284 | return $(renamed-target) ; |
---|
2285 | } |
---|
2286 | |
---|
2287 | rule grist-targets ( targets + : subdir-tokens * ) |
---|
2288 | { |
---|
2289 | local subdir-grist = "" ; |
---|
2290 | if $(subdir-tokens) |
---|
2291 | { |
---|
2292 | subdir-grist = [ FGrist $(subdir-tokens) ] ; |
---|
2293 | if $(SOURCE_GRIST) |
---|
2294 | { |
---|
2295 | subdir-grist = "!$(subdir-grist)" ; |
---|
2296 | } |
---|
2297 | } |
---|
2298 | if ! $(SOURCE_GRIST) |
---|
2299 | { |
---|
2300 | return $(targets:G=$(subdir-grist)) ; |
---|
2301 | } |
---|
2302 | else |
---|
2303 | { |
---|
2304 | return $(targets:G=$(SOURCE_GRIST)$(subdir-grist)) ; |
---|
2305 | } |
---|
2306 | } |
---|
2307 | |
---|
2308 | # EXAMPLE: |
---|
2309 | # |
---|
2310 | # stage test-stage |
---|
2311 | # : <exe>foo/bar/test1 <dll>qwerty/keys docs/README |
---|
2312 | # : <tag><prefix>"_" <tag><debug>"D" <tag><profile>"P" <tag><gcc>"GCC" |
---|
2313 | # : debug profile <suppress>true |
---|
2314 | # ; |
---|
2315 | # |
---|
2316 | # PRODUCES: |
---|
2317 | # |
---|
2318 | # test-stage/libkeys_GCCD.so |
---|
2319 | # test-stage/libkeys_GCCP.so |
---|
2320 | # test-stage/test1_GCCD |
---|
2321 | # test-stage/test1_GCCP |
---|
2322 | # test-stage/README |
---|
2323 | # |
---|
2324 | # IFF: |
---|
2325 | # |
---|
2326 | # $shell> jam test-stage |
---|
2327 | # |
---|
2328 | rule stage ( name : sources + : requirements * : local-build * ) |
---|
2329 | { |
---|
2330 | if ! $(gIN_LIB_INCLUDE) |
---|
2331 | { |
---|
2332 | |
---|
2333 | local stage-id = |
---|
2334 | [ grist-targets $(name) ] ; |
---|
2335 | local arch-subdirs = [ get-values <architecture-subdirs> : $(requirements) ] ; |
---|
2336 | local tree-root = [ get-values <tree-subdirs> : $(requirements) ] ; |
---|
2337 | if $(tree-root) { tree-root = [ split-path $(tree-root[1]) ] ; } |
---|
2338 | local locate = [ get-values <locate> : $(requirements) ] ; |
---|
2339 | if $(locate) { locate = [ split-path $(locate) ] ; } |
---|
2340 | local fake-target = [ get-values <target> : $(requirements) ] ; |
---|
2341 | local rename-rule = [ get-values <rename> : $(requirements) ] ; |
---|
2342 | |
---|
2343 | # Supress the regular build of this target |
---|
2344 | local gSUPPRESS_FAKE_TARGETS = [ get-values <suppress> : $(local-build) ] ; |
---|
2345 | |
---|
2346 | local stage-dir = $(name:G=) ; |
---|
2347 | local files ; |
---|
2348 | local file-mode ; |
---|
2349 | local file-tagged ; |
---|
2350 | local file-subdir ; |
---|
2351 | |
---|
2352 | # Prevent built object from getting deleted so that when targets are linked |
---|
2353 | # multiple times they are available. |
---|
2354 | local KEEPOBJS = true ; |
---|
2355 | |
---|
2356 | # For each source, collect its information, and possibly generate it. |
---|
2357 | # |
---|
2358 | for local source in $(sources) |
---|
2359 | { |
---|
2360 | source = [ split-qualified-property $(source) ] ; |
---|
2361 | local source-build = [ MATCH "^<([^>]*)>" : $(source[1-2]) ] ; |
---|
2362 | source = [ expand-source-names $(source[3]) ] ; |
---|
2363 | |
---|
2364 | if $(source:G) |
---|
2365 | { |
---|
2366 | local gIN_LIB_INCLUDE = TRUE ; |
---|
2367 | |
---|
2368 | local target = $(source:D=:G=) ; |
---|
2369 | local target-id = [ target-id-of $(source) ] ; |
---|
2370 | local target-subdir = [ directory-of [ target-path-of $(source) ] ] ; |
---|
2371 | |
---|
2372 | dependent-include $(source:G=) ; |
---|
2373 | local gIMPOSED_REQUIREMENTS($(target-id)) = $(requirements) ; |
---|
2374 | local subvariants = [ expand-target-subvariants $(target-id) : $(local-build) : $(TOOLS) ] ; |
---|
2375 | |
---|
2376 | for local subvariant in $(subvariants) |
---|
2377 | { |
---|
2378 | local s-target = ; |
---|
2379 | local s-properties = ; |
---|
2380 | local s-toolset = ; |
---|
2381 | local s-variant = ; |
---|
2382 | split-target-subvariant s-target s-properties s-toolset s-variant : $(subvariant) ; |
---|
2383 | local s-subdir ; |
---|
2384 | if $(arch-subdirs) |
---|
2385 | { |
---|
2386 | local arch = [ get-values <instruction-set> : $(s-properties) ] ; |
---|
2387 | arch ?= [ get-values <architecture> : $(s-properties) ] ; |
---|
2388 | arch ?= $(OSPLAT:L) ; |
---|
2389 | if $(arch) = "default" { arch = $(OSPLAT:L) ; } |
---|
2390 | arch += [ get-values <address-model> : $(s-properties) ] ; |
---|
2391 | arch += $(OS:L) ; |
---|
2392 | s-subdir = $(arch:J=-) ; |
---|
2393 | } |
---|
2394 | |
---|
2395 | local source-build-rule = [ MATCH "[`]([^`]+)[`]" : $(source-build[2]) ] ; |
---|
2396 | if ( $(s-toolset) = $(source-build[1]) || $(source-build[1]) = * ) && |
---|
2397 | ( $(s-variant) = $(source-build[2]) || $(source-build[2]) = * ) || |
---|
2398 | $(source-build-rule) && [ $(source-build-rule) $(s-toolset) $(s-variant) ] |
---|
2399 | { |
---|
2400 | |
---|
2401 | local target-subvariant = ; |
---|
2402 | { |
---|
2403 | local [ protect-subproject ] ; |
---|
2404 | enter-subproject $(target-subdir) ; |
---|
2405 | target-subvariant = |
---|
2406 | [ subvariant-target $(s-target) : $(s-properties) : $(s-toolset) $(s-variant) ] ; |
---|
2407 | } |
---|
2408 | |
---|
2409 | local sv-files = ; |
---|
2410 | for local sv in $(target-subvariant) |
---|
2411 | { |
---|
2412 | local sv-file = $(gFILES($(sv))) ; |
---|
2413 | sv-file ?= $(sv) ; |
---|
2414 | sv-files += $(sv-file) ; |
---|
2415 | } |
---|
2416 | sv-files = [ unique $(sv-files) ] ; |
---|
2417 | for local sv in $(sv-files) |
---|
2418 | { |
---|
2419 | local renamed-target ; |
---|
2420 | local split-properties = [ split-path $(s-properties[1]) ] ; |
---|
2421 | for local rr in $(rename-rule) |
---|
2422 | { |
---|
2423 | renamed-target += [ $(rr) $(sv) : $(split-properties) ] ; |
---|
2424 | } |
---|
2425 | renamed-target ?= |
---|
2426 | [ rename-target $(sv) : [ split-path $(s-properties[1]) ] : ] ; |
---|
2427 | |
---|
2428 | files += $(sv) ; |
---|
2429 | file-mode($(sv)) = $($(gTARGET_TYPE($(s-target)))MODE) ; |
---|
2430 | file-tagged($(sv)) = $(renamed-target) ; |
---|
2431 | file-subdir($(sv)) = $(s-subdir) ; |
---|
2432 | } |
---|
2433 | |
---|
2434 | } |
---|
2435 | } |
---|
2436 | } |
---|
2437 | else |
---|
2438 | { |
---|
2439 | local renamed-file ; |
---|
2440 | for local rr in $(rename-rule) |
---|
2441 | { |
---|
2442 | renamed-file += [ $(rr) $(source) ] ; |
---|
2443 | } |
---|
2444 | renamed-file ?= $(source) ; |
---|
2445 | |
---|
2446 | files += $(source) ; |
---|
2447 | file-tagged($(source)) = $(renamed-file) ; |
---|
2448 | } |
---|
2449 | } |
---|
2450 | |
---|
2451 | # Generate and collect the file copy build instructions. If we |
---|
2452 | # are getting defined in the dependent phase skip the actual instructions. |
---|
2453 | # |
---|
2454 | local destination-files = ; |
---|
2455 | local result-files = ; |
---|
2456 | local locate-target = $(locate) ; |
---|
2457 | if $(ALL_LOCATE_TARGET) |
---|
2458 | { |
---|
2459 | locate-target ?= [ join-path [ split-path $(ALL_LOCATE_TARGET) ] $(SUBDIR_TOKENS) ] ; |
---|
2460 | } |
---|
2461 | locate-target ?= [ split-path $(SUBDIR) ] ; |
---|
2462 | for local file in $(files) |
---|
2463 | { |
---|
2464 | local destination-file ; |
---|
2465 | local destination-subdir ; |
---|
2466 | if $(file:G) |
---|
2467 | { |
---|
2468 | destination-file = $(file-tagged($(file)):G=:D=) ; |
---|
2469 | destination-subdir = $(file-subdir($(file))) ; |
---|
2470 | } |
---|
2471 | else |
---|
2472 | { |
---|
2473 | destination-file = $(file-tagged($(file)):D=) ; |
---|
2474 | if $(tree-root) |
---|
2475 | { |
---|
2476 | destination-subdir = [ strip-initial $(tree-root) : [ split-path $(file:D) ] ] ; |
---|
2477 | } |
---|
2478 | } |
---|
2479 | destination-file = |
---|
2480 | [ grist-targets $(destination-file) : [ split-path $(stage-dir) ] $(destination-subdir) ] ; |
---|
2481 | destination-files += $(destination-file) ; |
---|
2482 | { |
---|
2483 | local FILEMODE = $(FILEMODE) ; |
---|
2484 | if $(file-mode($(file))) { FILEMODE = $(file-mode($(file))) ; } |
---|
2485 | MakeLocate $(destination-file) : |
---|
2486 | [ FDirName $(locate-target) [ split-path $(stage-dir) ] $(destination-subdir) ] ; |
---|
2487 | for local df in $(destination-file) |
---|
2488 | { |
---|
2489 | result-files += $(df) ; |
---|
2490 | FileClone $(df) : $(file) ; |
---|
2491 | } |
---|
2492 | local target = $(stage-id) $(destination-subdir) $(destination-file:G=) ; |
---|
2493 | declare-fake-targets $(target:J=/) : $(destination-file) ; |
---|
2494 | } |
---|
2495 | } |
---|
2496 | |
---|
2497 | # Don't expose fake targets when suppressing default builds. |
---|
2498 | # But honor requirement to expose sources through given <target>. |
---|
2499 | # |
---|
2500 | if ! $(fake-target) |
---|
2501 | { |
---|
2502 | declare-fake-targets $(stage-id:G=) : $(destination-files) ; |
---|
2503 | } |
---|
2504 | else |
---|
2505 | { |
---|
2506 | if $(gSUPPRESS_FAKE_TARGETS) |
---|
2507 | { |
---|
2508 | declare-fake-targets $(fake-target) : $(files) ; |
---|
2509 | } |
---|
2510 | else |
---|
2511 | { |
---|
2512 | declare-fake-targets $(fake-target) : $(destination-files) ; |
---|
2513 | } |
---|
2514 | } |
---|
2515 | |
---|
2516 | Clean clean : $(destination-files) ; |
---|
2517 | |
---|
2518 | return $(result-files) ; |
---|
2519 | |
---|
2520 | } |
---|
2521 | } |
---|
2522 | |
---|
2523 | # GIVEN: |
---|
2524 | # |
---|
2525 | # A bare target, either with or without grist. |
---|
2526 | # |
---|
2527 | # RETURNS: |
---|
2528 | # |
---|
2529 | # The fully qualified and gristed target ID. |
---|
2530 | # |
---|
2531 | # EXAMPLE: |
---|
2532 | # |
---|
2533 | # [ target-id-of <lib>../../sub1/sub2/test.dll ] |
---|
2534 | # |
---|
2535 | # RETURNS: |
---|
2536 | # |
---|
2537 | # <sub1!sub2>test.dll |
---|
2538 | # |
---|
2539 | rule target-id-of ( target-ref ) |
---|
2540 | { |
---|
2541 | local grist = $(target-ref:G) ; |
---|
2542 | local target = $(target-ref:G=) ; |
---|
2543 | while $(target:G) |
---|
2544 | { |
---|
2545 | grist += $(target:G) ; |
---|
2546 | target = $(target:G=) ; |
---|
2547 | } |
---|
2548 | local path = [ directory-of $(target) ] ; |
---|
2549 | if ! [ MATCH "^(@)" : $(path) ] |
---|
2550 | { |
---|
2551 | path = [ join @$(PROJECT) [ simplify-path-tokens [ top-relative-tokens $(path) ] ] : / ] ; |
---|
2552 | } |
---|
2553 | local tokens = [ split-path $(path) ] ; |
---|
2554 | local project-name = [ MATCH "^@([^/\\]+)" : $(tokens[1]) ] ; |
---|
2555 | if $(project-name) |
---|
2556 | { |
---|
2557 | tokens = $(tokens[2-]) ; |
---|
2558 | } |
---|
2559 | project-name ?= $(PROJECT) ; |
---|
2560 | local SOURCE_GRIST = [ FGrist @$(project-name) [ simplify-path-tokens $(tokens) ] ] ; |
---|
2561 | local target-id = [ FGristFiles $(target:D=) ] ; |
---|
2562 | return $(target-id) ; |
---|
2563 | } |
---|
2564 | |
---|
2565 | # |
---|
2566 | # |
---|
2567 | rule target-path-of ( target-ref ) |
---|
2568 | { |
---|
2569 | local grist = $(target-ref:G) ; |
---|
2570 | local target = $(target-ref:G=) ; |
---|
2571 | while $(target:G) |
---|
2572 | { |
---|
2573 | grist += $(target:G) ; |
---|
2574 | target = $(target:G=) ; |
---|
2575 | } |
---|
2576 | local path = [ directory-of $(target) ] ; |
---|
2577 | if ! [ MATCH "^(@)" : $(path) ] |
---|
2578 | { |
---|
2579 | path = [ join @$(PROJECT) [ simplify-path-tokens [ top-relative-tokens $(path) ] ] : / ] ; |
---|
2580 | } |
---|
2581 | path = $(path)/$(target:D=) ; |
---|
2582 | if $(grist) |
---|
2583 | { |
---|
2584 | path = $(grist:J="")$(path) ; |
---|
2585 | } |
---|
2586 | return $(path) ; |
---|
2587 | } |
---|
2588 | |
---|
2589 | # Common rules for generating a single tag based on the |
---|
2590 | # variant, build properties, and the toolset used to build. |
---|
2591 | # To use place this rule name in the requirementes section of |
---|
2592 | # a stage target. |
---|
2593 | # |
---|
2594 | # The tag is constructed as such: |
---|
2595 | # |
---|
2596 | # [-<toolset-tag>][-<thread-tag>][-<runtime-tag>][-<version-tag>] |
---|
2597 | # |
---|
2598 | # <toolset-tag> maps to an abbreviated name of the toolset |
---|
2599 | # and when possible and applicable the version of the toolset. |
---|
2600 | # |
---|
2601 | # <thread-tag> "mt" when multi-threading is enabled. |
---|
2602 | # |
---|
2603 | # <runtime-tag> adds these single letter tags: |
---|
2604 | # "s" when static linking to runtime |
---|
2605 | # "g" when linking to debug runtime |
---|
2606 | # "y" when building debug-python variants |
---|
2607 | # "d" when building debug variants |
---|
2608 | # "p" when building with stlport libraries |
---|
2609 | # "n" when building with stlport and using native iostreams |
---|
2610 | # |
---|
2611 | # The tag added is a <tag><prefix> to allow for additional tags. |
---|
2612 | # |
---|
2613 | rule common-variant-tag ( toolset variant : properties * ) |
---|
2614 | { |
---|
2615 | local tags = ; |
---|
2616 | |
---|
2617 | local thread-tag = ; |
---|
2618 | if <threading>multi in $(properties) { thread-tag = mt ; } |
---|
2619 | |
---|
2620 | local runtime-tag = ; |
---|
2621 | if <runtime-link>static in $(properties) { runtime-tag += s ; } |
---|
2622 | if <runtime-build>debug in $(properties) { runtime-tag += g ; } |
---|
2623 | if [ MATCH .*(debug-python).* : $(variant) ] { runtime-tag += y ; } |
---|
2624 | else { if [ MATCH .*(debug).* : $(variant) ] { runtime-tag += d ; } } |
---|
2625 | if [ MATCH .*(stlp).* : $(toolset) ] || |
---|
2626 | [ MATCH .*(stlp).* : $(properties:G) ] |
---|
2627 | { runtime-tag += p ; } |
---|
2628 | if <stlport-iostream>off in $(properties) { runtime-tag += n ; } |
---|
2629 | |
---|
2630 | local toolset-tag = ; |
---|
2631 | if ! $(gUNVERSIONED_VARIANT_TAG) |
---|
2632 | { |
---|
2633 | local include-minor-version = YES ; |
---|
2634 | switch $(toolset) |
---|
2635 | { |
---|
2636 | case borland* : toolset-tag += bcb ; |
---|
2637 | case como* : toolset-tag += como ; |
---|
2638 | case cwpro8* : toolset-tag += cw 8 ; |
---|
2639 | case cwpro9* : toolset-tag += cw 9 ; |
---|
2640 | case cw-* : toolset-tag += cw ; include-minor-version = ; |
---|
2641 | case darwin* : toolset-tag += ; |
---|
2642 | case edg* : toolset-tag += edg ; |
---|
2643 | case gcc* : toolset-tag += gcc ; |
---|
2644 | case intel-linux* : toolset-tag += il ; |
---|
2645 | case intel-win32* : toolset-tag += iw ; |
---|
2646 | case kcc* : toolset-tag += kcc ; |
---|
2647 | case kylix* : toolset-tag += bck ; |
---|
2648 | case metrowerks* : toolset-tag += cw ; |
---|
2649 | case mingw* : toolset-tag += mgw ; |
---|
2650 | case mipspro* : toolset-tag += mp ; |
---|
2651 | case msvc* : toolset-tag += vc 6 ; |
---|
2652 | case sunpro* : toolset-tag += sw ; |
---|
2653 | case tru64cxx* : toolset-tag += tru ; |
---|
2654 | case vacpp* : toolset-tag += xlc ; |
---|
2655 | case vc[678][_]* : |
---|
2656 | { |
---|
2657 | toolset-tag += vc ; |
---|
2658 | toolset-tag += [ MATCH "vc([678])[_]([0123456789]*)" : $(toolset) ] ; |
---|
2659 | } |
---|
2660 | case vc[678]* : |
---|
2661 | { |
---|
2662 | toolset-tag += vc ; |
---|
2663 | toolset-tag += [ MATCH "vc([678])" : $(toolset) ] ; |
---|
2664 | } |
---|
2665 | case * : |
---|
2666 | toolset-tag += [ MATCH "^([^-]*)" : $(toolset) ] ; |
---|
2667 | } |
---|
2668 | if $(include-minor-version) |
---|
2669 | { |
---|
2670 | toolset-tag += [ MATCH "[-]([0123456789]+)[_.]([0123456789]*)" : $(toolset) ] ; |
---|
2671 | } |
---|
2672 | else |
---|
2673 | { |
---|
2674 | toolset-tag += [ MATCH "[-]([0123456789]+)[_.][0123456789]*" : $(toolset) ] ; |
---|
2675 | } |
---|
2676 | |
---|
2677 | # boost/config/auto_link.hpp expects toolset tags that do not always |
---|
2678 | # match the above algorithm for MSVC 6.x and 7.0. |
---|
2679 | # |
---|
2680 | switch $(toolset-tag:J=) |
---|
2681 | { |
---|
2682 | case vc6* : toolset-tag = vc 6 ; |
---|
2683 | case vc70 : toolset-tag = vc 7 ; |
---|
2684 | } |
---|
2685 | } |
---|
2686 | |
---|
2687 | local version-tag = ; |
---|
2688 | if ! $(gUNVERSIONED_VARIANT_TAG) |
---|
2689 | { |
---|
2690 | local version-number = [ get-values <version> : $(properties) ] ; |
---|
2691 | version-number ?= $(BOOST_VERSION) ; |
---|
2692 | version-tag = [ MATCH "^([^.]+)[.]([^.]+)[.]([^.]+)" : $(version-number[1]) ] ; |
---|
2693 | if $(version-tag[3]) = 0 |
---|
2694 | { |
---|
2695 | version-tag = $(version-tag[1-2]) ; |
---|
2696 | } |
---|
2697 | version-tag = $(version-tag:J="_") ; |
---|
2698 | } |
---|
2699 | |
---|
2700 | tags += $(toolset-tag:J=) ; |
---|
2701 | tags += $(thread-tag:J=) ; |
---|
2702 | tags += $(runtime-tag:J=) ; |
---|
2703 | tags += $(version-tag) ; |
---|
2704 | |
---|
2705 | if $(tags) |
---|
2706 | { |
---|
2707 | return $(properties) <*><*><tag><prefix>-$(tags:J=-) ; |
---|
2708 | } |
---|
2709 | else |
---|
2710 | { |
---|
2711 | return $(properties) ; |
---|
2712 | } |
---|
2713 | } |
---|
2714 | |
---|
2715 | # Recursive version of GLOB. Builds the glob of files while |
---|
2716 | # also searching in the subdirectories of the given root. |
---|
2717 | # |
---|
2718 | rule glob-tree ( root : patterns * ) |
---|
2719 | { |
---|
2720 | local e ; |
---|
2721 | local f = [ GLOB $(root) : $(patterns) ] ; |
---|
2722 | local files ; |
---|
2723 | for e in $(f) |
---|
2724 | { |
---|
2725 | if $(e:D=) != CVS { files += $(e) ; } |
---|
2726 | } |
---|
2727 | local d = [ difference [ GLOB $(root) : * ] : $(files) ] ; |
---|
2728 | for e in $(d) |
---|
2729 | { |
---|
2730 | if ! ( $(e:D=) in . .. ) { files += [ glob-tree $(e) : $(patterns) ] ; } |
---|
2731 | } |
---|
2732 | return $(files) ; |
---|
2733 | } |
---|
2734 | |
---|
2735 | rule unless ( test * : no-value * : yes-value * ) |
---|
2736 | { if ! $(test) { return $(no-value) ; } else { return $(yes-value) ; } } |
---|
2737 | |
---|
2738 | rule cond ( test * : yes-value * : no-value * ) |
---|
2739 | { if $(test) { return $(yes-value) ; } else { return $(no-value) ; } } |
---|
2740 | |
---|
2741 | # If the toolset matches the given regex pattern, modify the |
---|
2742 | # subvariant-path and properties for static linking |
---|
2743 | rule force-NT-static-link ( pattern : toolset : subvariant-path properties * ) |
---|
2744 | { |
---|
2745 | if $(NT) && [ MATCH $(pattern) : $(toolset) ] |
---|
2746 | { |
---|
2747 | properties = [ impose-requirements $(properties) : |
---|
2748 | <runtime-link>static ] ; |
---|
2749 | } |
---|
2750 | |
---|
2751 | return $(subvariant-path) $(properties) ; |
---|
2752 | } |
---|
2753 | |
---|
2754 | # Stick this rule name in your requirements if you are building code |
---|
2755 | # which requires locale support. It handles the metrowerks-specific |
---|
2756 | # case that locale support demands the static version of the runtime |
---|
2757 | # library. |
---|
2758 | rule std::locale-support ( toolset variant : subvariant-path properties * ) |
---|
2759 | { |
---|
2760 | return [ |
---|
2761 | force-NT-static-link .*(cw-8).* |
---|
2762 | : $(toolset) : $(subvariant-path) $(properties) |
---|
2763 | ] ; |
---|
2764 | } |
---|
2765 | |
---|
2766 | # Stick this rule name in your requirements if you are building code |
---|
2767 | # which requires facet support. It handles the intel-win32-specific |
---|
2768 | # case that facet support seems to demand the static version of the |
---|
2769 | # runtime library. |
---|
2770 | rule std::facet-support ( toolset variant : subvariant-path properties * ) |
---|
2771 | { |
---|
2772 | return [ |
---|
2773 | force-NT-static-link .*(intel).* |
---|
2774 | : $(toolset) : $(subvariant-path) $(properties) |
---|
2775 | ] ; |
---|
2776 | } |
---|
2777 | |
---|
2778 | # load the specified modules if they haven't been loaded already. If |
---|
2779 | # the module has no suffix, ".jam" is appended. If the module name is |
---|
2780 | # prepended with a path, it is sought in that location relative to the |
---|
2781 | # current Jamfile, otherwise it is sought in BOOST_BUILD_PATH. |
---|
2782 | rule import ( modules + ) |
---|
2783 | { |
---|
2784 | for local name in $(modules) |
---|
2785 | { |
---|
2786 | local search = $(BOOST_BUILD_PATH) ; # search here |
---|
2787 | local n = $(name:D=) ; # for this basename |
---|
2788 | if ! $(n:S) |
---|
2789 | { |
---|
2790 | n = $(n).jam ; |
---|
2791 | } |
---|
2792 | |
---|
2793 | # if a directory was specified |
---|
2794 | local d = $(name:D) ; |
---|
2795 | if $(d) |
---|
2796 | { |
---|
2797 | # Normalize the path relative to the invocation directory. |
---|
2798 | n = [ root-paths $(n) : $(d:R=$(SUBDIR)) ] ; |
---|
2799 | n = [ root-paths $(n) : [ PWD ] ] ; |
---|
2800 | search = ; # no searching; the path was specified. |
---|
2801 | } |
---|
2802 | |
---|
2803 | SEARCH on $(n) = $(search) ; |
---|
2804 | |
---|
2805 | if ! $($(n).included) |
---|
2806 | { |
---|
2807 | include $(n) ; |
---|
2808 | $(n).included = true ; |
---|
2809 | } |
---|
2810 | } |
---|
2811 | } |
---|
2812 | |
---|
2813 | # Declare a project's installable sources (raw sources or built targets) |
---|
2814 | # |
---|
2815 | rule install ( |
---|
2816 | name # The name to refer to these set of targets/sources. |
---|
2817 | type # The type of targets/sources, and therefore their install location. |
---|
2818 | : sources + # The targets and sources to make available for installation. |
---|
2819 | : options * |
---|
2820 | ) |
---|
2821 | { |
---|
2822 | if $(gINSTALL_SOURCES) |
---|
2823 | { |
---|
2824 | local _include_ ; |
---|
2825 | if $(gINSTALL_INCLUSIONS) |
---|
2826 | { |
---|
2827 | if $(name) in $(gINSTALL_INCLUSIONS) |
---|
2828 | { |
---|
2829 | _include_ = true ; |
---|
2830 | } |
---|
2831 | } |
---|
2832 | else if ! $(name) in $(gINSTALL_EXCLUSIONS) |
---|
2833 | { |
---|
2834 | _include_ = true ; |
---|
2835 | } |
---|
2836 | if $(_include_) |
---|
2837 | { |
---|
2838 | local result ; |
---|
2839 | for local source in $(sources) |
---|
2840 | { |
---|
2841 | result += [ target-path-of $(source) ] ; |
---|
2842 | } |
---|
2843 | if ! $(result) in $(gINSTALL_SOURCES($(type))) |
---|
2844 | { |
---|
2845 | gINSTALL_SOURCES($(type)) += $(result) ; |
---|
2846 | } |
---|
2847 | return $(result) ; |
---|
2848 | } |
---|
2849 | } |
---|
2850 | } |
---|
2851 | |
---|
2852 | # |
---|
2853 | rule install-subinclude ( jamfiles + : options * ) |
---|
2854 | { |
---|
2855 | local gINSTALL_SOURCES = TRUE ; |
---|
2856 | local gIN_LIB_INCLUDE = TRUE ; |
---|
2857 | local gINSTALL_EXCLUSIONS = [ get-values <exclude> : $(options) ] ; |
---|
2858 | local gINSTALL_INCLUSIONS = [ get-values <include> : $(options) ] ; |
---|
2859 | |
---|
2860 | for local jamfile in $(jamfiles) |
---|
2861 | { |
---|
2862 | local sub-jamfile = [ relative-path $(jamfile) ] ; |
---|
2863 | dependent-include $(sub-jamfile) ; |
---|
2864 | } |
---|
2865 | } |
---|
2866 | |
---|
2867 | # get project installation sources of a given type |
---|
2868 | rule install-sources ( type ) |
---|
2869 | { |
---|
2870 | return $(gINSTALL_SOURCES($(type))) ; |
---|
2871 | } |
---|
2872 | |
---|
2873 | rule common-names ( ) |
---|
2874 | { |
---|
2875 | return common-variant-tag ; |
---|
2876 | } |
---|
2877 | rule common-stage-tag ( toolset variant : subvariant-path properties * ) |
---|
2878 | { |
---|
2879 | return [ common-variant-tag $(toolset) $(variant) : $(subvariant-path) $(properties) ] ; |
---|
2880 | } |
---|
2881 | |
---|
2882 | # Enforces toolset level requirements. This is added to all targets. |
---|
2883 | rule toolset::requirements ( toolset variant : subvariant-path properties * ) |
---|
2884 | { |
---|
2885 | local requirements = ; |
---|
2886 | switch $(toolset) |
---|
2887 | { |
---|
2888 | case cwpro8* : |
---|
2889 | { |
---|
2890 | # dynamic runtime only comes in the multi-threading flavor |
---|
2891 | if <runtime-link>dynamic in $(properties) { requirements += <threading>multi ; } |
---|
2892 | } |
---|
2893 | case cwpro9* : |
---|
2894 | { |
---|
2895 | # dynamic runtime only comes in the multi-threading flavor |
---|
2896 | if <runtime-link>dynamic in $(properties) { requirements += <threading>multi ; } |
---|
2897 | } |
---|
2898 | case cw* : |
---|
2899 | { |
---|
2900 | # dynamic runtime only comes in the multi-threading flavor |
---|
2901 | if <runtime-link>dynamic in $(properties) { requirements += <threading>multi ; } |
---|
2902 | } |
---|
2903 | case msvc* : |
---|
2904 | { |
---|
2905 | # dynamic runtime only comes in the multi-threading flavor |
---|
2906 | if <runtime-link>dynamic in $(properties) { requirements += <threading>multi ; } |
---|
2907 | if [ MATCH .*(stlp).* : $(toolset) ] || |
---|
2908 | [ MATCH .*(stlp).* : $(properties:G) ] |
---|
2909 | { |
---|
2910 | # STLPort doesn't have any single-threaded builds, so we're going |
---|
2911 | # to force all such targets to be built with multithread support. |
---|
2912 | # This is essentially a usage-requirement on the stlport library. |
---|
2913 | requirements += <threading>multi ; |
---|
2914 | } |
---|
2915 | } |
---|
2916 | case vc* : |
---|
2917 | { |
---|
2918 | # dynamic runtime only comes in the multi-threading flavor |
---|
2919 | if <runtime-link>dynamic in $(properties) { requirements += <threading>multi ; } |
---|
2920 | if [ MATCH .*(stlp).* : $(toolset) ] || |
---|
2921 | [ MATCH .*(stlp).* : $(properties:G) ] |
---|
2922 | { |
---|
2923 | # STLPort doesn't have any single-threaded builds, so we're going |
---|
2924 | # to force all such targets to be built with multithread support. |
---|
2925 | # This is essentially a usage-requirement on the stlport library. |
---|
2926 | requirements += <threading>multi ; |
---|
2927 | # STLPort doesn't support <stlport-iostream>off with vc7 and vc8. |
---|
2928 | # This is essentially a usage-requirement on the stlport library. |
---|
2929 | switch $(toolset) |
---|
2930 | { |
---|
2931 | case vc7* : requirements += <stlport-iostream>on ; |
---|
2932 | case vc8* : requirements += <stlport-iostream>on ; |
---|
2933 | case vc-7* : requirements += <stlport-iostream>on ; |
---|
2934 | case vc-8* : requirements += <stlport-iostream>on ; |
---|
2935 | } |
---|
2936 | } |
---|
2937 | # vc8 doesn't have any single threaded runtime |
---|
2938 | switch $(toolset) |
---|
2939 | { |
---|
2940 | case vc-8* : requirements += <threading>multi ; |
---|
2941 | } |
---|
2942 | } |
---|
2943 | case intel-win32* : |
---|
2944 | { |
---|
2945 | # dynamic runtime only comes in the multi-threading flavor |
---|
2946 | if <runtime-link>dynamic in $(properties) { requirements += <threading>multi ; } |
---|
2947 | } |
---|
2948 | case iw* : |
---|
2949 | { |
---|
2950 | # dynamic runtime only comes in the multi-threading flavor |
---|
2951 | if <runtime-link>dynamic in $(properties) { requirements += <threading>multi ; } |
---|
2952 | } |
---|
2953 | } |
---|
2954 | if <stlport-version>5.0 in $(properties) |
---|
2955 | { |
---|
2956 | # STLPort-5 doesn't have any single-threaded builds, so we're going |
---|
2957 | # to force all such targets to be built with multithread support. |
---|
2958 | # This is essentially a usage-requirement on the stlport library. |
---|
2959 | requirements += <threading>multi ; |
---|
2960 | } |
---|
2961 | return $(subvariant-path) [ impose-requirements $(properties) : $(requirements) ] ; |
---|
2962 | } |
---|
2963 | |
---|
2964 | # Utility, to impose a subset of requirements onto a property set. |
---|
2965 | rule impose-requirements ( properties * : requirements * ) |
---|
2966 | { |
---|
2967 | local requirements = [ unique $(requirements) ] ; |
---|
2968 | local free-feature-requirements = [ segregate-free-properties properties ] ; |
---|
2969 | properties = |
---|
2970 | [ sort |
---|
2971 | [ difference $(properties) : [ get-properties $(requirements:G) : $(properties) ] ] |
---|
2972 | $(requirements) |
---|
2973 | ] |
---|
2974 | $(free-feature-requirements) |
---|
2975 | ; |
---|
2976 | return $(properties) ; |
---|
2977 | } |
---|