summaryrefslogtreecommitdiff
path: root/tools/build/v2/build/project.ann.py
blob: 349f549550bf9e0f6f7402c04517a419966889f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000   1) # Status: being ported by Vladimir Prus
ddc17f01 (vladimir_prus 2007-10-26 14:57:56 +0000   2) # Base revision: 40480
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000   3) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000   4) # Copyright 2002, 2003 Dave Abrahams 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000   5) # Copyright 2002, 2005, 2006 Rene Rivera 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000   6) # Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000   7) # Distributed under the Boost Software License, Version 1.0. 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000   8) # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000   9) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  10) #  Implements project representation and loading.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  11) #   Each project is represented by 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  12) #   - a module where all the Jamfile content live. 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  13) #   - an instance of 'project-attributes' class.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  14) #     (given module name, can be obtained by 'attributes' rule)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  15) #   - an instance of 'project-target' class (from targets.jam)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  16) #     (given a module name, can be obtained by 'target' rule)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  17) #
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  18) #  Typically, projects are created as result of loading Jamfile, which is
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  19) #  do by rules 'load' and 'initialize', below. First, module for Jamfile
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  20) #  is loaded and new project-attributes instance is created. Some rules
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  21) #  necessary for project are added to the module (see 'project-rules' module)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  22) #  at the bottom of this file.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  23) #  Default project attributes are set (inheriting attributes of parent project, if
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  24) #  it exists). After that, Jamfile is read. It can declare its own attributes,
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  25) #  via 'project' rule, which will be combined with already set attributes.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  26) #
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  27) #
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  28) #  The 'project' rule can also declare project id, which will be associated with 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  29) #  the project module.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  30) #
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  31) #  There can also be 'standalone' projects. They are created by calling 'initialize'
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  32) #  on arbitrary module, and not specifying location. After the call, the module can
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  33) #  call 'project' rule, declare main target and behave as regular projects. However,
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  34) #  since it's not associated with any location, it's better declare only prebuilt 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  35) #  targets.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  36) #
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  37) #  The list of all loaded Jamfile is stored in variable .project-locations. It's possible
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  38) #  to obtain module name for a location using 'module-name' rule. The standalone projects
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  39) #  are not recorded, the only way to use them is by project id.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  40) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  41) import b2.util.path
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000  42) from b2.build import property_set, property
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000  43) from b2.build.errors import ExceptionWithUserContext
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  44) import b2.build.targets
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  45) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  46) import bjam
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  47) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  48) import re
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  49) import sys
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  50) import os
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  51) import string
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000  52) import imp
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000  53) import traceback
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  54) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  55) class ProjectRegistry:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  56) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  57)     def __init__(self, manager, global_build_dir):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  58)         self.manager = manager
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  59)         self.global_build_dir = None
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000  60)         self.project_rules_ = ProjectRules(self)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  61) 
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000  62)         # The target corresponding to the project being loaded now
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  63)         self.current_project = None
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  64)         
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  65)         # The set of names of loaded project modules
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  66)         self.jamfile_modules = {}
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  67) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  68)         # Mapping from location to module name
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  69)         self.location2module = {}
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  70) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  71)         # Mapping from project id to project module
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  72)         self.id2module = {}
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  73) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  74)         # Map from Jamfile directory to parent Jamfile/Jamroot
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  75)         # location.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  76)         self.dir2parent_jamfile = {}
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  77) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  78)         # Map from directory to the name of Jamfile in
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  79)         # that directory (or None).
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  80)         self.dir2jamfile = {}
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  81) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  82)         # Map from project module to attributes object.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  83)         self.module2attributes = {}
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  84) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  85)         # Map from project module to target for the project
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  86)         self.module2target = {}
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  87) 
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000  88)         # Map from names to Python modules, for modules loaded
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000  89)         # via 'using' and 'import' rules in Jamfiles.
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000  90)         self.loaded_tool_modules_ = {}
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000  91) 
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000  92)         # Map from project target to the list of
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000  93)         # (id,location) pairs corresponding to all 'use-project'
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000  94)         # invocations.
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000  95)         # TODO: should not have a global map, keep this
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000  96)         # in ProjectTarget.
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000  97)         self.used_projects = {}
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000  98) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000  99)         self.saved_current_project = []
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 100) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 101)         self.JAMROOT = self.manager.getenv("JAMROOT");
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 102) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 103)         # Note the use of character groups, as opposed to listing
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 104)         # 'Jamroot' and 'jamroot'. With the latter, we'd get duplicate
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 105)         # matches on windows and would have to eliminate duplicates.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 106)         if not self.JAMROOT:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 107)             self.JAMROOT = ["project-root.jam", "[Jj]amroot", "[Jj]amroot.jam"]
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 108) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 109)         # Default patterns to search for the Jamfiles to use for build
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 110)         # declarations.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 111)         self.JAMFILE = self.manager.getenv("JAMFILE")
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 112) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 113)         if not self.JAMFILE:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 114)             self.JAMFILE = ["[Bb]uild.jam", "[Jj]amfile.v2", "[Jj]amfile",
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 115)                             "[Jj]amfile.jam"]
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 116) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 117) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 118)     def load (self, jamfile_location):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 119)         """Loads jamfile at the given location. After loading, project global
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 120)         file and jamfile needed by the loaded one will be loaded recursively.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 121)         If the jamfile at that location is loaded already, does nothing.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 122)         Returns the project module for the Jamfile."""
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 123) 
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 124)         absolute = os.path.join(os.getcwd(), jamfile_location)
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 125)         absolute = os.path.normpath(absolute)
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 126)         jamfile_location = b2.util.path.relpath(os.getcwd(), absolute)
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 127) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 128)         if "--debug-loading" in self.manager.argv():
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 129)             print "Loading Jamfile at '%s'" % jamfile_location
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 130) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 131)             
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 132)         mname = self.module_name(jamfile_location)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 133)         # If Jamfile is already loaded, don't try again.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 134)         if not mname in self.jamfile_modules:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 135)         
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 136)             self.load_jamfile(jamfile_location)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 137)                 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 138)             # We want to make sure that child project are loaded only
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 139)             # after parent projects. In particular, because parent projects
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 140)             # define attributes whch are inherited by children, and we don't
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 141)             # want children to be loaded before parents has defined everything.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 142)             #
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 143)             # While "build-project" and "use-project" can potentially refer
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 144)             # to child projects from parent projects, we don't immediately
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 145)             # load child projects when seing those attributes. Instead,
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 146)             # we record the minimal information that will be used only later.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 147)             
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 148)             self.load_used_projects(mname)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 149)              
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 150)         return mname
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 151) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 152)     def load_used_projects(self, module_name):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 153)         # local used = [ modules.peek $(module-name) : .used-projects ] ;
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 154)         used = self.used_projects[module_name]
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 155)     
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 156)         location = self.attribute(module_name, "location")
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 157)         for u in used:
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 158)             id = u[0]
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 159)             where = u[1]
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 160) 
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 161)             self.use(id, os.path.join(location, where))
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 162) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 163)     def load_parent(self, location):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 164)         """Loads parent of Jamfile at 'location'.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 165)         Issues an error if nothing is found."""
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 166) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 167)         found = b2.util.path.glob_in_parents(
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 168)             location, self.JAMROOT + self.JAMFILE) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 169) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 170)         if not found:
1674e2d9 (jhunold       2008-08-08 19:52:05 +0000 171)             print "error: Could not find parent for project at '%s'" % location
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 172)             print "error: Did not find Jamfile or project-root.jam in any parent directory."
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 173)             sys.exit(1)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 174)     
49c03622 (jhunold       2008-07-23 09:57:41 +0000 175)         return self.load(os.path.dirname(found[0]))
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 176) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 177)     def act_as_jamfile(self, module, location):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 178)         """Makes the specified 'module' act as if it were a regularly loaded Jamfile 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 179)         at 'location'. If Jamfile is already located for that location, it's an 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 180)         error."""
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 181) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 182)         if self.module_name(location) in self.jamfile_modules:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 183)             self.manager.errors()(
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 184)                 "Jamfile was already loaded for '%s'" % location)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 185)     
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 186)         # Set up non-default mapping from location to module.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 187)         self.location2module[location] = module
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 188)     
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 189)         # Add the location to the list of project locations
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 190)         # so that we don't try to load Jamfile in future
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 191)         self.jamfile_modules.append(location)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 192)     
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 193)         self.initialize(module, location)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 194) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 195)     def find(self, name, current_location):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 196)         """Given 'name' which can be project-id or plain directory name,
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 197)         return project module corresponding to that id or directory.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 198)         Returns nothing of project is not found."""
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 199) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 200)         project_module = None
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 201) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 202)         # Try interpreting name as project id.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 203)         if name[0] == '/':
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 204)             project_module = self.id2module.get(name)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 205) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 206)         if not project_module:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 207)             location = os.path.join(current_location, name)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 208)             # If no project is registered for the given location, try to
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 209)             # load it. First see if we have Jamfile. If not we might have project
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 210)             # root, willing to act as Jamfile. In that case, project-root
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 211)             # must be placed in the directory referred by id.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 212)         
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 213)             project_module = self.module_name(location)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 214)             if not project_module in self.jamfile_modules and \
49c03622 (jhunold       2008-07-23 09:57:41 +0000 215)                b2.util.path.glob([location], self.JAMROOT + self.JAMFILE):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 216)                 project_module = self.load(location)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 217) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 218)         return project_module
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 219) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 220)     def module_name(self, jamfile_location):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 221)         """Returns the name of module corresponding to 'jamfile-location'.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 222)         If no module corresponds to location yet, associates default
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 223)         module name with that location."""
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 224)         module = self.location2module.get(jamfile_location)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 225)         if not module:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 226)             # Root the path, so that locations are always umbiguious.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 227)             # Without this, we can't decide if '../../exe/program1' and '.'
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 228)             # are the same paths, or not.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 229)             jamfile_location = os.path.realpath(
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 230)                 os.path.join(os.getcwd(), jamfile_location))
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 231)             module = "Jamfile<%s>" % jamfile_location
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 232)             self.location2module[jamfile_location] = module
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 233)         return module
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 234) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 235)     def find_jamfile (self, dir, parent_root=0, no_errors=0):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 236)         """Find the Jamfile at the given location. This returns the
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 237)         exact names of all the Jamfiles in the given directory. The optional
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 238)         parent-root argument causes this to search not the given directory
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 239)         but the ones above it up to the directory given in it."""
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 240)         
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 241)         # Glob for all the possible Jamfiles according to the match pattern.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 242)         #
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 243)         jamfile_glob = None
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 244)         if parent_root:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 245)             parent = self.dir2parent_jamfile.get(dir)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 246)             if not parent:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 247)                 parent = b2.util.path.glob_in_parents(dir,
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 248)                                                                self.JAMFILE)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 249)                 self.dir2parent_jamfile[dir] = parent
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 250)             jamfile_glob = parent
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 251)         else:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 252)             jamfile = self.dir2jamfile.get(dir)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 253)             if not jamfile:
49c03622 (jhunold       2008-07-23 09:57:41 +0000 254)                 jamfile = b2.util.path.glob([dir], self.JAMFILE)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 255)                 self.dir2jamfile[dir] = jamfile
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 256)             jamfile_glob = jamfile
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 257) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 258)         if len(jamfile_glob):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 259)             # Multiple Jamfiles found in the same place. Warn about this.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 260)             # And ensure we use only one of them.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 261)             # As a temporary convenience measure, if there's Jamfile.v2 amount
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 262)             # found files, suppress the warning and use it.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 263)             #
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 264)             pattern = "(.*[Jj]amfile\\.v2)|(.*[Bb]uild\\.jam)"
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 265)             v2_jamfiles = [x for x in jamfile_glob if re.match(pattern, x)]
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 266)             if len(v2_jamfiles) == 1:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 267)                 jamfile_glob = v2_jamfiles
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 268)             else:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 269)                 print """warning: Found multiple Jamfiles at '%s'!
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 270) Loading the first one: '%s'.""" % (dir, jamfile_glob[0])
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 271)     
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 272)         # Could not find it, error.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 273)         if not no_errors and not jamfile_glob:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 274)             self.manager.errors()(
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 275)                 """Unable to load Jamfile.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 276) Could not find a Jamfile in directory '%s'
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 277) Attempted to find it with pattern '%s'.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 278) Please consult the documentation at 'http://boost.org/b2.'."""
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 279)                 % (dir, string.join(self.JAMFILE)))
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 280) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 281)         return jamfile_glob[0]
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 282)     
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 283)     def load_jamfile(self, dir):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 284)         """Load a Jamfile at the given directory. Returns nothing.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 285)         Will attempt to load the file as indicated by the JAMFILE patterns.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 286)         Effect of calling this rule twice with the same 'dir' is underfined."""
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 287)       
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 288)         # See if the Jamfile is where it should be.
49c03622 (jhunold       2008-07-23 09:57:41 +0000 289)         jamfile_to_load = b2.util.path.glob([dir], self.JAMROOT)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 290)         if not jamfile_to_load:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 291)             jamfile_to_load = self.find_jamfile(dir)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 292)         else:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 293)             jamfile_to_load = jamfile_to_load[0]
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 294)             
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 295)         # The module of the jamfile.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 296)         dir = os.path.realpath(os.path.dirname(jamfile_to_load))
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 297)         
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 298)         jamfile_module = self.module_name (dir)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 299) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 300)         # Initialize the jamfile module before loading.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 301)         #    
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 302)         self.initialize(jamfile_module, dir, os.path.basename(jamfile_to_load))
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 303) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 304)         saved_project = self.current_project
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 305) 
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 306)         self.used_projects[jamfile_module] = []
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 307)         
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 308)         # Now load the Jamfile in it's own context.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 309)         # Initialization might have load parent Jamfiles, which might have
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 310)         # loaded the current Jamfile with use-project. Do a final check to make
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 311)         # sure it's not loaded already.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 312)         if not jamfile_module in self.jamfile_modules:
49c03622 (jhunold       2008-07-23 09:57:41 +0000 313)             self.jamfile_modules[jamfile_module] = True
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 314) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 315)             # FIXME:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 316)             # mark-as-user $(jamfile-module) ;
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 317) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 318)             bjam.call("load", jamfile_module, jamfile_to_load)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 319)             basename = os.path.basename(jamfile_to_load)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 320)                         
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 321)         # Now do some checks
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 322)         if self.current_project != saved_project:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 323)             self.manager.errors()(
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 324) """The value of the .current-project variable
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 325) has magically changed after loading a Jamfile.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 326) This means some of the targets might be defined a the wrong project.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 327) after loading %s
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 328) expected value %s
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 329) actual value %s""" % (jamfile_module, saved_project, self.current_project))
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 330)           
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 331)         if self.global_build_dir:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 332)             id = self.attribute(jamfile_module, "id")
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 333)             project_root = self.attribute(jamfile_module, "project-root")
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 334)             location = self.attribute(jamfile_module, "location")
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 335) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 336)             if location and project_root == dir:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 337)                 # This is Jamroot
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 338)                 if not id:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 339)                     # FIXME: go via errors module, so that contexts are
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 340)                     # shown?
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 341)                     print "warning: the --build-dir option was specified"
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 342)                     print "warning: but Jamroot at '%s'" % dir
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 343)                     print "warning: specified no project id"
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 344)                     print "warning: the --build-dir option will be ignored"
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 345) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 346) 
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 347)     def load_standalone(self, jamfile_module, file):
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 348)         """Loads 'file' as standalone project that has no location
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 349)         associated with it.  This is mostly useful for user-config.jam,
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 350)         which should be able to define targets, but although it has
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 351)         some location in filesystem, we don't want any build to
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 352)         happen in user's HOME, for example.
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 353) 
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 354)         The caller is required to never call this method twice on
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 355)         the same file.
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 356)         """
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 357) 
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 358)         self.initialize(jamfile_module)
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 359)         self.used_projects[jamfile_module] = []
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 360)         bjam.call("load", jamfile_module, file)
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 361)         self.load_used_projects(jamfile_module)
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 362)         
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 363)     def is_jamroot(self, basename):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 364)         match = [ pat for pat in self.JAMROOT if re.match(pat, basename)]
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 365)         if match:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 366)             return 1
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 367)         else:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 368)             return 0
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 369) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 370)     def initialize(self, module_name, location=None, basename=None):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 371)         """Initialize the module for a project.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 372)         
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 373)         module-name is the name of the project module.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 374)         location is the location (directory) of the project to initialize.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 375)                  If not specified, stanalone project will be initialized
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 376)         """
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 377) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 378)         if "--debug-loading" in self.manager.argv():
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 379)             print "Initializing project '%s'" % module_name
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 380) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 381)         # TODO: need to consider if standalone projects can do anything but defining
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 382)         # prebuilt targets. If so, we need to give more sensible "location", so that
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 383)         # source paths are correct.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 384)         if not location:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 385)             location = ""
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 386)         else:
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 387)             location = b2.util.path.relpath(os.getcwd(), location)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 388) 
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 389)         attributes = ProjectAttributes(self.manager, location, module_name)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 390)         self.module2attributes[module_name] = attributes
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 391) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 392)         if location:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 393)             attributes.set("source-location", location, exact=1)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 394)         else:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 395)             attributes.set("source-location", "", exact=1)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 396) 
49c03622 (jhunold       2008-07-23 09:57:41 +0000 397)         attributes.set("requirements", property_set.empty(), exact=True)
49c03622 (jhunold       2008-07-23 09:57:41 +0000 398)         attributes.set("usage-requirements", property_set.empty(), exact=True)
49c03622 (jhunold       2008-07-23 09:57:41 +0000 399)         attributes.set("default-build", [], exact=True)
49c03622 (jhunold       2008-07-23 09:57:41 +0000 400)         attributes.set("projects-to-build", [], exact=True)
49c03622 (jhunold       2008-07-23 09:57:41 +0000 401)         attributes.set("project-root", None, exact=True)
49c03622 (jhunold       2008-07-23 09:57:41 +0000 402)         attributes.set("build-dir", None, exact=True)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 403)         
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 404)         self.project_rules_.init_project(module_name)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 405) 
49c03622 (jhunold       2008-07-23 09:57:41 +0000 406)         jamroot = False
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 407) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 408)         parent_module = None;
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 409)         if module_name == "site-config":
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 410)             # No parent
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 411)             pass
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 412)         elif module_name == "user-config":
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 413)             parent_module = "site-config"
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 414)         elif location and not self.is_jamroot(basename):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 415)             # We search for parent/project-root only if jamfile was specified 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 416)             # --- i.e
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 417)             # if the project is not standalone.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 418)             parent_module = self.load_parent(location)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 419)         else:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 420)             # It's either jamroot, or standalone project.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 421)             # If it's jamroot, inherit from user-config.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 422)             if location:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 423)                 parent_module = "user-config" ;                
49c03622 (jhunold       2008-07-23 09:57:41 +0000 424)                 jamroot = True ;
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 425)                 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 426)         if parent_module:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 427)             self.inherit_attributes(module_name, parent_module)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 428)             attributes.set("parent-module", parent_module, exact=1)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 429) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 430)         if jamroot:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 431)             attributes.set("project-root", location, exact=1)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 432)                                 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 433)         parent = None
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 434)         if parent_module:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 435)             parent = self.target(parent_module)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 436) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 437)         if not self.module2target.has_key(module_name):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 438)             target = b2.build.targets.ProjectTarget(self.manager,
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 439)                 module_name, module_name, parent,
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 440)                 self.attribute(module_name,"requirements"),
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 441)                 # FIXME: why we need to pass this? It's not
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 442)                 # passed in jam code.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 443)                 self.attribute(module_name, "default-build"))
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 444)             self.module2target[module_name] = target
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 445) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 446)         self.current_project = self.target(module_name)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 447) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 448)     def inherit_attributes(self, project_module, parent_module):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 449)         """Make 'project-module' inherit attributes of project
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 450)         root and parent module."""
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 451) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 452)         attributes = self.module2attributes[project_module]
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 453)         pattributes = self.module2attributes[parent_module]
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 454)         
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 455)         # Parent module might be locationless user-config.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 456)         # FIXME:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 457)         #if [ modules.binding $(parent-module) ]
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 458)         #{        
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 459)         #    $(attributes).set parent : [ path.parent 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 460)         #                                 [ path.make [ modules.binding $(parent-module) ] ] ] ;
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 461)         #    }
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 462)         
49c03622 (jhunold       2008-07-23 09:57:41 +0000 463)         attributes.set("project-root", pattributes.get("project-root"), exact=True)
49c03622 (jhunold       2008-07-23 09:57:41 +0000 464)         attributes.set("default-build", pattributes.get("default-build"), exact=True)
49c03622 (jhunold       2008-07-23 09:57:41 +0000 465)         attributes.set("requirements", pattributes.get("requirements"), exact=True)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 466)         attributes.set("usage-requirements",
cde6f09a (vladimir_prus 2007-10-19 23:12:33 +0000 467)                        pattributes.get("usage-requirements"), exact=1)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 468) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 469)         parent_build_dir = pattributes.get("build-dir")
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 470)         
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 471)         if parent_build_dir:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 472)         # Have to compute relative path from parent dir to our dir
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 473)         # Convert both paths to absolute, since we cannot
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 474)         # find relative path from ".." to "."
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 475) 
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 476)              location = attributes.get("location")
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 477)              parent_location = pattributes.get("location")
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 478) 
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 479)              our_dir = os.path.join(os.getcwd(), location)
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 480)              parent_dir = os.path.join(os.getcwd(), parent_location)
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 481) 
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 482)              build_dir = os.path.join(parent_build_dir,
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 483)                                       b2.util.path.relpath(parent_dir,
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 484)                                                                     our_dir))
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 485) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 486)     def register_id(self, id, module):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 487)         """Associate the given id with the given project module."""
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 488)         self.id2module[id] = module
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 489) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 490)     def current(self):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 491)         """Returns the project which is currently being loaded."""
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 492)         return self.current_project
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 493) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 494)     def push_current(self, project):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 495)         """Temporary changes the current project to 'project'. Should
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 496)         be followed by 'pop-current'."""
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 497)         self.saved_current_project.append(self.current_project)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 498)         self.current_project = project
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 499) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 500)     def pop_current(self):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 501)         self.current_project = self.saved_current_project[-1]
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 502)         del self.saved_current_project[-1]
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 503) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 504)     def attributes(self, project):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 505)         """Returns the project-attribute instance for the
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 506)         specified jamfile module."""
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 507)         return self.module2attributes[project]
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 508) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 509)     def attribute(self, project, attribute):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 510)         """Returns the value of the specified attribute in the
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 511)         specified jamfile module."""
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 512)         return self.module2attributes[project].get(attribute)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 513) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 514)     def target(self, project_module):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 515)         """Returns the project target corresponding to the 'project-module'."""
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 516)         if not self.module2target[project_module]:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 517)             self.module2target[project_module] = \
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 518)                 ProjectTarget(project_module, project_module,
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 519)                               self.attribute(project_module, "requirements"))
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 520)         
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 521)         return self.module2target[project_module]
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 522) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 523)     def use(self, id, location):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 524)         # Use/load a project.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 525)         saved_project = self.current_project
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 526)         project_module = self.load(location)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 527)         declared_id = self.attribute(project_module, "id")
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 528) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 529)         if not declared_id or declared_id != id:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 530)             # The project at 'location' either have no id or
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 531)             # that id is not equal to the 'id' parameter.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 532)             if self.id2module[id] and self.id2module[id] != project_module:
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 533)                 self.manager.errors()(
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 534) """Attempt to redeclare already existing project id '%s'""" % id)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 535)             self.id2module[id] = project_module
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 536) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 537)         self.current_module = saved_project
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 538) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 539)     def add_rule(self, name, callable):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 540)         """Makes rule 'name' available to all subsequently loaded Jamfiles.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 541) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 542)         Calling that rule wil relay to 'callable'."""
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 543)         self.project_rules_.add_rule(name, callable)
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 544) 
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 545)     def project_rules(self):
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 546)         return self.project_rules_
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 547) 
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 548)     def glob_internal(self, project, wildcards, excludes, rule_name):
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 549)         location = project.get("source-location")
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 550) 
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 551)         result = []
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 552)         callable = b2.util.path.__dict__[rule_name]
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 553)         
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 554)         paths = callable(location, wildcards, excludes)
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 555)         has_dir = 0
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 556)         for w in wildcards:
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 557)             if os.path.dirname(w):
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 558)                 has_dir = 1
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 559)                 break
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 560) 
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 561)         if has_dir or rule_name != "glob":
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 562)             # The paths we've found are relative to current directory,
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 563)             # but the names specified in sources list are assumed to
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 564)             # be relative to source directory of the corresponding
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 565)             # prject. So, just make the name absolute.
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 566)             result = [os.path.join(os.getcwd(), p) for p in paths]
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 567)         else:
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 568)             # There were not directory in wildcard, so the files are all
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 569)             # in the source directory of the project. Just drop the
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 570)             # directory, instead of making paths absolute.
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 571)             result = [os.path.basename(p) for p in paths]
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 572)             
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 573)         return result
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 574) 
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 575)     def load_module(self, name, extra_path=None):
53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 576)         """Classic Boost.Build 'modules' are in fact global variables.
53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 577)         Therefore, try to find an already loaded Python module called 'name' in sys.modules. 
53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 578)         If the module ist not loaded, find it Boost.Build search
53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 579)         path and load it.  The new module is not entered in sys.modules.
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 580)         The motivation here is to have disjoint namespace of modules
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 581)         loaded via 'import/using' in Jamfile, and ordinary Python
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 582)         modules. We don't want 'using foo' in Jamfile to load ordinary
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 583)         Python module 'foo' which is going to not work. And we
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 584)         also don't want 'import foo' in regular Python module to
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 585)         accidentally grab module named foo that is internal to
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 586)         Boost.Build and intended to provide interface to Jamfiles."""
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 587) 
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 588)         existing = self.loaded_tool_modules_.get(name)
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 589)         if existing:
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 590)             return existing
53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 591) 
53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 592)         modules = sys.modules
53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 593)         for class_name in modules:
53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 594)             if name in class_name:
53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 595)                 module = modules[class_name]
53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 596)                 self.loaded_tool_modules_[name] = module
53b0faa2 (jhunold       2008-08-10 18:25:50 +0000 597)                 return module
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 598)         
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 599)         path = extra_path
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 600)         if not path:
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 601)             path = []
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 602)         path.extend(self.manager.b2.path())
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 603)         location = None
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 604)         for p in path:
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 605)             l = os.path.join(p, name + ".py")
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 606)             if os.path.exists(l):
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 607)                 location = l
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 608)                 break
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 609) 
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 610)         if not location:
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 611)             self.manager.errors()("Cannot find module '%s'" % name)
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 612) 
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 613)         mname = "__build_build_temporary__"
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 614)         file = open(location)
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 615)         try:
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 616)             # TODO: this means we'll never make use of .pyc module,
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 617)             # which might be a problem, or not.
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 618)             module = imp.load_module(mname, file, os.path.basename(location),
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 619)                                      (".py", "r", imp.PY_SOURCE))
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 620)             del sys.modules[mname]
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 621)             self.loaded_tool_modules_[name] = module
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 622)             return module
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 623)         finally:
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 624)             file.close()
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 625)         
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 626) 
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 627) 
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 628) # FIXME:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 629) # Defines a Boost.Build extension project. Such extensions usually
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 630) # contain library targets and features that can be used by many people.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 631) # Even though extensions are really projects, they can be initialize as
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 632) # a module would be with the "using" (project.project-rules.using)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 633) # mechanism.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 634) #rule extension ( id : options * : * )
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 635) #{
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 636) #    # The caller is a standalone module for the extension.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 637) #    local mod = [ CALLER_MODULE ] ;
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 638) #    
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 639) #    # We need to do the rest within the extension module.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 640) #    module $(mod)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 641) #    {
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 642) #        import path ;
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 643) #        
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 644) #        # Find the root project.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 645) #        local root-project = [ project.current ] ;
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 646) #        root-project = [ $(root-project).project-module ] ;
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 647) #        while
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 648) #            [ project.attribute $(root-project) parent-module ] &&
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 649) #            [ project.attribute $(root-project) parent-module ] != user-config
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 650) #        {
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 651) #            root-project = [ project.attribute $(root-project) parent-module ] ;
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 652) #        }
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 653) #        
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 654) #        # Create the project data, and bring in the project rules
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 655) #        # into the module.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 656) #        project.initialize $(__name__) :
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 657) #            [ path.join [ project.attribute $(root-project) location ] ext $(1:L) ] ;
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 658) #        
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 659) #        # Create the project itself, i.e. the attributes.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 660) #        # All extensions are created in the "/ext" project space.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 661) #        project /ext/$(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 662) #        local attributes = [ project.attributes $(__name__) ] ;
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 663) #        
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 664) #        # Inherit from the root project of whomever is defining us.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 665) #        project.inherit-attributes $(__name__) : $(root-project) ;
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 666) #        $(attributes).set parent-module : $(root-project) : exact ;
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 667) #    }
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 668) #}
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 669)         
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 670) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 671) class ProjectAttributes:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 672)     """Class keeping all the attributes of a project.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 673) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 674)     The standard attributes are 'id', "location", "project-root", "parent"
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 675)     "requirements", "default-build", "source-location" and "projects-to-build".
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 676)     """
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 677)         
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 678)     def __init__(self, manager, location, project_module):
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 679)         self.manager = manager
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 680)         self.location = location
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 681)         self.project_module = project_module
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 682)         self.attributes = {}
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 683)         self.usage_requirements = None
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 684)         
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 685)     def set(self, attribute, specification, exact):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 686)         """Set the named attribute from the specification given by the user.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 687)         The value actually set may be different."""
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 688) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 689)         if exact:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 690)             self.__dict__[attribute] = specification
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 691)             
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 692)         elif attribute == "requirements":
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 693)             self.requirements = property_set.refine_from_user_input(
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 694)                 self.requirements, specification,
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 695)                 self.project_module, self.location)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 696)             
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 697)         elif attribute == "usage-requirements":
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 698)             unconditional = []
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 699)             for p in specification:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 700)                 split = property.split_conditional(p)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 701)                 if split:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 702)                     unconditional.append(split[1])
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 703)                 else:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 704)                     unconditional.append(p)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 705) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 706)             non_free = property.remove("free", unconditional)
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 707)             if non_free:                
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 708)                 pass
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 709)                 # FIXME:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 710)                 #errors.error "usage-requirements" $(specification) "have non-free properties" $(non-free) ;
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 711) 
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 712)             t = property.translate_paths(specification, self.location)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 713) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 714)             existing = self.__dict__.get("usage-requirements")
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 715)             if existing:
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 716)                 new = property_set.create(existing.raw() +  t)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 717)             else:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 718)                 new = property_set.create(t)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 719)             self.__dict__["usage-requirements"] = new
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 720) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 721)                 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 722)         elif attribute == "default-build":
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 723)             self.__dict__["default-build"] = property_set.create(specification)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 724)             
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 725)         elif attribute == "source-location":
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 726)             source_location = []
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 727)             for path in specification:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 728)                 source_location += os.path.join(self.location, path)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 729)             self.__dict__["source-location"] = source_location
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 730)                 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 731)         elif attribute == "build-dir":
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 732)             self.__dict__["build-dir"] = os.path.join(self.location, specification)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 733)                  
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 734)         elif not attribute in ["id", "default-build", "location",
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 735)                                "source-location", "parent",
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 736)                                "projects-to-build", "project-root"]:
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 737)             self.manager.errors()(
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 738) """Invalid project attribute '%s' specified
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 739) for project at '%s'""" % (attribute, self.location))
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 740)         else:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 741)             self.__dict__[attribute] = specification
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 742) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 743)     def get(self, attribute):
cde6f09a (vladimir_prus 2007-10-19 23:12:33 +0000 744)         return self.__dict__[attribute]
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 745) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 746)     def dump(self):
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 747)         """Prints the project attributes."""
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 748)         id = self.get("id")
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 749)         if not id:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 750)             id = "(none)"
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 751)         else:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 752)             id = id[0]
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 753) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 754)         parent = self.get("parent")
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 755)         if not parent:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 756)             parent = "(none)"
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 757)         else:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 758)             parent = parent[0]
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 759) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 760)         print "'%s'" % id
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 761)         print "Parent project:%s", parent
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 762)         print "Requirements:%s", self.get("requirements")
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 763)         print "Default build:%s", string.join(self.get("debuild-build"))
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 764)         print "Source location:%s", string.join(self.get("source-location"))
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 765)         print "Projects to build:%s", string.join(self.get("projects-to-build").sort());
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 766) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 767) class ProjectRules:
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 768)     """Class keeping all rules that are made available to Jamfile."""
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 769) 
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 770)     def __init__(self, registry):
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 771)         self.registry = registry
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 772)         self.manager_ = registry.manager
38d984eb (vladimir_prus 2007-10-13 17:52:25 +0000 773)         self.rules = {}
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 774)         self.local_names = [x for x in self.__class__.__dict__
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 775)                             if x not in ["__init__", "init_project", "add_rule",
7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 776)                                          "error_reporting_wrapper", "add_rule_for_type"]]
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 777)         self.all_names_ = [x for x in self.local_names]
7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 778) 
7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 779)     def add_rule_for_type(self, type):
7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 780)         rule_name = type.lower();
7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 781) 
7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 782)         def xpto (name, sources, requirements = [], default_build = None, usage_requirements = []):
7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 783)             return self.manager_.targets().create_typed_target(
7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 784)                 type, self.registry.current(), name[0], sources,
7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 785)                 requirements, default_build, usage_requirements) 
7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 786) 
7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 787)         self.add_rule(type.lower(), xpto)
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 788)     
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 789)     def add_rule(self, name, callable):
38d984eb (vladimir_prus 2007-10-13 17:52:25 +0000 790)         self.rules[name] = callable
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 791)         self.all_names_.append(name)
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 792) 
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 793)     def all_names(self):
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 794)         return self.all_names_
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 795) 
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 796)     def call_and_report_errors(self, callable, *args):
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 797)         result = None
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 798)         try:
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 799)             self.manager_.errors().push_jamfile_context()
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 800)             result = callable(*args)
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 801)         except ExceptionWithUserContext, e:
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 802)             e.report()
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 803)         except Exception, e:
7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 804)             try:
7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 805)                 self.manager_.errors().handle_stray_exception (e)
7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 806)             except ExceptionWithUserContext, e:
7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 807)                 e.report()
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 808)         finally:                
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 809)             self.manager_.errors().pop_jamfile_context()
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 810)                                         
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 811)         return result
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 812) 
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 813)     def make_wrapper(self, callable):
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 814)         """Given a free-standing function 'callable', return a new
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 815)         callable that will call 'callable' and report all exceptins,
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 816)         using 'call_and_report_errors'."""
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 817)         def wrapper(*args):
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 818)             self.call_and_report_errors(callable, *args)
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 819)         return wrapper
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 820) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 821)     def init_project(self, project_module):
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 822) 
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 823)         for n in self.local_names:            
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 824)             # Using 'getattr' here gives us a bound method,
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 825)             # while using self.__dict__[r] would give unbound one.
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 826)             v = getattr(self, n)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 827)             if callable(v):
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 828)                 if n == "import_":
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 829)                     n = "import"
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 830)                 else:
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 831)                     n = string.replace(n, "_", "-")
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 832)                     
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 833)                 bjam.import_rule(project_module, n,
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 834)                                  self.make_wrapper(v))
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 835) 
38d984eb (vladimir_prus 2007-10-13 17:52:25 +0000 836)         for n in self.rules:
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 837)             bjam.import_rule(project_module, n,
0317671e (vladimir_prus 2007-10-28 14:02:06 +0000 838)                              self.make_wrapper(self.rules[n]))
38d984eb (vladimir_prus 2007-10-13 17:52:25 +0000 839) 
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 840)     def project(self, *args):
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 841) 
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 842)         jamfile_module = self.registry.current().project_module()
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 843)         attributes = self.registry.attributes(jamfile_module)
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 844)         
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 845)         id = None
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 846)         if args and args[0]:
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 847)             id = args[0][0]
092119e3 (vladimir_prus 2007-10-16 05:45:31 +0000 848)             args = args[1:]
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 849) 
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 850)         if id:
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 851)             if id[0] != '/':
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 852)                 id = '/' + id
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 853)             self.registry.register_id (id, jamfile_module)
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 854) 
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 855)         explicit_build_dir = None
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 856)         for a in args:
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 857)             if a:
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 858)                 attributes.set(a[0], a[1:], exact=0)
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 859)                 if a[0] == "build-dir":
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 860)                     explicit_build_dir = a[1]
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 861)         
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 862)         # If '--build-dir' is specified, change the build dir for the project.
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 863)         if self.registry.global_build_dir:
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 864) 
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 865)             location = attributes.get("location")
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 866)             # Project with empty location is 'standalone' project, like
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 867)             # user-config, or qt.  It has no build dir.
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 868)             # If we try to set build dir for user-config, we'll then
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 869)             # try to inherit it, with either weird, or wrong consequences.
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 870)             if location and location == attributes.get("project-root"):
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 871)                 # This is Jamroot.
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 872)                 if id:
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 873)                     if explicit_build_dir and os.path.isabs(explicit_build_dir):
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 874)                         self.register.manager.errors()(
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 875) """Absolute directory specified via 'build-dir' project attribute
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 876) Don't know how to combine that with the --build-dir option.""")
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 877) 
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 878)                     rid = id
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 879)                     if rid[0] == '/':
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 880)                         rid = rid[1:]
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 881) 
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 882)                     p = os.path.join(self.registry.global_build_dir,
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 883)                                      rid, explicit_build_dir)
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 884)                     attributes.set("build-dir", p, exact=1)
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 885)             elif explicit_build_dir:
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 886)                 self.registry.manager.errors()(
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 887) """When --build-dir is specified, the 'build-project'
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 888) attribute is allowed only for top-level 'project' invocations""")
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 889) 
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 890)     def constant(self, name, value):
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 891)         """Declare and set a project global constant.
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 892)         Project global constants are normal variables but should
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 893)         not be changed. They are applied to every child Jamfile."""
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 894)         m = "Jamfile</home/ghost/Work/Boost/boost-svn/tools/build/v2_python/python/tests/bjam/make>"
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 895)         self.registry.current().add_constant(name[0], value)
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 896) 
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 897)     def path_constant(self, name, value):
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 898)         """Declare and set a project global constant, whose value is a path. The
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 899)         path is adjusted to be relative to the invocation directory. The given
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 900)         value path is taken to be either absolute, or relative to this project
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 901)         root."""
0ed8e16d (vladimir_prus 2007-10-13 21:34:05 +0000 902)         self.registry.current().add_constant(name[0], value, path=1)
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 903) 
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 904)     def use_project(self, id, where):
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 905)         # See comment in 'load' for explanation why we record the
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 906)         # parameters as opposed to loading the project now.
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 907)         m = self.registry.current().project_module();
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 908)         self.registry.used_projects[m].append((id, where))
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 909)         
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 910)     def build_project(self, dir):
1674e2d9 (jhunold       2008-08-08 19:52:05 +0000 911)         assert(isinstance(dir, list))
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 912)         jamfile_module = self.registry.current().project_module()
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 913)         attributes = self.registry.attributes(jamfile_module)
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 914)         now = attributes.get("projects-to-build")
1674e2d9 (jhunold       2008-08-08 19:52:05 +0000 915)         attributes.set("projects-to-build", now + dir, exact=True)
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 916) 
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 917)     def explicit(self, target_names):
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 918)         t = self.registry.current()
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 919)         for n in target_names:
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 920)             t.mark_target_as_explicit(n)
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 921) 
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 922)     def glob(self, wildcards, excludes=None):
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 923)         return self.registry.glob_internal(self.registry.current(),
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 924)                                            wildcards, excludes, "glob")
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 925) 
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 926)     def glob_tree(self, wildcards, excludes=None):
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 927)         bad = 0
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 928)         for p in wildcards:
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 929)             if os.path.dirname(p):
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 930)                 bad = 1
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 931) 
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 932)         if excludes:
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 933)             for p in excludes:
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 934)                 if os.path.dirname(p):
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 935)                     bad = 1
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 936) 
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 937)         if bad:
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 938)             self.registry.manager().errors()(
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 939) "The patterns to 'glob-tree' may not include directory")
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 940)         return self.registry.glob_internal(self.registry.current(),
2a36874b (vladimir_prus 2007-10-14 07:20:55 +0000 941)                                            wildcards, excludes, "glob_tree")
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 942)     
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 943) 
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 944)     def using(self, toolset, *args):
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 945)         # The module referred by 'using' can be placed in
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 946)         # the same directory as Jamfile, and the user
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 947)         # will expect the module to be found even though
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 948)         # the directory is not in BOOST_BUILD_PATH.
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 949)         # So temporary change the search path.
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 950)         jamfile_module = self.registry.current().project_module()
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 951)         attributes = self.registry.attributes(jamfile_module)
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 952)         location = attributes.get("location")
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 953) 
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 954)         m = self.registry.load_module(toolset[0], [location])
7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 955)         if not m.__dict__.has_key("init"):
7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 956)             self.registry.manager.errors()(
7da7f9c1 (vladimir_prus 2008-05-18 04:29:53 +0000 957)                 "Tool module '%s' does not define the 'init' method" % toolset[0])
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 958)         m.init(*args)
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 959) 
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 960) 
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 961)     def import_(self, name, names_to_import=None, local_names=None):
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 962) 
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 963)         name = name[0]
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 964)         jamfile_module = self.registry.current().project_module()
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 965)         attributes = self.registry.attributes(jamfile_module)
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 966)         location = attributes.get("location")
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 967) 
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 968)         m = self.registry.load_module(name, [location])
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 969) 
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 970)         for f in m.__dict__:
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 971)             v = m.__dict__[f]
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 972)             if callable(v):
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 973)                 bjam.import_rule(jamfile_module, name + "." + f, v)
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 974) 
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 975)         if names_to_import:
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 976)             if not local_names:
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 977)                 local_names = names_to_import
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 978) 
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 979)             if len(names_to_import) != len(local_names):
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 980)                 self.registry.manager.errors()(
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 981) """The number of names to import and local names do not match.""")
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 982) 
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 983)             for n, l in zip(names_to_import, local_names):
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 984)                 bjam.import_rule(jamfile_module, l, m.__dict__[n])
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 985)         
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 986)     def conditional(self, condition, requirements):
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 987)         """Calculates conditional requirements for multiple requirements
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 988)         at once. This is a shorthand to be reduce duplication and to
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 989)         keep an inline declarative syntax. For example:
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 990) 
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 991)             lib x : x.cpp : [ conditional <toolset>gcc <variant>debug :
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 992)                 <define>DEBUG_EXCEPTION <define>DEBUG_TRACE ] ;
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 993)         """
f049766b (vladimir_prus 2007-10-10 09:31:06 +0000 994) 
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 995)         c = string.join(condition, ",")
f2aef897 (vladimir_prus 2007-10-14 09:19:52 +0000 996)         return [c + ":" + r for r in requirements]