1 """SCons.Environment
2
3 Base class for construction Environments. These are
4 the primary objects used to communicate dependency and
5 construction information to the build engine.
6
7 Keyword arguments supplied when the construction Environment
8 is created are construction variables used to initialize the
9 Environment
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 __revision__ = "src/engine/SCons/Environment.py rel_2.4.1:3453:73fefd3ea0b0 2015/11/09 03:25:05 bdbaddog"
35
36
37 import copy
38 import os
39 import sys
40 import re
41 import shlex
42 from collections import UserDict
43
44 import SCons.Action
45 import SCons.Builder
46 import SCons.Debug
47 from SCons.Debug import logInstanceCreation
48 import SCons.Defaults
49 import SCons.Errors
50 import SCons.Memoize
51 import SCons.Node
52 import SCons.Node.Alias
53 import SCons.Node.FS
54 import SCons.Node.Python
55 import SCons.Platform
56 import SCons.SConf
57 import SCons.SConsign
58 import SCons.Subst
59 import SCons.Tool
60 import SCons.Util
61 import SCons.Warnings
65
66 _null = _Null
67
68 _warn_copy_deprecated = True
69 _warn_source_signatures_deprecated = True
70 _warn_target_signatures_deprecated = True
71
72 CleanTargets = {}
73 CalculatorArgs = {}
74
75 semi_deepcopy = SCons.Util.semi_deepcopy
76 semi_deepcopy_dict = SCons.Util.semi_deepcopy_dict
77
78
79
80
81 UserError = SCons.Errors.UserError
85
86 AliasBuilder = SCons.Builder.Builder(action = alias_builder,
87 target_factory = SCons.Node.Alias.default_ans.Alias,
88 source_factory = SCons.Node.FS.Entry,
89 multi = 1,
90 is_explicit = None,
91 name='AliasBuilder')
108
109
110
111
112 reserved_construction_var_names = [
113 'CHANGED_SOURCES',
114 'CHANGED_TARGETS',
115 'SOURCE',
116 'SOURCES',
117 'TARGET',
118 'TARGETS',
119 'UNCHANGED_SOURCES',
120 'UNCHANGED_TARGETS',
121 ]
122
123 future_reserved_construction_var_names = [
124
125
126
127 ]
137
141
146
159
163
167
169 """Delete duplicates from a sequence, keeping the first or last."""
170 seen={}
171 result=[]
172 if keep_last:
173 l.reverse()
174 for i in l:
175 try:
176 if i not in seen:
177 result.append(i)
178 seen[i]=1
179 except TypeError:
180
181 result.append(i)
182 if keep_last:
183 result.reverse()
184 return result
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199 -class MethodWrapper(object):
200 """
201 A generic Wrapper class that associates a method (which can
202 actually be any callable) with an object. As part of creating this
203 MethodWrapper object an attribute with the specified (by default,
204 the name of the supplied method) is added to the underlying object.
205 When that new "method" is called, our __call__() method adds the
206 object as the first argument, simulating the Python behavior of
207 supplying "self" on method calls.
208
209 We hang on to the name by which the method was added to the underlying
210 base class so that we can provide a method to "clone" ourselves onto
211 a new underlying object being copied (without which we wouldn't need
212 to save that info).
213 """
214 - def __init__(self, object, method, name=None):
215 if name is None:
216 name = method.__name__
217 self.object = object
218 self.method = method
219 self.name = name
220 setattr(self.object, name, self)
221
223 nargs = (self.object,) + args
224 return self.method(*nargs, **kwargs)
225
226 - def clone(self, new_object):
227 """
228 Returns an object that re-binds the underlying "method" to
229 the specified new object.
230 """
231 return self.__class__(new_object, self.method, self.name)
232
234 """
235 A MethodWrapper subclass that that associates an environment with
236 a Builder.
237
238 This mainly exists to wrap the __call__() function so that all calls
239 to Builders can have their argument lists massaged in the same way
240 (treat a lone argument as the source, treat two arguments as target
241 then source, make sure both target and source are lists) without
242 having to have cut-and-paste code to do it.
243
244 As a bit of obsessive backwards compatibility, we also intercept
245 attempts to get or set the "env" or "builder" attributes, which were
246 the names we used before we put the common functionality into the
247 MethodWrapper base class. We'll keep this around for a while in case
248 people shipped Tool modules that reached into the wrapper (like the
249 Tool/qt.py module does, or did). There shouldn't be a lot attribute
250 fetching or setting on these, so a little extra work shouldn't hurt.
251 """
253 if source is _null:
254 source = target
255 target = None
256 if target is not None and not SCons.Util.is_List(target):
257 target = [target]
258 if source is not None and not SCons.Util.is_List(source):
259 source = [source]
260 return MethodWrapper.__call__(self, target, source, *args, **kw)
261
263 return '<BuilderWrapper %s>' % repr(self.name)
264
267
269 if name == 'env':
270 return self.object
271 elif name == 'builder':
272 return self.method
273 else:
274 raise AttributeError(name)
275
277 if name == 'env':
278 self.object = value
279 elif name == 'builder':
280 self.method = value
281 else:
282 self.__dict__[name] = value
283
284
285
286
287
288
289
290
291
292
293
294
295 -class BuilderDict(UserDict):
296 """This is a dictionary-like class used by an Environment to hold
297 the Builders. We need to do this because every time someone changes
298 the Builders in the Environment's BUILDERS dictionary, we must
299 update the Environment's attributes."""
306
308
309
310 raise TypeError( 'cannot semi_deepcopy a BuilderDict' )
311
321
325
329
330
331
332 _is_valid_var = re.compile(r'[_a-zA-Z]\w*$')
335 """Return if the specified string is a legitimate construction
336 variable.
337 """
338 return _is_valid_var.match(varstr)
339
343 """Base class for different flavors of construction environments.
344
345 This class contains a minimal set of methods that handle contruction
346 variable expansion and conversion of strings to Nodes, which may or
347 may not be actually useful as a stand-alone class. Which methods
348 ended up in this class is pretty arbitrary right now. They're
349 basically the ones which we've empirically determined are common to
350 the different construction environment subclasses, and most of the
351 others that use or touch the underlying dictionary of construction
352 variables.
353
354 Eventually, this class should contain all the methods that we
355 determine are necessary for a "minimal" interface to the build engine.
356 A full "native Python" SCons environment has gotten pretty heavyweight
357 with all of the methods and Tools and construction variables we've
358 jammed in there, so it would be nice to have a lighter weight
359 alternative for interfaces that don't need all of the bells and
360 whistles. (At some point, we'll also probably rename this class
361 "Base," since that more reflects what we want this class to become,
362 but because we've released comments that tell people to subclass
363 Environment.Base to create their own flavors of construction
364 environment, we'll save that for a future refactoring when this
365 class actually becomes useful.)
366 """
367
378
379
398
400 return cmp(self._dict, other._dict)
401
403 special = self._special_del.get(key)
404 if special:
405 special(self, key)
406 else:
407 del self._dict[key]
408
410 return self._dict[key]
411
413
414
415
416
417
418
419
420
421
422
423
424
425 if key in self._special_set_keys:
426 self._special_set[key](self, key, value)
427 else:
428
429
430
431
432 if key not in self._dict \
433 and not _is_valid_var.match(key):
434 raise SCons.Errors.UserError("Illegal construction variable `%s'" % key)
435 self._dict[key] = value
436
437 - def get(self, key, default=None):
438 """Emulates the get() method of dictionaries."""
439 return self._dict.get(key, default)
440
442 return key in self._dict
443
446
448 return list(self._dict.items())
449
451 if node_factory is _null:
452 node_factory = self.fs.File
453 if lookup_list is _null:
454 lookup_list = self.lookup_list
455
456 if not args:
457 return []
458
459 args = SCons.Util.flatten(args)
460
461 nodes = []
462 for v in args:
463 if SCons.Util.is_String(v):
464 n = None
465 for l in lookup_list:
466 n = l(v)
467 if n is not None:
468 break
469 if n is not None:
470 if SCons.Util.is_String(n):
471
472 kw['raw'] = 1
473 n = self.subst(n, **kw)
474 if node_factory:
475 n = node_factory(n)
476 if SCons.Util.is_List(n):
477 nodes.extend(n)
478 else:
479 nodes.append(n)
480 elif node_factory:
481
482 kw['raw'] = 1
483 v = node_factory(self.subst(v, **kw))
484 if SCons.Util.is_List(v):
485 nodes.extend(v)
486 else:
487 nodes.append(v)
488 else:
489 nodes.append(v)
490
491 return nodes
492
495
498
499 - def subst(self, string, raw=0, target=None, source=None, conv=None, executor=None):
500 """Recursively interpolates construction variables from the
501 Environment into the specified string, returning the expanded
502 result. Construction variables are specified by a $ prefix
503 in the string and begin with an initial underscore or
504 alphabetic character followed by any number of underscores
505 or alphanumeric characters. The construction variable names
506 may be surrounded by curly braces to separate the name from
507 trailing characters.
508 """
509 gvars = self.gvars()
510 lvars = self.lvars()
511 lvars['__env__'] = self
512 if executor:
513 lvars.update(executor.get_lvars())
514 return SCons.Subst.scons_subst(string, self, raw, target, source, gvars, lvars, conv)
515
516 - def subst_kw(self, kw, raw=0, target=None, source=None):
517 nkw = {}
518 for k, v in kw.items():
519 k = self.subst(k, raw, target, source)
520 if SCons.Util.is_String(v):
521 v = self.subst(v, raw, target, source)
522 nkw[k] = v
523 return nkw
524
525 - def subst_list(self, string, raw=0, target=None, source=None, conv=None, executor=None):
534
535 - def subst_path(self, path, target=None, source=None):
536 """Substitute a path list, turning EntryProxies into Nodes
537 and leaving Nodes (and other objects) as-is."""
538
539 if not SCons.Util.is_List(path):
540 path = [path]
541
542 def s(obj):
543 """This is the "string conversion" routine that we have our
544 substitutions use to return Nodes, not strings. This relies
545 on the fact that an EntryProxy object has a get() method that
546 returns the underlying Node that it wraps, which is a bit of
547 architectural dependence that we might need to break or modify
548 in the future in response to additional requirements."""
549 try:
550 get = obj.get
551 except AttributeError:
552 obj = SCons.Util.to_String_for_subst(obj)
553 else:
554 obj = get()
555 return obj
556
557 r = []
558 for p in path:
559 if SCons.Util.is_String(p):
560 p = self.subst(p, target=target, source=source, conv=s)
561 if SCons.Util.is_List(p):
562 if len(p) == 1:
563 p = p[0]
564 else:
565
566
567
568 p = ''.join(map(SCons.Util.to_String_for_subst, p))
569 else:
570 p = s(p)
571 r.append(p)
572 return r
573
574 subst_target_source = subst
575
577 import subprocess
578
579 kw = { 'stdin' : 'devnull',
580 'stdout' : subprocess.PIPE,
581 'stderr' : subprocess.PIPE,
582 'universal_newlines' : True,
583 }
584
585
586 if not SCons.Util.is_List(command): kw['shell'] = True
587
588 p = SCons.Action._subproc(self, command, **kw)
589 out,err = p.communicate()
590 status = p.wait()
591 if err:
592 sys.stderr.write(unicode(err))
593 if status:
594 raise OSError("'%s' exited %d" % (command, status))
595 return out
596
598 """
599 Adds the specified function as a method of this construction
600 environment with the specified name. If the name is omitted,
601 the default name is the name of the function itself.
602 """
603 method = MethodWrapper(self, function, name)
604 self.added_methods.append(method)
605
607 """
608 Removes the specified function's MethodWrapper from the
609 added_methods list, so we don't re-bind it when making a clone.
610 """
611 self.added_methods = [dm for dm in self.added_methods if not dm.method is function]
612
614 """
615 Produce a modified environment whose variables are overridden by
616 the overrides dictionaries. "overrides" is a dictionary that
617 will override the variables of this environment.
618
619 This function is much more efficient than Clone() or creating
620 a new Environment because it doesn't copy the construction
621 environment dictionary, it just wraps the underlying construction
622 environment, and doesn't even create a wrapper object if there
623 are no overrides.
624 """
625 if not overrides: return self
626 o = copy_non_reserved_keywords(overrides)
627 if not o: return self
628 overrides = {}
629 merges = None
630 for key, value in o.items():
631 if key == 'parse_flags':
632 merges = value
633 else:
634 overrides[key] = SCons.Subst.scons_subst_once(value, self, key)
635 env = OverrideEnvironment(self, overrides)
636 if merges: env.MergeFlags(merges)
637 return env
638
640 """
641 Parse the set of flags and return a dict with the flags placed
642 in the appropriate entry. The flags are treated as a typical
643 set of command-line flags for a GNU-like toolchain and used to
644 populate the entries in the dict immediately below. If one of
645 the flag strings begins with a bang (exclamation mark), it is
646 assumed to be a command and the rest of the string is executed;
647 the result of that evaluation is then added to the dict.
648 """
649 dict = {
650 'ASFLAGS' : SCons.Util.CLVar(''),
651 'CFLAGS' : SCons.Util.CLVar(''),
652 'CCFLAGS' : SCons.Util.CLVar(''),
653 'CXXFLAGS' : SCons.Util.CLVar(''),
654 'CPPDEFINES' : [],
655 'CPPFLAGS' : SCons.Util.CLVar(''),
656 'CPPPATH' : [],
657 'FRAMEWORKPATH' : SCons.Util.CLVar(''),
658 'FRAMEWORKS' : SCons.Util.CLVar(''),
659 'LIBPATH' : [],
660 'LIBS' : [],
661 'LINKFLAGS' : SCons.Util.CLVar(''),
662 'RPATH' : [],
663 }
664
665 def do_parse(arg):
666
667 if not arg:
668 return
669
670 if not SCons.Util.is_String(arg):
671 for t in arg: do_parse(t)
672 return
673
674
675 if arg[0] == '!':
676 arg = self.backtick(arg[1:])
677
678
679 def append_define(name, dict = dict):
680 t = name.split('=')
681 if len(t) == 1:
682 dict['CPPDEFINES'].append(name)
683 else:
684 dict['CPPDEFINES'].append([t[0], '='.join(t[1:])])
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706 params = shlex.split(arg)
707 append_next_arg_to = None
708 for arg in params:
709 if append_next_arg_to:
710 if append_next_arg_to == 'CPPDEFINES':
711 append_define(arg)
712 elif append_next_arg_to == '-include':
713 t = ('-include', self.fs.File(arg))
714 dict['CCFLAGS'].append(t)
715 elif append_next_arg_to == '-isysroot':
716 t = ('-isysroot', arg)
717 dict['CCFLAGS'].append(t)
718 dict['LINKFLAGS'].append(t)
719 elif append_next_arg_to == '-isystem':
720 t = ('-isystem', arg)
721 dict['CCFLAGS'].append(t)
722 elif append_next_arg_to == '-arch':
723 t = ('-arch', arg)
724 dict['CCFLAGS'].append(t)
725 dict['LINKFLAGS'].append(t)
726 else:
727 dict[append_next_arg_to].append(arg)
728 append_next_arg_to = None
729 elif not arg[0] in ['-', '+']:
730 dict['LIBS'].append(self.fs.File(arg))
731 elif arg == '-dylib_file':
732 dict['LINKFLAGS'].append(arg)
733 append_next_arg_to = 'LINKFLAGS'
734 elif arg[:2] == '-L':
735 if arg[2:]:
736 dict['LIBPATH'].append(arg[2:])
737 else:
738 append_next_arg_to = 'LIBPATH'
739 elif arg[:2] == '-l':
740 if arg[2:]:
741 dict['LIBS'].append(arg[2:])
742 else:
743 append_next_arg_to = 'LIBS'
744 elif arg[:2] == '-I':
745 if arg[2:]:
746 dict['CPPPATH'].append(arg[2:])
747 else:
748 append_next_arg_to = 'CPPPATH'
749 elif arg[:4] == '-Wa,':
750 dict['ASFLAGS'].append(arg[4:])
751 dict['CCFLAGS'].append(arg)
752 elif arg[:4] == '-Wl,':
753 if arg[:11] == '-Wl,-rpath=':
754 dict['RPATH'].append(arg[11:])
755 elif arg[:7] == '-Wl,-R,':
756 dict['RPATH'].append(arg[7:])
757 elif arg[:6] == '-Wl,-R':
758 dict['RPATH'].append(arg[6:])
759 else:
760 dict['LINKFLAGS'].append(arg)
761 elif arg[:4] == '-Wp,':
762 dict['CPPFLAGS'].append(arg)
763 elif arg[:2] == '-D':
764 if arg[2:]:
765 append_define(arg[2:])
766 else:
767 append_next_arg_to = 'CPPDEFINES'
768 elif arg == '-framework':
769 append_next_arg_to = 'FRAMEWORKS'
770 elif arg[:14] == '-frameworkdir=':
771 dict['FRAMEWORKPATH'].append(arg[14:])
772 elif arg[:2] == '-F':
773 if arg[2:]:
774 dict['FRAMEWORKPATH'].append(arg[2:])
775 else:
776 append_next_arg_to = 'FRAMEWORKPATH'
777 elif arg in ['-mno-cygwin',
778 '-pthread',
779 '-openmp',
780 '-fopenmp']:
781 dict['CCFLAGS'].append(arg)
782 dict['LINKFLAGS'].append(arg)
783 elif arg == '-mwindows':
784 dict['LINKFLAGS'].append(arg)
785 elif arg[:5] == '-std=':
786 if arg[5:].find('++')!=-1:
787 key='CXXFLAGS'
788 else:
789 key='CFLAGS'
790 dict[key].append(arg)
791 elif arg[0] == '+':
792 dict['CCFLAGS'].append(arg)
793 dict['LINKFLAGS'].append(arg)
794 elif arg in ['-include', '-isysroot', '-isystem', '-arch']:
795 append_next_arg_to = arg
796 else:
797 dict['CCFLAGS'].append(arg)
798
799 for arg in flags:
800 do_parse(arg)
801 return dict
802
804 """
805 Merge the dict in args into the construction variables of this
806 env, or the passed-in dict. If args is not a dict, it is
807 converted into a dict using ParseFlags. If unique is not set,
808 the flags are appended rather than merged.
809 """
810
811 if dict is None:
812 dict = self
813 if not SCons.Util.is_Dict(args):
814 args = self.ParseFlags(args)
815 if not unique:
816 self.Append(**args)
817 return self
818 for key, value in args.items():
819 if not value:
820 continue
821 try:
822 orig = self[key]
823 except KeyError:
824 orig = value
825 else:
826 if not orig:
827 orig = value
828 elif value:
829
830
831
832
833
834
835 try:
836 orig = orig + value
837 except (KeyError, TypeError):
838 try:
839 add_to_orig = orig.append
840 except AttributeError:
841 value.insert(0, orig)
842 orig = value
843 else:
844 add_to_orig(value)
845 t = []
846 if key[-4:] == 'PATH':
847
848 for v in orig:
849 if v not in t:
850 t.append(v)
851 else:
852
853 orig.reverse()
854 for v in orig:
855 if v not in t:
856 t.insert(0, v)
857 self[key] = t
858 return self
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880 -def default_decide_source(dependency, target, prev_ni):
881 f = SCons.Defaults.DefaultEnvironment().decide_source
882 return f(dependency, target, prev_ni)
883
885 f = SCons.Defaults.DefaultEnvironment().decide_target
886 return f(dependency, target, prev_ni)
887
889 f = SCons.Defaults.DefaultEnvironment().copy_from_cache
890 return f(src, dst)
891
892 -class Base(SubstitutionEnvironment):
893 """Base class for "real" construction Environments. These are the
894 primary objects used to communicate dependency and construction
895 information to the build engine.
896
897 Keyword arguments supplied when the construction Environment
898 is created are construction variables used to initialize the
899 Environment.
900 """
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916 - def __init__(self,
917 platform=None,
918 tools=None,
919 toolpath=None,
920 variables=None,
921 parse_flags = None,
922 **kw):
923 """
924 Initialization of a basic SCons construction environment,
925 including setting up special construction variables like BUILDER,
926 PLATFORM, etc., and searching for and applying available Tools.
927
928 Note that we do *not* call the underlying base class
929 (SubsitutionEnvironment) initialization, because we need to
930 initialize things in a very specific order that doesn't work
931 with the much simpler base class initialization.
932 """
933 if SCons.Debug.track_instances: logInstanceCreation(self, 'Environment.Base')
934 self._memo = {}
935 self.fs = SCons.Node.FS.get_default_fs()
936 self.ans = SCons.Node.Alias.default_ans
937 self.lookup_list = SCons.Node.arg2nodes_lookups
938 self._dict = semi_deepcopy(SCons.Defaults.ConstructionEnvironment)
939 self._init_special()
940 self.added_methods = []
941
942
943
944
945
946
947
948 self.decide_target = default_decide_target
949 self.decide_source = default_decide_source
950
951 self.copy_from_cache = default_copy_from_cache
952
953 self._dict['BUILDERS'] = BuilderDict(self._dict['BUILDERS'], self)
954
955 if platform is None:
956 platform = self._dict.get('PLATFORM', None)
957 if platform is None:
958 platform = SCons.Platform.Platform()
959 if SCons.Util.is_String(platform):
960 platform = SCons.Platform.Platform(platform)
961 self._dict['PLATFORM'] = str(platform)
962 platform(self)
963
964 self._dict['HOST_OS'] = self._dict.get('HOST_OS',None)
965 self._dict['HOST_ARCH'] = self._dict.get('HOST_ARCH',None)
966
967
968 self._dict['TARGET_OS'] = self._dict.get('TARGET_OS',None)
969 self._dict['TARGET_ARCH'] = self._dict.get('TARGET_ARCH',None)
970
971
972
973
974
975 if 'options' in kw:
976
977
978 variables = kw['options']
979 del kw['options']
980 self.Replace(**kw)
981 keys = list(kw.keys())
982 if variables:
983 keys = keys + list(variables.keys())
984 variables.Update(self)
985
986 save = {}
987 for k in keys:
988 try:
989 save[k] = self._dict[k]
990 except KeyError:
991
992
993 pass
994
995 SCons.Tool.Initializers(self)
996
997 if tools is None:
998 tools = self._dict.get('TOOLS', None)
999 if tools is None:
1000 tools = ['default']
1001 apply_tools(self, tools, toolpath)
1002
1003
1004
1005
1006 for key, val in save.items():
1007 self._dict[key] = val
1008
1009
1010 if parse_flags: self.MergeFlags(parse_flags)
1011
1012
1013
1014
1015
1016
1018 """Fetch the builder with the specified name from the environment.
1019 """
1020 try:
1021 return self._dict['BUILDERS'][name]
1022 except KeyError:
1023 return None
1024
1039
1041 """Return a factory function for creating Nodes for this
1042 construction environment.
1043 """
1044 name = default
1045 try:
1046 is_node = issubclass(factory, SCons.Node.FS.Base)
1047 except TypeError:
1048
1049
1050 pass
1051 else:
1052 if is_node:
1053
1054
1055
1056
1057 try: name = factory.__name__
1058 except AttributeError: pass
1059 else: factory = None
1060 if not factory:
1061
1062
1063
1064
1065
1066 factory = getattr(self.fs, name)
1067 return factory
1068
1069 @SCons.Memoize.CountMethodCall
1071 try:
1072 return self._memo['_gsm']
1073 except KeyError:
1074 pass
1075
1076 result = {}
1077
1078 try:
1079 scanners = self._dict['SCANNERS']
1080 except KeyError:
1081 pass
1082 else:
1083
1084
1085
1086
1087 if not SCons.Util.is_List(scanners):
1088 scanners = [scanners]
1089 else:
1090 scanners = scanners[:]
1091 scanners.reverse()
1092 for scanner in scanners:
1093 for k in scanner.get_skeys(self):
1094 if k and self['PLATFORM'] == 'win32':
1095 k = k.lower()
1096 result[k] = scanner
1097
1098 self._memo['_gsm'] = result
1099
1100 return result
1101
1103 """Find the appropriate scanner given a key (usually a file suffix).
1104 """
1105 if skey and self['PLATFORM'] == 'win32':
1106 skey = skey.lower()
1107 return self._gsm().get(skey)
1108
1110 """Delete the cached scanner map (if we need to).
1111 """
1112 try:
1113 del self._memo['_gsm']
1114 except KeyError:
1115 pass
1116
1118 """Update an environment's values directly, bypassing the normal
1119 checks that occur when users try to set items.
1120 """
1121 self._dict.update(dict)
1122
1124 try:
1125 return self.src_sig_type
1126 except AttributeError:
1127 t = SCons.Defaults.DefaultEnvironment().src_sig_type
1128 self.src_sig_type = t
1129 return t
1130
1132 try:
1133 return self.tgt_sig_type
1134 except AttributeError:
1135 t = SCons.Defaults.DefaultEnvironment().tgt_sig_type
1136 self.tgt_sig_type = t
1137 return t
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1149 """Append values to existing construction variables
1150 in an Environment.
1151 """
1152 kw = copy_non_reserved_keywords(kw)
1153 for key, val in kw.items():
1154
1155
1156
1157
1158 try:
1159 if key == 'CPPDEFINES' and SCons.Util.is_String(self._dict[key]):
1160 self._dict[key] = [self._dict[key]]
1161 orig = self._dict[key]
1162 except KeyError:
1163
1164
1165 if key == 'CPPDEFINES' and SCons.Util.is_String(val):
1166 self._dict[key] = [val]
1167 else:
1168 self._dict[key] = val
1169 else:
1170 try:
1171
1172
1173
1174
1175
1176 update_dict = orig.update
1177 except AttributeError:
1178 try:
1179
1180
1181
1182 self._dict[key] = orig + val
1183 except (KeyError, TypeError):
1184 try:
1185
1186 add_to_orig = orig.append
1187 except AttributeError:
1188
1189
1190
1191
1192
1193 if orig:
1194 val.insert(0, orig)
1195 self._dict[key] = val
1196 else:
1197
1198
1199 if val:
1200 add_to_orig(val)
1201 else:
1202
1203
1204 if SCons.Util.is_List(val):
1205 if key == 'CPPDEFINES':
1206 tmp = []
1207 for (k, v) in orig.iteritems():
1208 if v is not None:
1209 tmp.append((k, v))
1210 else:
1211 tmp.append((k,))
1212 orig = tmp
1213 orig += val
1214 self._dict[key] = orig
1215 else:
1216 for v in val:
1217 orig[v] = None
1218 else:
1219 try:
1220 update_dict(val)
1221 except (AttributeError, TypeError, ValueError):
1222 if SCons.Util.is_Dict(val):
1223 for k, v in val.items():
1224 orig[k] = v
1225 else:
1226 orig[val] = None
1227 self.scanner_map_delete(kw)
1228
1229
1230
1237
1238 - def AppendENVPath(self, name, newpath, envname = 'ENV',
1239 sep = os.pathsep, delete_existing=1):
1240 """Append path elements to the path 'name' in the 'ENV'
1241 dictionary for this environment. Will only add any particular
1242 path once, and will normpath and normcase all paths to help
1243 assure this. This can also handle the case where the env
1244 variable is a list instead of a string.
1245
1246 If delete_existing is 0, a newpath which is already in the path
1247 will not be moved to the end (it will be left where it is).
1248 """
1249
1250 orig = ''
1251 if envname in self._dict and name in self._dict[envname]:
1252 orig = self._dict[envname][name]
1253
1254 nv = SCons.Util.AppendPath(orig, newpath, sep, delete_existing,
1255 canonicalize=self._canonicalize)
1256
1257 if envname not in self._dict:
1258 self._dict[envname] = {}
1259
1260 self._dict[envname][name] = nv
1261
1263 """Append values to existing construction variables
1264 in an Environment, if they're not already there.
1265 If delete_existing is 1, removes existing values first, so
1266 values move to end.
1267 """
1268 kw = copy_non_reserved_keywords(kw)
1269 for key, val in kw.items():
1270 if SCons.Util.is_List(val):
1271 val = _delete_duplicates(val, delete_existing)
1272 if key not in self._dict or self._dict[key] in ('', None):
1273 self._dict[key] = val
1274 elif SCons.Util.is_Dict(self._dict[key]) and \
1275 SCons.Util.is_Dict(val):
1276 self._dict[key].update(val)
1277 elif SCons.Util.is_List(val):
1278 dk = self._dict[key]
1279 if key == 'CPPDEFINES':
1280 tmp = []
1281 for i in val:
1282 if SCons.Util.is_List(i):
1283 if len(i) >= 2:
1284 tmp.append((i[0], i[1]))
1285 else:
1286 tmp.append((i[0],))
1287 elif SCons.Util.is_Tuple(i):
1288 tmp.append(i)
1289 else:
1290 tmp.append((i,))
1291 val = tmp
1292
1293 if SCons.Util.is_Dict(dk):
1294 tmp = []
1295 for (k, v) in dk.iteritems():
1296 if v is not None:
1297 tmp.append((k, v))
1298 else:
1299 tmp.append((k,))
1300 dk = tmp
1301 elif SCons.Util.is_String(dk):
1302 dk = [(dk,)]
1303 else:
1304 tmp = []
1305 for i in dk:
1306 if SCons.Util.is_List(i):
1307 if len(i) >= 2:
1308 tmp.append((i[0], i[1]))
1309 else:
1310 tmp.append((i[0],))
1311 elif SCons.Util.is_Tuple(i):
1312 tmp.append(i)
1313 else:
1314 tmp.append((i,))
1315 dk = tmp
1316 else:
1317 if not SCons.Util.is_List(dk):
1318 dk = [dk]
1319 if delete_existing:
1320 dk = [x for x in dk if x not in val]
1321 else:
1322 val = [x for x in val if x not in dk]
1323 self._dict[key] = dk + val
1324 else:
1325 dk = self._dict[key]
1326 if SCons.Util.is_List(dk):
1327 if key == 'CPPDEFINES':
1328 tmp = []
1329 for i in dk:
1330 if SCons.Util.is_List(i):
1331 if len(i) >= 2:
1332 tmp.append((i[0], i[1]))
1333 else:
1334 tmp.append((i[0],))
1335 elif SCons.Util.is_Tuple(i):
1336 tmp.append(i)
1337 else:
1338 tmp.append((i,))
1339 dk = tmp
1340
1341 if SCons.Util.is_Dict(val):
1342 tmp = []
1343 for (k, v) in val.iteritems():
1344 if v is not None:
1345 tmp.append((k, v))
1346 else:
1347 tmp.append((k,))
1348 val = tmp
1349 elif SCons.Util.is_String(val):
1350 val = [(val,)]
1351 if delete_existing:
1352 dk = filter(lambda x, val=val: x not in val, dk)
1353 self._dict[key] = dk + val
1354 else:
1355 dk = [x for x in dk if x not in val]
1356 self._dict[key] = dk + val
1357 else:
1358
1359
1360 if delete_existing:
1361 dk = filter(lambda x, val=val: x not in val, dk)
1362 self._dict[key] = dk + [val]
1363 else:
1364 if not val in dk:
1365 self._dict[key] = dk + [val]
1366 else:
1367 if key == 'CPPDEFINES':
1368 if SCons.Util.is_String(dk):
1369 dk = [dk]
1370 elif SCons.Util.is_Dict(dk):
1371 tmp = []
1372 for (k, v) in dk.iteritems():
1373 if v is not None:
1374 tmp.append((k, v))
1375 else:
1376 tmp.append((k,))
1377 dk = tmp
1378 if SCons.Util.is_String(val):
1379 if val in dk:
1380 val = []
1381 else:
1382 val = [val]
1383 elif SCons.Util.is_Dict(val):
1384 tmp = []
1385 for i,j in val.iteritems():
1386 if j is not None:
1387 tmp.append((i,j))
1388 else:
1389 tmp.append(i)
1390 val = tmp
1391 if delete_existing:
1392 dk = [x for x in dk if x not in val]
1393 self._dict[key] = dk + val
1394 self.scanner_map_delete(kw)
1395
1396 - def Clone(self, tools=[], toolpath=None, parse_flags = None, **kw):
1397 """Return a copy of a construction Environment. The
1398 copy is like a Python "deep copy"--that is, independent
1399 copies are made recursively of each objects--except that
1400 a reference is copied when an object is not deep-copyable
1401 (like a function). There are no references to any mutable
1402 objects in the original Environment.
1403 """
1404
1405 builders = self._dict.get('BUILDERS', {})
1406
1407 clone = copy.copy(self)
1408
1409 clone._dict = semi_deepcopy_dict(self._dict, ['BUILDERS'])
1410 clone._dict['BUILDERS'] = BuilderDict(builders, clone)
1411
1412
1413
1414
1415
1416 clone.added_methods = []
1417 for mw in self.added_methods:
1418 if mw == getattr(self, mw.name):
1419 clone.added_methods.append(mw.clone(clone))
1420
1421 clone._memo = {}
1422
1423
1424
1425 kw = copy_non_reserved_keywords(kw)
1426 new = {}
1427 for key, value in kw.items():
1428 new[key] = SCons.Subst.scons_subst_once(value, self, key)
1429 clone.Replace(**new)
1430
1431 apply_tools(clone, tools, toolpath)
1432
1433
1434 clone.Replace(**new)
1435
1436
1437 if parse_flags: clone.MergeFlags(parse_flags)
1438
1439 if SCons.Debug.track_instances: logInstanceCreation(self, 'Environment.EnvironmentClone')
1440 return clone
1441
1442 - def Copy(self, *args, **kw):
1449
1451 if dependency.changed_state(target, prev_ni):
1452 return 1
1453 return self.decide_source(dependency, target, prev_ni)
1454
1455 - def _changed_content(self, dependency, target, prev_ni):
1456 return dependency.changed_content(target, prev_ni)
1457
1459 target_env = dependency.get_build_env()
1460 type = target_env.get_tgt_sig_type()
1461 if type == 'source':
1462 return target_env.decide_source(dependency, target, prev_ni)
1463 else:
1464 return target_env.decide_target(dependency, target, prev_ni)
1465
1466 - def _changed_timestamp_then_content(self, dependency, target, prev_ni):
1467 return dependency.changed_timestamp_then_content(target, prev_ni)
1468
1471
1474
1476 return self.fs.copy(src, dst)
1477
1479 return self.fs.copy2(src, dst)
1480
1504
1506 """Return the first available program in progs.
1507 """
1508 if not SCons.Util.is_List(progs):
1509 progs = [ progs ]
1510 for prog in progs:
1511 path = self.WhereIs(prog)
1512 if path: return prog
1513 return None
1514
1516 if not args:
1517 return self._dict
1518 dlist = [self._dict[x] for x in args]
1519 if len(dlist) == 1:
1520 dlist = dlist[0]
1521 return dlist
1522
1523 - def Dump(self, key = None):
1524 """
1525 Using the standard Python pretty printer, return the contents of the
1526 scons build environment as a string.
1527
1528 If the key passed in is anything other than None, then that will
1529 be used as an index into the build environment dictionary and
1530 whatever is found there will be fed into the pretty printer. Note
1531 that this key is case sensitive.
1532 """
1533 import pprint
1534 pp = pprint.PrettyPrinter(indent=2)
1535 if key:
1536 dict = self.Dictionary(key)
1537 else:
1538 dict = self.Dictionary()
1539 return pp.pformat(dict)
1540
1541 - def FindIxes(self, paths, prefix, suffix):
1542 """
1543 Search a list of paths for something that matches the prefix and suffix.
1544
1545 paths - the list of paths or nodes.
1546 prefix - construction variable for the prefix.
1547 suffix - construction variable for the suffix.
1548 """
1549
1550 suffix = self.subst('$'+suffix)
1551 prefix = self.subst('$'+prefix)
1552
1553 for path in paths:
1554 dir,name = os.path.split(str(path))
1555 if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix:
1556 return path
1557
1558 - def ParseConfig(self, command, function=None, unique=1):
1559 """
1560 Use the specified function to parse the output of the command
1561 in order to modify the current environment. The 'command' can
1562 be a string or a list of strings representing a command and
1563 its arguments. 'Function' is an optional argument that takes
1564 the environment, the output of the command, and the unique flag.
1565 If no function is specified, MergeFlags, which treats the output
1566 as the result of a typical 'X-config' command (i.e. gtk-config),
1567 will merge the output into the appropriate variables.
1568 """
1569 if function is None:
1570 def parse_conf(env, cmd, unique=unique):
1571 return env.MergeFlags(cmd, unique)
1572 function = parse_conf
1573 if SCons.Util.is_List(command):
1574 command = ' '.join(command)
1575 command = self.subst(command)
1576 return function(self, self.backtick(command))
1577
1578 - def ParseDepends(self, filename, must_exist=None, only_one=0):
1579 """
1580 Parse a mkdep-style file for explicit dependencies. This is
1581 completely abusable, and should be unnecessary in the "normal"
1582 case of proper SCons configuration, but it may help make
1583 the transition from a Make hierarchy easier for some people
1584 to swallow. It can also be genuinely useful when using a tool
1585 that can write a .d file, but for which writing a scanner would
1586 be too complicated.
1587 """
1588 filename = self.subst(filename)
1589 try:
1590 fp = open(filename, 'r')
1591 except IOError:
1592 if must_exist:
1593 raise
1594 return
1595 lines = SCons.Util.LogicalLines(fp).readlines()
1596 lines = [l for l in lines if l[0] != '#']
1597 tdlist = []
1598 for line in lines:
1599 try:
1600 target, depends = line.split(':', 1)
1601 except (AttributeError, ValueError):
1602
1603
1604 pass
1605 else:
1606 tdlist.append((target.split(), depends.split()))
1607 if only_one:
1608 targets = []
1609 for td in tdlist:
1610 targets.extend(td[0])
1611 if len(targets) > 1:
1612 raise SCons.Errors.UserError(
1613 "More than one dependency target found in `%s': %s"
1614 % (filename, targets))
1615 for target, depends in tdlist:
1616 self.Depends(target, depends)
1617
1621
1623 """Prepend values to existing construction variables
1624 in an Environment.
1625 """
1626 kw = copy_non_reserved_keywords(kw)
1627 for key, val in kw.items():
1628
1629
1630
1631
1632 try:
1633 orig = self._dict[key]
1634 except KeyError:
1635
1636
1637 self._dict[key] = val
1638 else:
1639 try:
1640
1641
1642
1643
1644
1645 update_dict = orig.update
1646 except AttributeError:
1647 try:
1648
1649
1650
1651 self._dict[key] = val + orig
1652 except (KeyError, TypeError):
1653 try:
1654
1655 add_to_val = val.append
1656 except AttributeError:
1657
1658
1659
1660
1661 if val:
1662 orig.insert(0, val)
1663 else:
1664
1665
1666
1667 if orig:
1668 add_to_val(orig)
1669 self._dict[key] = val
1670 else:
1671
1672
1673 if SCons.Util.is_List(val):
1674 for v in val:
1675 orig[v] = None
1676 else:
1677 try:
1678 update_dict(val)
1679 except (AttributeError, TypeError, ValueError):
1680 if SCons.Util.is_Dict(val):
1681 for k, v in val.items():
1682 orig[k] = v
1683 else:
1684 orig[val] = None
1685 self.scanner_map_delete(kw)
1686
1687 - def PrependENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep,
1688 delete_existing=1):
1689 """Prepend path elements to the path 'name' in the 'ENV'
1690 dictionary for this environment. Will only add any particular
1691 path once, and will normpath and normcase all paths to help
1692 assure this. This can also handle the case where the env
1693 variable is a list instead of a string.
1694
1695 If delete_existing is 0, a newpath which is already in the path
1696 will not be moved to the front (it will be left where it is).
1697 """
1698
1699 orig = ''
1700 if envname in self._dict and name in self._dict[envname]:
1701 orig = self._dict[envname][name]
1702
1703 nv = SCons.Util.PrependPath(orig, newpath, sep, delete_existing,
1704 canonicalize=self._canonicalize)
1705
1706 if envname not in self._dict:
1707 self._dict[envname] = {}
1708
1709 self._dict[envname][name] = nv
1710
1712 """Prepend values to existing construction variables
1713 in an Environment, if they're not already there.
1714 If delete_existing is 1, removes existing values first, so
1715 values move to front.
1716 """
1717 kw = copy_non_reserved_keywords(kw)
1718 for key, val in kw.items():
1719 if SCons.Util.is_List(val):
1720 val = _delete_duplicates(val, not delete_existing)
1721 if key not in self._dict or self._dict[key] in ('', None):
1722 self._dict[key] = val
1723 elif SCons.Util.is_Dict(self._dict[key]) and \
1724 SCons.Util.is_Dict(val):
1725 self._dict[key].update(val)
1726 elif SCons.Util.is_List(val):
1727 dk = self._dict[key]
1728 if not SCons.Util.is_List(dk):
1729 dk = [dk]
1730 if delete_existing:
1731 dk = [x for x in dk if x not in val]
1732 else:
1733 val = [x for x in val if x not in dk]
1734 self._dict[key] = val + dk
1735 else:
1736 dk = self._dict[key]
1737 if SCons.Util.is_List(dk):
1738
1739
1740 if delete_existing:
1741 dk = [x for x in dk if x not in val]
1742 self._dict[key] = [val] + dk
1743 else:
1744 if not val in dk:
1745 self._dict[key] = [val] + dk
1746 else:
1747 if delete_existing:
1748 dk = [x for x in dk if x not in val]
1749 self._dict[key] = val + dk
1750 self.scanner_map_delete(kw)
1751
1753 """Replace existing construction variables in an Environment
1754 with new construction variables and/or values.
1755 """
1756 try:
1757 kwbd = kw['BUILDERS']
1758 except KeyError:
1759 pass
1760 else:
1761 kwbd = BuilderDict(kwbd,self)
1762 del kw['BUILDERS']
1763 self.__setitem__('BUILDERS', kwbd)
1764 kw = copy_non_reserved_keywords(kw)
1765 self._update(semi_deepcopy(kw))
1766 self.scanner_map_delete(kw)
1767
1768 - def ReplaceIxes(self, path, old_prefix, old_suffix, new_prefix, new_suffix):
1769 """
1770 Replace old_prefix with new_prefix and old_suffix with new_suffix.
1771
1772 env - Environment used to interpolate variables.
1773 path - the path that will be modified.
1774 old_prefix - construction variable for the old prefix.
1775 old_suffix - construction variable for the old suffix.
1776 new_prefix - construction variable for the new prefix.
1777 new_suffix - construction variable for the new suffix.
1778 """
1779 old_prefix = self.subst('$'+old_prefix)
1780 old_suffix = self.subst('$'+old_suffix)
1781
1782 new_prefix = self.subst('$'+new_prefix)
1783 new_suffix = self.subst('$'+new_suffix)
1784
1785 dir,name = os.path.split(str(path))
1786 if name[:len(old_prefix)] == old_prefix:
1787 name = name[len(old_prefix):]
1788 if name[-len(old_suffix):] == old_suffix:
1789 name = name[:-len(old_suffix)]
1790 return os.path.join(dir, new_prefix+name+new_suffix)
1791
1793 for k in kw.keys():
1794 if k in self._dict:
1795 del kw[k]
1796 self.Replace(**kw)
1797
1800
1809
1810 - def WhereIs(self, prog, path=None, pathext=None, reject=[]):
1811 """Find prog in the path.
1812 """
1813 if path is None:
1814 try:
1815 path = self['ENV']['PATH']
1816 except KeyError:
1817 pass
1818 elif SCons.Util.is_String(path):
1819 path = self.subst(path)
1820 if pathext is None:
1821 try:
1822 pathext = self['ENV']['PATHEXT']
1823 except KeyError:
1824 pass
1825 elif SCons.Util.is_String(pathext):
1826 pathext = self.subst(pathext)
1827 prog = SCons.Util.CLVar(self.subst(prog))
1828 path = SCons.Util.WhereIs(prog[0], path, pathext, reject)
1829 if path: return path
1830 return None
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840 - def Action(self, *args, **kw):
1841 def subst_string(a, self=self):
1842 if SCons.Util.is_String(a):
1843 a = self.subst(a)
1844 return a
1845 nargs = list(map(subst_string, args))
1846 nkw = self.subst_kw(kw)
1847 return SCons.Action.Action(*nargs, **nkw)
1848
1858
1859 - def AddPostAction(self, files, action):
1860 nodes = self.arg2nodes(files, self.fs.Entry)
1861 action = SCons.Action.Action(action)
1862 uniq = {}
1863 for executor in [n.get_executor() for n in nodes]:
1864 uniq[executor] = 1
1865 for executor in uniq.keys():
1866 executor.add_post_action(action)
1867 return nodes
1868
1869 - def Alias(self, target, source=[], action=None, **kw):
1921
1929
1937
1941
1947
1948 - def Clean(self, targets, files):
1957
1969
1970 - def Command(self, target, source, action, **kw):
1971 """Builds the supplied target files from the supplied
1972 source files using the supplied action. Action may
1973 be any type that the Builder constructor will accept
1974 for an action."""
1975 bkw = {
1976 'action' : action,
1977 'target_factory' : self.fs.Entry,
1978 'source_factory' : self.fs.Entry,
1979 }
1980 try: bkw['source_scanner'] = kw['source_scanner']
1981 except KeyError: pass
1982 else: del kw['source_scanner']
1983 bld = SCons.Builder.Builder(**bkw)
1984 return bld(self, target, source, **kw)
1985
1986 - def Depends(self, target, dependency):
1987 """Explicity specify that 'target's depend on 'dependency'."""
1988 tlist = self.arg2nodes(target, self.fs.Entry)
1989 dlist = self.arg2nodes(dependency, self.fs.Entry)
1990 for t in tlist:
1991 t.add_dependency(dlist)
1992 return tlist
1993
1994 - def Dir(self, name, *args, **kw):
2004
2006 """Tags a target so that it will not be cleaned by -c"""
2007 tlist = []
2008 for t in targets:
2009 tlist.extend(self.arg2nodes(t, self.fs.Entry))
2010 for t in tlist:
2011 t.set_noclean()
2012 return tlist
2013
2015 """Tags a target so that it will not be cached"""
2016 tlist = []
2017 for t in targets:
2018 tlist.extend(self.arg2nodes(t, self.fs.Entry))
2019 for t in tlist:
2020 t.set_nocache()
2021 return tlist
2022
2023 - def Entry(self, name, *args, **kw):
2024 """
2025 """
2026 s = self.subst(name)
2027 if SCons.Util.is_Sequence(s):
2028 result=[]
2029 for e in s:
2030 result.append(self.fs.Entry(e, *args, **kw))
2031 return result
2032 return self.fs.Entry(s, *args, **kw)
2033
2036
2037 - def Execute(self, action, *args, **kw):
2038 """Directly execute an action through an Environment
2039 """
2040 action = self.Action(action, *args, **kw)
2041 result = action([], [], self)
2042 if isinstance(result, SCons.Errors.BuildError):
2043 errstr = result.errstr
2044 if result.filename:
2045 errstr = result.filename + ': ' + errstr
2046 sys.stderr.write("scons: *** %s\n" % errstr)
2047 return result.status
2048 else:
2049 return result
2050
2051 - def File(self, name, *args, **kw):
2061
2066
2069
2076
2077 - def Glob(self, pattern, ondisk=True, source=False, strings=False, exclude=None):
2078 return self.fs.Glob(self.subst(pattern), ondisk, source, strings, exclude)
2079
2080 - def Ignore(self, target, dependency):
2087
2090
2091 - def Local(self, *targets):
2102
2110
2118
2122
2123 - def Requires(self, target, prerequisite):
2124 """Specify that 'prerequisite' must be built before 'target',
2125 (but 'target' does not actually depend on 'prerequisite'
2126 and need not be rebuilt if it changes)."""
2127 tlist = self.arg2nodes(target, self.fs.Entry)
2128 plist = self.arg2nodes(prerequisite, self.fs.Entry)
2129 for t in tlist:
2130 t.add_prerequisite(plist)
2131 return tlist
2132
2141
2142 - def SConsignFile(self, name=".sconsign", dbm_module=None):
2153
2169
2179
2197
2199 """This function converts a string or list into a list of strings
2200 or Nodes. This makes things easier for users by allowing files to
2201 be specified as a white-space separated list to be split.
2202 The input rules are:
2203 - A single string containing names separated by spaces. These will be
2204 split apart at the spaces.
2205 - A single Node instance
2206 - A list containing either strings or Node instances. Any strings
2207 in the list are not split at spaces.
2208 In all cases, the function returns a list of Nodes and strings."""
2209 if SCons.Util.is_List(arg):
2210 return list(map(self.subst, arg))
2211 elif SCons.Util.is_String(arg):
2212 return self.subst(arg).split()
2213 else:
2214 return [self.subst(arg)]
2215
2237
2238 - def Value(self, value, built_value=None):
2242
2243 - def VariantDir(self, variant_dir, src_dir, duplicate=1):
2247
2262 build_source(node.all_children())
2263
2264 def final_source(node):
2265 while (node != node.srcnode()):
2266 node = node.srcnode()
2267 return node
2268 sources = map( final_source, sources );
2269
2270 return list(set(sources))
2271
2273 """ returns the list of all targets of the Install and InstallAs Builder.
2274 """
2275 from SCons.Tool import install
2276 if install._UNIQUE_INSTALLED_FILES is None:
2277 install._UNIQUE_INSTALLED_FILES = SCons.Util.uniquer_hashables(install._INSTALLED_FILES)
2278 return install._UNIQUE_INSTALLED_FILES
2279
2282 """A proxy that overrides variables in a wrapped construction
2283 environment by returning values from an overrides dictionary in
2284 preference to values from the underlying subject environment.
2285
2286 This is a lightweight (I hope) proxy that passes through most use of
2287 attributes to the underlying Environment.Base class, but has just
2288 enough additional methods defined to act like a real construction
2289 environment with overridden values. It can wrap either a Base
2290 construction environment, or another OverrideEnvironment, which
2291 can in turn nest arbitrary OverrideEnvironments...
2292
2293 Note that we do *not* call the underlying base class
2294 (SubsitutionEnvironment) initialization, because we get most of those
2295 from proxying the attributes of the subject construction environment.
2296 But because we subclass SubstitutionEnvironment, this class also
2297 has inherited arg2nodes() and subst*() methods; those methods can't
2298 be proxied because they need *this* object's methods to fetch the
2299 values from the overrides dictionary.
2300 """
2301
2302 - def __init__(self, subject, overrides={}):
2306
2307
2309 return getattr(self.__dict__['__subject'], name)
2311 setattr(self.__dict__['__subject'], name, value)
2312
2313
2315 try:
2316 return self.__dict__['overrides'][key]
2317 except KeyError:
2318 return self.__dict__['__subject'].__getitem__(key)
2324 try:
2325 del self.__dict__['overrides'][key]
2326 except KeyError:
2327 deleted = 0
2328 else:
2329 deleted = 1
2330 try:
2331 result = self.__dict__['__subject'].__delitem__(key)
2332 except KeyError:
2333 if not deleted:
2334 raise
2335 result = None
2336 return result
2337 - def get(self, key, default=None):
2338 """Emulates the get() method of dictionaries."""
2339 try:
2340 return self.__dict__['overrides'][key]
2341 except KeyError:
2342 return self.__dict__['__subject'].get(key, default)
2344 try:
2345 self.__dict__['overrides'][key]
2346 return 1
2347 except KeyError:
2348 return key in self.__dict__['__subject']
2354 """Emulates the items() method of dictionaries."""
2355 d = self.__dict__['__subject'].Dictionary().copy()
2356 d.update(self.__dict__['overrides'])
2357 return d
2359 """Emulates the items() method of dictionaries."""
2360 return list(self.Dictionary().items())
2361
2362
2364 """Update an environment's values directly, bypassing the normal
2365 checks that occur when users try to set items.
2366 """
2367 self.__dict__['overrides'].update(dict)
2368
2370 return self.__dict__['__subject'].gvars()
2371
2376
2377
2381
2382
2383
2384
2385
2386
2387
2388 Environment = Base
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402 -def NoSubstitutionProxy(subject):
2403 class _NoSubstitutionProxy(Environment):
2404 def __init__(self, subject):
2405 self.__dict__['__subject'] = subject
2406 def __getattr__(self, name):
2407 return getattr(self.__dict__['__subject'], name)
2408 def __setattr__(self, name, value):
2409 return setattr(self.__dict__['__subject'], name, value)
2410 def executor_to_lvars(self, kwdict):
2411 if kwdict.has_key('executor'):
2412 kwdict['lvars'] = kwdict['executor'].get_lvars()
2413 del kwdict['executor']
2414 else:
2415 kwdict['lvars'] = {}
2416 def raw_to_mode(self, dict):
2417 try:
2418 raw = dict['raw']
2419 except KeyError:
2420 pass
2421 else:
2422 del dict['raw']
2423 dict['mode'] = raw
2424 def subst(self, string, *args, **kwargs):
2425 return string
2426 def subst_kw(self, kw, *args, **kwargs):
2427 return kw
2428 def subst_list(self, string, *args, **kwargs):
2429 nargs = (string, self,) + args
2430 nkw = kwargs.copy()
2431 nkw['gvars'] = {}
2432 self.executor_to_lvars(nkw)
2433 self.raw_to_mode(nkw)
2434 return SCons.Subst.scons_subst_list(*nargs, **nkw)
2435 def subst_target_source(self, string, *args, **kwargs):
2436 nargs = (string, self,) + args
2437 nkw = kwargs.copy()
2438 nkw['gvars'] = {}
2439 self.executor_to_lvars(nkw)
2440 self.raw_to_mode(nkw)
2441 return SCons.Subst.scons_subst(*nargs, **nkw)
2442 return _NoSubstitutionProxy(subject)
2443
2444
2445
2446
2447
2448
2449