]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/tools/build/src/build/virtual-target.jam
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / tools / build / src / build / virtual-target.jam
CommitLineData
7c673cae
FG
1# Copyright 2003 Dave Abrahams
2# Copyright 2005, 2006 Rene Rivera
3# Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
4# Distributed under the Boost Software License, Version 1.0.
5# (See accompanying file LICENSE_1_0.txt or copy at
6# http://www.boost.org/LICENSE_1_0.txt)
7
8# Implements virtual targets, which correspond to actual files created during a
9# build, but are not yet targets in Jam sense. They are needed, for example,
10# when searching for possible transformation sequences, when it is not yet known
11# whether a particular target should be created at all.
12#
13# +--------------------------+
14# | virtual-target |
15# +==========================+
16# | actualize |
17# +--------------------------+
18# | actualize-action() = 0 |
19# | actualize-location() = 0 |
20# +----------------+---------+
21# |
22# ^
23# / \
24# +-+-+
25# |
26# +---------------------+ +-------+--------------+
27# | action | | abstract-file-target |
28# +=====================| * +======================+
29# | action-name | +--+ action |
30# | properties | | +----------------------+
31# +---------------------+--+ | actualize-action() |
32# | actualize() |0..1 +-----------+----------+
33# | path() | |
34# | adjust-properties() | sources |
35# | actualize-sources() | targets |
36# +------+--------------+ ^
37# | / \
38# ^ +-+-+
39# / \ |
40# +-+-+ +-------------+-------------+
41# | | |
42# | +------+---------------+ +--------+-------------+
43# | | file-target | | searched-lib-target |
44# | +======================+ +======================+
45# | | actualize-location() | | actualize-location() |
46# | +----------------------+ +----------------------+
47# |
48# +-+------------------------------+
49# | |
50# +----+----------------+ +---------+-----------+
51# | compile-action | | link-action |
52# +=====================+ +=====================+
53# | adjust-properties() | | adjust-properties() |
54# +---------------------+ | actualize-sources() |
55# +---------------------+
56#
57# The 'compile-action' and 'link-action' classes are not defined here but in
58# builtin.jam modules. They are shown in the diagram to give the big picture.
59
60import "class" : new ;
11fdf7f2 61import feature ;
7c673cae 62import path ;
11fdf7f2 63import property-set ;
7c673cae
FG
64import sequence ;
65import set ;
11fdf7f2 66import toolset ;
7c673cae
FG
67import type ;
68import utility ;
69
70
71# Models a potential target. It can be converted into a Jam target and used in
72# building, if needed. However, it can be also dropped, which allows us to
73# search for different transformations and select only one.
74#
75class virtual-target
76{
77 import scanner ;
78 import sequence ;
79 import utility ;
80 import virtual-target ;
81
82 rule __init__ (
83 name # Target/project name.
84 : project # Project to which this target belongs.
85 )
86 {
87 self.name = $(name) ;
88 self.project = $(project) ;
89 self.dependencies = ;
90 }
91
92 # Name of this target.
93 #
94 rule name ( )
95 {
96 return $(self.name) ;
97 }
98
99 # Project of this target.
100 #
101 rule project ( )
102 {
103 return $(self.project) ;
104 }
105
106 # Adds additional 'virtual-target' instances this one depends on.
107 #
108 rule depends ( d + )
109 {
110 self.dependencies = [ sequence.merge $(self.dependencies) :
111 [ sequence.insertion-sort $(d) ] ] ;
112 }
113
114 rule dependencies ( )
115 {
116 return $(self.dependencies) ;
117 }
118
119 rule always ( )
120 {
121 .always = 1 ;
122 }
123
11fdf7f2
TL
124 rule fail-expected ( )
125 {
126 .fail-expected = 1 ;
127 }
128
7c673cae
FG
129 # Generates all the actual targets and sets up build actions for this
130 # target.
131 #
132 # If 'scanner' is specified, creates an additional target with the same
133 # location as the actual target, which will depend on the actual target and
134 # be associated with a 'scanner'. That additional target is returned. See
135 # the docs (#dependency_scanning) for rationale. Target must correspond to a
136 # file if 'scanner' is specified.
137 #
138 # If scanner is not specified then the actual target is returned.
139 #
140 rule actualize ( scanner ? )
141 {
142 local actual-name = [ actualize-no-scanner ] ;
143
144 if $(.always)
145 {
146 ALWAYS $(actual-name) ;
147 }
148
11fdf7f2
TL
149 if $(.fail-expected)
150 {
151 FAIL_EXPECTED $(actual-name) ;
152 }
153
7c673cae
FG
154 if ! $(scanner)
155 {
156 return $(actual-name) ;
157 }
158 else
159 {
160 # Add the scanner instance to the grist for name.
161 local g = [ sequence.join [ utility.ungrist $(actual-name:G) ]
162 $(scanner) : - ] ;
163 local name = $(actual-name:G=$(g)) ;
164
165 if ! $(self.made.$(scanner))
166 {
167 self.made.$(scanner) = true ;
168 actualize-location $(name) ;
169 scanner.install $(scanner) : $(name) ;
170 }
171 return $(name) ;
172 }
173 }
174
175# private: (overridables)
176
177 # Sets up build actions for 'target'. Should call appropriate rules and set
178 # target variables.
179 #
180 rule actualize-action ( target )
181 {
182 import errors : error : errors.error ;
183 errors.error "method should be defined in derived classes" ;
184 }
185
186 # Sets up variables on 'target' which specify its location.
187 #
188 rule actualize-location ( target )
189 {
190 import errors : error : errors.error ;
191 errors.error "method should be defined in derived classes" ;
192 }
193
194 # If the target is a generated one, returns the path where it will be
195 # generated. Otherwise, returns an empty list.
196 #
197 rule path ( )
198 {
199 import errors : error : errors.error ;
200 errors.error "method should be defined in derived classes" ;
201 }
202
203 # Returns the actual target name to be used in case when no scanner is
204 # involved.
205 #
206 rule actual-name ( )
207 {
208 import errors : error : errors.error ;
209 errors.error "method should be defined in derived classes" ;
210 }
211
11fdf7f2
TL
212 # Returns additional properties that are relevant for this target
213 # beyond those required by the action.
214 #
215 rule relevant ( )
216 {
217 return [ property-set.empty ] ;
218 }
219
7c673cae
FG
220# implementation
221 rule actualize-no-scanner ( )
222 {
223 # In fact, we just need to merge virtual-target with
224 # abstract-file-target as the latter is the only class derived from the
225 # former. But that has been left for later.
226
227 import errors : error : errors.error ;
228 errors.error "method should be defined in derived classes" ;
229 }
230}
231
232
233# Target corresponding to a file. The exact mapping for file is not yet
234# specified in this class. (TODO: Actually, the class name could be better...)
235#
236# May be a source file (when no action is specified) or a derived file
237# (otherwise).
238#
239# The target's grist is a concatenation of its project's location, action
240# properties (for derived targets) and, optionally, value identifying the main
241# target.
242#
243class abstract-file-target : virtual-target
244{
245 import project ;
246 import regex ;
247 import sequence ;
248 import path ;
249 import type ;
250 import property-set ;
251 import indirect ;
252
253 rule __init__ (
254 name # Target's name.
255 exact ? # If non-empty, the name is exactly the name created file
256 # should have. Otherwise, the '__init__' method will add a
257 # suffix obtained from 'type' by calling
258 # 'type.generated-target-suffix'.
259 : type ? # Target's type.
260 : project
261 : action ?
262 )
263 {
264 virtual-target.__init__ $(name) : $(project) ;
265
266 self.type = $(type) ;
267 self.action = $(action) ;
268 if $(action)
269 {
270 $(action).add-targets $(__name__) ;
271
272 if $(self.type) && ! $(exact)
273 {
274 _adjust-name $(name) ;
275 }
276 }
277 }
278
279 rule type ( )
280 {
281 return $(self.type) ;
282 }
283
284 # Sets the path. When generating target name, it will override any path
285 # computation from properties.
286 #
287 rule set-path ( path )
288 {
289 self.path = [ path.native $(path) ] ;
290 }
291
292 # Returns the currently set action.
293 #
294 rule action ( )
295 {
296 return $(self.action) ;
297 }
298
299 # Sets/gets the 'root' flag. Target is root if it directly corresponds to
300 # some variant of a main target.
301 #
302 rule root ( set ? )
303 {
304 if $(set)
305 {
306 self.root = true ;
307 }
308 return $(self.root) ;
309 }
310
311 # Gets or sets the subvariant which created this target. Subvariant is set
312 # when target is brought into existance and is never changed after that. In
313 # particular, if a target is shared by multiple subvariants, only the first
314 # one is stored.
315 #
316 rule creating-subvariant ( s ? # If specified, specifies the value to set,
317 # which should be a 'subvariant' class
318 # instance.
319 )
320 {
321 if $(s) && ! $(self.creating-subvariant)
322 {
323 self.creating-subvariant = $(s) ;
324 }
325 return $(self.creating-subvariant) ;
326 }
327
328 rule actualize-action ( target )
329 {
330 if $(self.action)
331 {
332 $(self.action).actualize ;
333 }
334 }
335
336 # Return a human-readable representation of this target. If this target has
337 # an action, that is:
338 #
339 # { <action-name>-<self.name>.<self.type> <action-sources>... }
340 #
341 # otherwise, it is:
342 #
343 # { <self.name>.<self.type> }
344 #
345 rule str ( )
346 {
347 local action = [ action ] ;
348 local name-dot-type = [ sequence.join $(self.name) "." $(self.type) ] ;
349
350 if $(action)
351 {
352 local sources = [ $(action).sources ] ;
353 local action-name = [ $(action).action-name ] ;
354
355 local ss ;
356 for local s in $(sources)
357 {
358 ss += [ $(s).str ] ;
359 }
360
361 return "{" $(action-name)-$(name-dot-type) $(ss) "}" ;
362 }
363 else
364 {
365 return "{" $(name-dot-type) "}" ;
366 }
367 }
368
369 rule less ( a )
370 {
371 if [ str ] < [ $(a).str ]
372 {
373 return true ;
374 }
375 }
376
377 rule equal ( a )
378 {
379 if [ str ] = [ $(a).str ]
380 {
381 return true ;
382 }
383 }
384
385# private:
386 rule actual-name ( )
387 {
388 if ! $(self.actual-name)
389 {
390 local grist = [ grist ] ;
391 local basename = [ path.native $(self.name) ] ;
392 self.actual-name = <$(grist)>$(basename) ;
393 }
394 return $(self.actual-name) ;
395 }
396
397 # Helper to 'actual-name', above. Computes a unique prefix used to
398 # distinguish this target from other targets with the same name creating
399 # different files.
400 #
401 rule grist ( )
402 {
403 # Depending on target, there may be different approaches to generating
404 # unique prefixes. We generate prefixes in the form:
405 # <one letter approach code> <the actual prefix>
406 local path = [ path ] ;
407 if $(path)
408 {
409 # The target will be generated to a known path. Just use the path
410 # for identification, since path is as unique as it can get.
411 return p$(path) ;
412 }
413 else
414 {
415 # File is either source, which will be searched for, or is not a
416 # file at all. Use the location of project for distinguishing.
417 local project-location = [ $(self.project).get location ] ;
418 local location-grist = [ sequence.join [ regex.split
419 $(project-location) "/" ] : "!" ] ;
420
421 if $(self.action)
422 {
423 local ps = [ $(self.action).properties ] ;
424 local property-grist = [ $(ps).as-path ] ;
425 # 'property-grist' can be empty when 'ps' is an empty property
426 # set.
427 if $(property-grist)
428 {
429 location-grist = $(location-grist)/$(property-grist) ;
430 }
431 }
432
433 return l$(location-grist) ;
434 }
435 }
436
437 # Given the target name specified in constructor, returns the name which
438 # should be really used, by looking at the <tag> properties. Tag properties
439 # need to be specified as <tag>@rule-name. This makes Boost Build call the
440 # specified rule with the target name, type and properties to get the new
441 # name. If no <tag> property is specified or the rule specified by <tag>
442 # returns nothing, returns the result of calling
443 # virtual-target.add-prefix-and-suffix.
444 #
445 rule _adjust-name ( specified-name )
446 {
447 local ps ;
448 if $(self.action)
449 {
450 ps = [ $(self.action).properties ] ;
451 }
452 else
453 {
454 ps = [ property-set.empty ] ;
455 }
456
457 # Add this target object for use in getting additional information
458 # when tagging.
459 ps = [ property-set.create [ $(ps).raw ] <target>$(__name__) ] ;
460
461 local tag = [ $(ps).get <tag> ] ;
462
463 if $(tag)
464 {
465 local rule-name = [ MATCH ^@(.*) : $(tag) ] ;
466 if $(rule-name)
467 {
468 if $(tag[2])
469 {
470 import errors : error : errors.error ;
471 errors.error <tag>@rulename is present but is not the only
472 <tag> feature. ;
473 }
474
475 self.name = [ indirect.call $(rule-name) $(specified-name)
476 : $(self.type) : $(ps) ] ;
477 }
478 else
479 {
480 import errors : error : errors.error ;
481 errors.error <tag> property value must be '@rule-name'. ;
482 }
483 }
484
485 # If there is no tag or the tag rule returned nothing.
486 if ! $(tag) || ! $(self.name)
487 {
488 self.name = [ virtual-target.add-prefix-and-suffix $(specified-name)
489 : $(self.type) : $(ps) ] ;
490 }
491 }
492
493 rule actualize-no-scanner ( )
494 {
495 local name = [ actual-name ] ;
496
497 # Do anything only on the first invocation.
498 if ! $(self.made-no-scanner)
499 {
500 self.made-no-scanner = true ;
501
502 if $(self.action)
503 {
504 # For non-derived target, we do not care if there are several
505 # virtual targets that refer to the same name. One case when
506 # this is unavoidable is when the file name is main.cpp and two
507 # targets have types CPP (for compiling) and MOCCABLE_CPP (for
508 # conversion to H via Qt tools).
509 virtual-target.register-actual-name $(name) : $(__name__) ;
510 }
511
512 for local i in $(self.dependencies)
513 {
514 DEPENDS $(name) : [ $(i).actualize ] ;
515 }
516
517 actualize-location $(name) ;
518 actualize-action $(name) ;
519 }
520 return $(name) ;
521 }
522}
523
524
525# Appends the suffix appropriate to 'type/property-set' combination to the
526# specified name and returns the result.
527#
528rule add-prefix-and-suffix ( specified-name : type ? : property-set )
529{
530 local suffix = [ type.generated-target-suffix $(type) : $(property-set) ] ;
531
532 # Handle suffixes for which no leading dot is desired. Those are specified
533 # by enclosing them in <...>. Needed by python so it can create "_d.so"
534 # extensions, for example.
535 if $(suffix:G)
536 {
537 suffix = [ utility.ungrist $(suffix) ] ;
538 }
539 else
540 {
541 suffix = .$(suffix) ;
542 }
543
544 local prefix = [ type.generated-target-prefix $(type) : $(property-set) ] ;
545
546 if [ MATCH ^($(prefix)) : $(specified-name) ]
547 {
548 prefix = ;
549 }
550 return $(prefix:E="")$(specified-name)$(suffix:E="") ;
551}
552
553
554# File targets with explicitly known location.
555#
556# The file path is determined as
557# * Value passed to the 'set-path' method, if any.
558# * For derived files, project's build dir, joined with components that
559# describe action properties. If free properties are not equal to the
560# project's reference properties an element with the name of the main
561# target is added.
562# * For source files, project's source dir.
563#
564# The file suffix is determined as:
565# * The value passed to the 'suffix' method, if any.
566# * The suffix corresponding to the target's type.
567#
568class file-target : abstract-file-target
569{
570 import "class" : new ;
571 import common ;
572
573 rule __init__ (
574 name exact ?
575 : type ? # Optional type for this target.
576 : project
577 : action ?
578 : path ?
579 )
580 {
581 abstract-file-target.__init__ $(name) $(exact) : $(type) : $(project) :
582 $(action) ;
583
584 self.path = $(path) ;
585 }
586
587 rule clone-with-different-type ( new-type )
588 {
589 return [ new file-target $(self.name) exact : $(new-type) :
590 $(self.project) : $(self.action) : $(self.path) ] ;
591 }
592
593 rule actualize-location ( target )
594 {
595 # Scanner targets are always bound to already existing files in already
596 # existing folder. They need to be marked as depending on their base
597 # target (i.e. the target being scanned) but, unlike regular
598 # dependencies set up by the DEPENDS rule, they must not depend on any
599 # targets already marked as included by the base target. Otherwise such
600 # an included file being newer than the file being scanned would cause
601 # the scanner target to be updated, further causing any target depending
602 # on that scanner target to be rebuilt. This is the exact relationship
603 # as set up by Boost Jam's SEARCH binding method (needed to support
604 # searching for generated targets) so we want to bind scanner targets
605 # using this method instead of explicitly specifying their location
606 # using LOCATE.
607 #
608 # FIXME: We recognize scanner targets by their given name being
609 # different from this target's actual name. This is a hack and should be
610 # cleaned up by reorganizing who knows about scanners in the
611 # virtual-target/abstract-file-target/file-target/notfile-target/
612 # searched-lib-target/... class hierarchy.
613 local is-scanner-target ;
614 if $(target) != [ actual-name ]
615 {
616 is-scanner-target = true ;
617 }
618
619 if $(self.action) && ! $(is-scanner-target)
620 {
621 # This is a derived file.
622 local path = [ path ] ;
623 LOCATE on $(target) = $(path) ;
624
625 # Make sure the path exists.
626 DEPENDS $(target) : $(path) ;
627 common.MkDir $(path) ;
628
629 # It is possible that the target name includes a directory too, for
630 # example when installing headers. Create that directory.
631 if $(target:D)
632 {
633 local d = $(target:D) ;
634 d = $(d:R=$(path)) ;
635 DEPENDS $(target) : $(d) ;
636 common.MkDir $(d) ;
637 }
638
639 # For a real file target, we create a fake target depending on the
640 # real target. This allows us to run
641 #
642 # b2 hello.o
643 #
644 # without trying to guess the name of the real target. Note that the
645 # target has no directory name and uses a special <e> grist.
646 #
647 # First, that means that "b2 hello.o" will build all known hello.o
648 # targets. Second, the <e> grist makes sure this target will not be
649 # confused with other targets, for example, if we have subdir 'test'
650 # with target 'test' in it that includes a 'test.o' file, then the
651 # target for directory will be just 'test' the target for test.o
652 # will be <ptest/bin/gcc/debug>test.o and the target we create below
653 # will be <e>test.o
654 DEPENDS $(target:G=e) : $(target) ;
655 # Allow b2 <path-to-file>/<file> to work. This will not catch all
656 # possible ways to refer to the path (relative/absolute, extra ".",
657 # various "..", but should help in obvious cases.
658 DEPENDS $(target:G=e:R=$(path)) : $(target) ;
659 }
660 else
661 {
662 SEARCH on $(target) = [ path.native $(self.path) ] ;
663 }
664 }
665
666 # Returns the directory for this target.
667 #
668 rule path ( )
669 {
670 if ! $(self.path)
671 {
672 if $(self.action)
673 {
674 local p = [ $(self.action).properties ] ;
675 local path,relative-to-build-dir = [ $(p).target-path ] ;
676 local path = $(path,relative-to-build-dir[1]) ;
677 local relative-to-build-dir = $(path,relative-to-build-dir[2]) ;
678
679 if $(relative-to-build-dir)
680 {
681 path = [ path.join [ $(self.project).build-dir ] $(path) ] ;
682 }
683
684 self.path = [ path.native $(path) ] ;
685 }
686 }
687 return $(self.path) ;
688 }
689}
690
691
692class notfile-target : abstract-file-target
693{
694 rule __init__ ( name : project : action ? )
695 {
696 abstract-file-target.__init__ $(name) : : $(project) : $(action) ;
697 }
698
699 # Returns nothing to indicate that the target's path is not known.
700 #
701 rule path ( )
702 {
703 return ;
704 }
705
706 rule actualize-location ( target )
707 {
708 NOTFILE $(target) ;
709 ALWAYS $(target) ;
710 # TEMPORARY $(target) ;
711 NOUPDATE $(target) ;
712 }
713}
714
715
716# Class representing an action. Both 'targets' and 'sources' should list
717# instances of 'virtual-target'. Action name should name a rule with this
718# prototype:
719# rule action-name ( targets + : sources * : properties * )
720# Targets and sources are passed as actual Jam targets. The rule may not
721# establish additional dependency relationships.
722#
723class action
724{
725 import "class" ;
726 import indirect ;
727 import path ;
728 import property-set ;
729 import set : difference ;
730 import toolset ;
731 import type ;
732
733 rule __init__ ( sources * : action-name + : property-set ? )
734 {
735 self.sources = $(sources) ;
736
737 self.action-name = [ indirect.make-qualified $(action-name) ] ;
738
739 if ! $(property-set)
740 {
741 property-set = [ property-set.empty ] ;
742 }
743
744 if ! [ class.is-instance $(property-set) ]
745 {
746 import errors : error : errors.error ;
747 errors.error "Property set instance required" ;
748 }
749
750 self.properties = $(property-set) ;
751 }
752
753 rule add-targets ( targets * )
754 {
755 self.targets += $(targets) ;
756 }
757
758 rule replace-targets ( old-targets * : new-targets * )
759 {
760 self.targets = [ set.difference $(self.targets) : $(old-targets) ] ;
761 self.targets += $(new-targets) ;
762 }
763
764 rule targets ( )
765 {
766 return $(self.targets) ;
767 }
768
769 rule sources ( )
770 {
771 return $(self.sources) ;
772 }
773
774 rule action-name ( )
775 {
776 return $(self.action-name) ;
777 }
778
779 rule properties ( )
780 {
781 return $(self.properties) ;
782 }
783
784 # Generates actual build instructions.
785 #
786 rule actualize ( )
787 {
788 if ! $(self.actualized)
789 {
790 self.actualized = true ;
791
792 local ps = [ properties ] ;
793 local properties = [ adjust-properties $(ps) ] ;
794
795 local actual-targets ;
796 for local i in [ targets ]
797 {
798 actual-targets += [ $(i).actualize ] ;
799 }
800
801 actualize-sources [ sources ] : $(properties) ;
802
803 DEPENDS $(actual-targets) : $(self.actual-sources)
804 $(self.dependency-only-sources) ;
805
806 # Action name can include additional rule arguments, which should
807 # not be passed to 'set-target-variables'.
808 toolset.set-target-variables
809 [ indirect.get-rule $(self.action-name[1]) ] $(actual-targets)
810 : $(properties) ;
811
812 # Reflect ourselves in a variable for the target. This allows
813 # looking up additional info for the action given the raw target.
814 # For example to debug or output action information from action
815 # rules.
816 .action on $(actual-targets) = $(__name__) ;
817
b32b8144
FG
818 #indirect.call $(self.action-name) $(actual-targets)
819 # : $(self.actual-sources) : [ $(properties).raw ] ;
820 execute $(self.action-name) $(actual-targets)
7c673cae
FG
821 : $(self.actual-sources) : [ $(properties).raw ] ;
822
823 # Since we set up the creating action here, we set up the action for
824 # cleaning up as well.
825 common.Clean clean-all : $(actual-targets) ;
826 }
827 }
828
829 # Helper for 'actualize-sources'. For each passed source, actualizes it with
830 # the appropriate scanner. Returns the actualized virtual targets.
831 #
832 rule actualize-source-type ( sources * : property-set )
833 {
834 local result = ;
835 for local i in $(sources)
836 {
837 local scanner ;
838 if [ $(i).type ]
839 {
840 scanner = [ type.get-scanner [ $(i).type ] : $(property-set) ] ;
841 }
842 result += [ $(i).actualize $(scanner) ] ;
843 }
844 return $(result) ;
845 }
846
847 # Creates actual Jam targets for sources. Initializes the following member
848 # variables:
849 # 'self.actual-sources' -- sources passed to the updating action.
850 # 'self.dependency-only-sources' -- sources marked as dependencies, but
851 # are not used otherwise.
852 #
853 # New values will be *appended* to the variables. They may be non-empty if
854 # caller wants it.
855 #
856 rule actualize-sources ( sources * : property-set )
857 {
858 local dependencies = [ $(self.properties).get <dependency> ] ;
859
860 self.dependency-only-sources +=
861 [ actualize-source-type $(dependencies) : $(property-set) ] ;
862 self.actual-sources +=
863 [ actualize-source-type $(sources) : $(property-set) ] ;
864
865 # This is used to help b2 find dependencies in generated headers and
866 # other main targets, e.g. in:
867 #
868 # make a.h : ....... ;
869 # exe hello : hello.cpp : <implicit-dependency>a.h ;
870 #
871 # For b2 to find the dependency the generated target must be
872 # actualized (i.e. have its Jam target constructed). In the above case,
873 # if we are building just hello ("b2 hello"), 'a.h' will not be
874 # actualized unless we do it here.
875 local implicit = [ $(self.properties).get <implicit-dependency> ] ;
876 for local i in $(implicit)
877 {
878 $(i:G=).actualize ;
879 }
880 }
881
882 # Determines real properties when trying to build with 'properties'. This is
883 # the last chance to fix properties, for example to adjust includes to get
884 # generated headers correctly. Default implementation simply returns its
885 # argument.
886 #
887 rule adjust-properties ( property-set )
888 {
889 return $(property-set) ;
890 }
b32b8144
FG
891
892 # Execute the action rule on the given targets, sources, and properties.
893 # Since this does the final call to the engine action rule this takes
894 # engine level targets and raw properties. One could override this, for
895 # example, to set additional variables on hte target that might be
896 # difficult to determine just using toolset flags.
897 # Note, you must call this base rule when overriding as otherwise the
898 # actions will not execute and the engine will not run commands.
899 #
900 rule execute ( action-name targets + : sources * : properties * )
901 {
902 indirect.call $(action-name) $(targets) : $(sources) : $(properties) ;
903 }
7c673cae
FG
904}
905
906
907# Action class which does nothing --- it produces the targets with specific
908# properties out of nowhere. It is needed to distinguish virtual targets with
909# different properties that are known to exist and have no actions which create
910# them.
911#
912class null-action : action
913{
914 rule __init__ ( property-set ? )
915 {
916 action.__init__ : .no-action : $(property-set) ;
917 }
918
919 rule actualize ( )
920 {
921 if ! $(self.actualized)
922 {
923 self.actualized = true ;
924 for local i in [ targets ]
925 {
926 $(i).actualize ;
927 }
928 }
929 }
930}
931
932
933# Class which acts exactly like 'action', except that its sources are not
934# scanned for dependencies.
935#
936class non-scanning-action : action
937{
938 rule __init__ ( sources * : action-name + : property-set ? )
939 {
940 action.__init__ $(sources) : $(action-name) : $(property-set) ;
941 }
942
943 rule actualize-source-type ( sources * : property-set )
944 {
945 local result ;
946 for local i in $(sources)
947 {
948 result += [ $(i).actualize ] ;
949 }
950 return $(result) ;
951 }
952}
953
954
955# Creates a virtual target with an appropriate name and type from 'file'. If a
956# target with that name in that project already exists, returns that already
957# created target.
958#
959# FIXME: a more correct way would be to compute the path to the file, based on
960# name and source location for the project, and use that path to determine if
961# the target has already been created. This logic should be shared with how we
962# usually find targets identified by a specific target id. It should also be
963# updated to work correctly when the file is specified using both relative and
964# absolute paths.
965#
966# TODO: passing a project with all virtual targets is starting to be annoying.
967#
968rule from-file ( file : file-loc : project )
969{
970 import type ; # Had to do this here to break a circular dependency.
971
972 # Check whether we already created a target corresponding to this file.
973 local path = [ path.root [ path.root $(file) $(file-loc) ] [ path.pwd ] ] ;
974
975 if $(.files.$(path))
976 {
977 return $(.files.$(path)) ;
978 }
979 else
980 {
981 local name = [ path.make $(file) ] ;
982 local type = [ type.type $(file) ] ;
983 local result ;
984
985 result = [ new file-target $(file) : $(type) : $(project) : :
986 $(file-loc) ] ;
987
988 .files.$(path) = $(result) ;
989 return $(result) ;
990 }
991}
992
993
994# Registers a new virtual target. Checks if there is already a registered target
995# with the same name, type, project and subvariant properties as well as the
996# same sources and equal action. If such target is found it is returned and a
997# new 'target' is not registered. Otherwise, 'target' is registered and
998# returned.
999#
1000rule register ( target )
1001{
1002 local signature = [ sequence.join [ $(target).path ] [ $(target).name ] : -
1003 ] ;
1004
1005 local result ;
1006 for local t in $(.cache.$(signature))
1007 {
1008 local a1 = [ $(t).action ] ;
1009 local a2 = [ $(target).action ] ;
1010
1011 if ! $(result)
1012 {
1013 if ! $(a1) && ! $(a2)
1014 {
1015 result = $(t) ;
1016 }
1017 else if $(a1) && $(a2) &&
1018 ( [ $(a1).action-name ] = [ $(a2).action-name ] ) &&
1019 ( [ $(a1).sources ] = [ $(a2).sources ] )
1020 {
1021 local ps1 = [ $(a1).properties ] ;
1022 local ps2 = [ $(a2).properties ] ;
11fdf7f2
TL
1023 local relevant = [ toolset.relevant [ $(a1).action-name ] ] ;
1024 relevant = [ $(relevant).add [ $(target).relevant ] ] ;
1025 local p1 = [ $(ps1).relevant $(relevant) ] ;
1026 local p2 = [ $(ps2).relevant $(relevant) ] ;
7c673cae
FG
1027 if $(p1) = $(p2)
1028 {
1029 result = $(t) ;
1030 }
1031 }
1032 }
1033 }
1034
1035 if ! $(result)
1036 {
1037 .cache.$(signature) += $(target) ;
1038 result = $(target) ;
1039 }
1040
1041 .recent-targets += $(result) ;
1042 .all-targets += $(result) ;
1043
1044 return $(result) ;
1045}
1046
1047
1048# Each target returned by 'register' is added to the .recent-targets list,
1049# returned by this function. This allows us to find all virtual targets created
1050# when building a specific main target, even those constructed only as
1051# intermediate targets.
1052#
1053rule recent-targets ( )
1054{
1055 return $(.recent-targets) ;
1056}
1057
1058
1059rule clear-recent-targets ( )
1060{
1061 .recent-targets = ;
1062}
1063
1064
1065# Returns all virtual targets ever created.
1066#
1067rule all-targets ( )
1068{
1069 return $(.all-targets) ;
1070}
1071
1072
1073# Returns all targets from 'targets' with types equal to 'type' or derived from
1074# it.
1075#
1076rule select-by-type ( type : targets * )
1077{
1078 local result ;
1079 for local t in $(targets)
1080 {
1081 if [ type.is-subtype [ $(t).type ] $(type) ]
1082 {
1083 result += $(t) ;
1084 }
1085 }
1086 return $(result) ;
1087}
1088
1089
1090rule register-actual-name ( actual-name : virtual-target )
1091{
1092 if $(.actual.$(actual-name))
1093 {
1094 local cs1 = [ $(.actual.$(actual-name)).creating-subvariant ] ;
1095 local cmt1-name ;
1096 if $(cs1)-is-defined
1097 {
1098 local cmt1 = [ $(cs1).main-target ] ;
1099 cmt1-name = [ $(cmt1).full-name ] ;
1100 }
1101 local cs2 = [ $(virtual-target).creating-subvariant ] ;
1102 local cmt2-name ;
1103 if $(cs2)-is-defined
1104 {
1105 local cmt2 = [ $(cs2).main-target ] ;
1106 cmt2-name = [ $(cmt2).full-name ] ;
1107 }
1108 local extra-error-information ;
1109 if ! $(cs1)-is-defined || ! $(cs2)-is-defined
1110 {
1111 extra-error-information = Encountered a virtual-target without a
1112 creating subvariant. It could be the virtual target has not been
1113 registered via the virtual-target.register rule. ;
1114 }
1115
1116 local action1 = [ $(.actual.$(actual-name)).action ] ;
1117 local action2 = [ $(virtual-target).action ] ;
1118 local properties-added ;
1119 local properties-removed ;
1120 if $(action1) && $(action2)
1121 {
1122 local p1 = [ $(action1).properties ] ;
7c673cae 1123 local p2 = [ $(action2).properties ] ;
11fdf7f2
TL
1124 # Only show features that are relevant for either target.
1125 local relevant = [ $(p1).get <relevant> ] [ $(p2).get <relevant> ] ;
1126 relevant = [ feature.expand-relevant $(relevant) ] ;
1127 # The presence of relevant can potentially mess things up,
1128 # so we always need to show it.
1129 relevant += relevant ;
1130 relevant = [ property-set.create <relevant>$(relevant) ] ;
1131 p1 = [ $(p1).relevant $(relevant) ] ;
1132 p2 = [ $(p2).relevant $(relevant) ] ;
1133 p1 = [ $(p1).raw ] ;
7c673cae
FG
1134 p2 = [ $(p2).raw ] ;
1135 properties-removed = [ set.difference $(p1) : $(p2) ] ;
1136 properties-removed ?= "none" ;
1137 properties-added = [ set.difference $(p2) : $(p1) ] ;
1138 properties-added ?= "none" ;
1139 }
1140 import errors : user-error : errors.user-error ;
1141 errors.user-error "Name clash for '$(actual-name)'"
1142 : ""
1143 : "Tried to build the target twice, with property sets having "
1144 : "these incompatible properties:"
1145 : ""
1146 : " - " $(properties-removed)
1147 : " - " $(properties-added)
1148 : ""
1149 : "Please make sure to have consistent requirements for these "
1150 : "properties everywhere in your project, especially for install"
1151 : "targets."
1152 ;
1153 }
1154 else
1155 {
1156 .actual.$(actual-name) = $(virtual-target) ;
1157 }
1158}
1159
1160
1161# Traverses the dependency graph of 'target' and return all targets that will be
1162# created before this one is created. If the root of some dependency graph is
1163# found during traversal, it is either included or not, depending on the
1164# 'include-roots' value. In either case traversal stops at root targets, i.e.
1165# root target sources are not traversed.
1166#
1167rule traverse ( target : include-roots ? : include-sources ? )
1168{
1169 local result ;
1170 if [ $(target).action ]
1171 {
1172 local action = [ $(target).action ] ;
1173 # This includes the 'target' as well.
1174 result += [ $(action).targets ] ;
1175
1176 for local t in [ $(action).sources ]
1177 {
1178 if ! [ $(t).root ]
1179 {
1180 result += [ traverse $(t) : $(include-roots) :
1181 $(include-sources) ] ;
1182 }
1183 else if $(include-roots)
1184 {
1185 result += $(t) ;
1186 }
1187 }
1188 }
1189 else if $(include-sources)
1190 {
1191 result = $(target) ;
1192 }
1193 return $(result) ;
1194}
1195
1196
1197# Takes an 'action' instance and creates a new instance of it and all targets
1198# produced by the action. The rule-name and properties are set to
1199# 'new-rule-name' and 'new-properties', if those are specified. Returns the
1200# cloned action.
1201#
1202rule clone-action ( action : new-project : new-action-name ? : new-properties ?
1203 )
1204{
1205 if ! $(new-action-name)
1206 {
1207 new-action-name = [ $(action).action-name ] ;
1208 }
1209 if ! $(new-properties)
1210 {
1211 new-properties = [ $(action).properties ] ;
1212 }
1213
1214 local action-class = [ modules.peek $(action) : __class__ ] ;
1215 local cloned-action = [ class.new $(action-class)
1216 [ $(action).sources ] : $(new-action-name) : $(new-properties) ] ;
1217
1218 local cloned-targets ;
1219 for local target in [ $(action).targets ]
1220 {
1221 local n = [ $(target).name ] ;
1222 # Do not modify produced target names.
1223 local cloned-target = [ class.new file-target $(n) exact :
1224 [ $(target).type ] : $(new-project) : $(cloned-action) ] ;
1225 local d = [ $(target).dependencies ] ;
1226 if $(d)
1227 {
1228 $(cloned-target).depends $(d) ;
1229 }
1230 $(cloned-target).root [ $(target).root ] ;
1231 $(cloned-target).creating-subvariant [ $(target).creating-subvariant ] ;
1232
1233 cloned-targets += $(cloned-target) ;
1234 }
1235
1236 return $(cloned-action) ;
1237}
1238
1239
1240class subvariant
1241{
1242 import sequence ;
1243 import type ;
1244
1245 rule __init__ ( main-target # The instance of main-target class.
1246 : property-set # Properties requested for this target.
1247 : sources *
1248 : build-properties # Actually used properties.
1249 : sources-usage-requirements # Properties propagated from sources.
1250 : created-targets * ) # Top-level created targets.
1251 {
1252 self.main-target = $(main-target) ;
1253 self.properties = $(property-set) ;
1254 self.sources = $(sources) ;
1255 self.build-properties = $(build-properties) ;
1256 self.sources-usage-requirements = $(sources-usage-requirements) ;
1257 self.created-targets = $(created-targets) ;
1258
1259 # Pre-compose a list of other dependency graphs this one depends on.
1260 local deps = [ $(build-properties).get <implicit-dependency> ] ;
1261 for local d in $(deps)
1262 {
1263 self.other-dg += [ $(d:G=).creating-subvariant ] ;
1264 }
1265
1266 self.other-dg = [ sequence.unique $(self.other-dg) ] ;
1267 }
1268
1269 rule main-target ( )
1270 {
1271 return $(self.main-target) ;
1272 }
1273
1274 rule created-targets ( )
1275 {
1276 return $(self.created-targets) ;
1277 }
1278
1279 rule requested-properties ( )
1280 {
1281 return $(self.properties) ;
1282 }
1283
1284 rule build-properties ( )
1285 {
1286 return $(self.build-properties) ;
1287 }
1288
1289 rule sources-usage-requirements ( )
1290 {
1291 return $(self.sources-usage-requirements) ;
1292 }
1293
1294 rule set-usage-requirements ( usage-requirements )
1295 {
1296 self.usage-requirements = $(usage-requirements) ;
1297 }
1298
1299 rule usage-requirements ( )
1300 {
1301 return $(self.usage-requirements) ;
1302 }
1303
1304 # Returns all targets referenced by this subvariant, either directly or
1305 # indirectly, and either as sources, or as dependency properties. Targets
1306 # referred to using the dependency property are returned as properties, not
1307 # targets.
1308 #
1309 rule all-referenced-targets ( theset )
1310 {
1311 # Find directly referenced targets.
1312 local deps = [ $(self.build-properties).dependency ] ;
1313 local all-targets = $(self.sources) $(deps) ;
1314
1315 # Find other subvariants.
1316 local r ;
1317 for local t in $(all-targets)
1318 {
1319 if ! [ $(theset).contains $(t) ]
1320 {
1321 $(theset).add $(t) ;
1322 r += [ $(t:G=).creating-subvariant ] ;
1323 }
1324 }
1325 r = [ sequence.unique $(r) ] ;
1326 for local s in $(r)
1327 {
1328 if $(s) != $(__name__)
1329 {
1330 $(s).all-referenced-targets $(theset) ;
1331 }
1332 }
1333 }
1334
1335 # Returns the properties specifying implicit include paths to generated
1336 # headers. This traverses all targets in this subvariant and subvariants
1337 # referred by <implicit-dependency> properties. For all targets of type
1338 # 'target-type' (or for all targets, if 'target-type' is not specified), the
1339 # result will contain <$(feature)>path-to-that-target.
1340 #
1341 rule implicit-includes ( feature : target-type ? )
1342 {
1343 local key = ii$(feature)-$(target-type:E="") ;
1344 if ! $($(key))-is-not-empty
1345 {
1346 local target-paths = [ all-target-directories $(target-type) ] ;
1347 target-paths = [ sequence.unique $(target-paths) ] ;
1348 local result = $(target-paths:G=$(feature)) ;
1349 if ! $(result)
1350 {
1351 result = "" ;
1352 }
1353 $(key) = $(result) ;
1354 }
1355 if $($(key)) = ""
1356 {
1357 return ;
1358 }
1359 else
1360 {
1361 return $($(key)) ;
1362 }
1363 }
1364
1365 rule all-target-directories ( target-type ? )
1366 {
11fdf7f2 1367 if ! $(self.target-directories.$(target-type:E=))
7c673cae
FG
1368 {
1369 compute-target-directories $(target-type) ;
1370 }
11fdf7f2 1371 return $(self.target-directories.$(target-type:E=)) ;
7c673cae
FG
1372 }
1373
1374 rule compute-target-directories ( target-type ? )
1375 {
1376 local result ;
1377 for local t in $(self.created-targets)
1378 {
1379 # Skip targets of the wrong type.
1380 local type = [ $(t).type ] ;
1381 if ! $(target-type) ||
1382 ( $(type) && [ type.is-derived $(type) $(target-type) ] )
1383 {
1384 result = [ sequence.merge $(result) : [ $(t).path ] ] ;
1385 }
1386 }
1387 for local d in $(self.other-dg)
1388 {
1389 result += [ $(d).all-target-directories $(target-type) ] ;
1390 }
11fdf7f2 1391 self.target-directories.$(target-type:E=) = $(result) ;
7c673cae
FG
1392 }
1393}