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
35 __revision__ = "src/engine/SCons/Environment.py 4720 2010/03/24 03:14:11 jars"
36
37
38 import copy
39 import os
40 import sys
41 import re
42 import shlex
43 import string
44 from UserDict import UserDict
45
46 import SCons.Action
47 import SCons.Builder
48 from SCons.Debug import logInstanceCreation
49 import SCons.Defaults
50 import SCons.Errors
51 import SCons.Memoize
52 import SCons.Node
53 import SCons.Node.Alias
54 import SCons.Node.FS
55 import SCons.Node.Python
56 import SCons.Platform
57 import SCons.SConf
58 import SCons.SConsign
59 import SCons.Subst
60 import SCons.Tool
61 import SCons.Util
62 import SCons.Warnings
63
66
67 _null = _Null
68
69 _warn_copy_deprecated = True
70 _warn_source_signatures_deprecated = True
71 _warn_target_signatures_deprecated = True
72
73 CleanTargets = {}
74 CalculatorArgs = {}
75
76 semi_deepcopy = SCons.Util.semi_deepcopy
77
78
79
80
81 UserError = SCons.Errors.UserError
82
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')
92
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 ]
128
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 not seen.has_key(i):
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
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):
221
223 nargs = (self.object,) + args
224 return apply(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 apply(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
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."""
301
302
303
304 self.env = env
305 UserDict.__init__(self, dict)
306
308 return self.__class__(self.data, self.env)
309
311 try:
312 method = getattr(self.env, item).method
313 except AttributeError:
314 pass
315 else:
316 self.env.RemoveMethod(method)
317 UserDict.__setitem__(self, item, val)
318 BuilderWrapper(self.env, val, item)
319
321 UserDict.__delitem__(self, item)
322 delattr(self.env, item)
323
327
328
329
330 _is_valid_var = re.compile(r'[_a-zA-Z]\w*$')
331
333 """Return if the specified string is a legitimate construction
334 variable.
335 """
336 return _is_valid_var.match(varstr)
337
338
339
341 """Base class for different flavors of construction environments.
342
343 This class contains a minimal set of methods that handle contruction
344 variable expansion and conversion of strings to Nodes, which may or
345 may not be actually useful as a stand-alone class. Which methods
346 ended up in this class is pretty arbitrary right now. They're
347 basically the ones which we've empirically determined are common to
348 the different construction environment subclasses, and most of the
349 others that use or touch the underlying dictionary of construction
350 variables.
351
352 Eventually, this class should contain all the methods that we
353 determine are necessary for a "minimal" interface to the build engine.
354 A full "native Python" SCons environment has gotten pretty heavyweight
355 with all of the methods and Tools and construction variables we've
356 jammed in there, so it would be nice to have a lighter weight
357 alternative for interfaces that don't need all of the bells and
358 whistles. (At some point, we'll also probably rename this class
359 "Base," since that more reflects what we want this class to become,
360 but because we've released comments that tell people to subclass
361 Environment.Base to create their own flavors of construction
362 environment, we'll save that for a future refactoring when this
363 class actually becomes useful.)
364 """
365
366 if SCons.Memoize.use_memoizer:
367 __metaclass__ = SCons.Memoize.Memoized_Metaclass
368
379
380
399
401 return cmp(self._dict, other._dict)
402
404 special = self._special_del.get(key)
405 if special:
406 special(self, key)
407 else:
408 del self._dict[key]
409
411 return self._dict[key]
412
414
415
416
417
418
419
420
421
422
423
424
425
426 if key in self._special_set_keys:
427 self._special_set[key](self, key, value)
428 else:
429
430
431
432
433 if not self._dict.has_key(key) \
434 and not _is_valid_var.match(key):
435 raise SCons.Errors.UserError, "Illegal construction variable `%s'" % key
436 self._dict[key] = value
437
438 - def get(self, key, default=None):
439 """Emulates the get() method of dictionaries."""
440 return self._dict.get(key, default)
441
444
447
449 return self._dict.items()
450
452 if node_factory is _null:
453 node_factory = self.fs.File
454 if lookup_list is _null:
455 lookup_list = self.lookup_list
456
457 if not args:
458 return []
459
460 args = SCons.Util.flatten(args)
461
462 nodes = []
463 for v in args:
464 if SCons.Util.is_String(v):
465 n = None
466 for l in lookup_list:
467 n = l(v)
468 if n is not None:
469 break
470 if n is not None:
471 if SCons.Util.is_String(n):
472
473 kw['raw'] = 1
474 n = apply(self.subst, (n,), kw)
475 if node_factory:
476 n = node_factory(n)
477 if SCons.Util.is_List(n):
478 nodes.extend(n)
479 else:
480 nodes.append(n)
481 elif node_factory:
482
483 kw['raw'] = 1
484 v = node_factory(apply(self.subst, (v,), kw))
485 if SCons.Util.is_List(v):
486 nodes.extend(v)
487 else:
488 nodes.append(v)
489 else:
490 nodes.append(v)
491
492 return nodes
493
496
499
500 - def subst(self, string, raw=0, target=None, source=None, conv=None, executor=None):
501 """Recursively interpolates construction variables from the
502 Environment into the specified string, returning the expanded
503 result. Construction variables are specified by a $ prefix
504 in the string and begin with an initial underscore or
505 alphabetic character followed by any number of underscores
506 or alphanumeric characters. The construction variable names
507 may be surrounded by curly braces to separate the name from
508 trailing characters.
509 """
510 gvars = self.gvars()
511 lvars = self.lvars()
512 lvars['__env__'] = self
513 if executor:
514 lvars.update(executor.get_lvars())
515 return SCons.Subst.scons_subst(string, self, raw, target, source, gvars, lvars, conv)
516
517 - def subst_kw(self, kw, raw=0, target=None, source=None):
518 nkw = {}
519 for k, v in kw.items():
520 k = self.subst(k, raw, target, source)
521 if SCons.Util.is_String(v):
522 v = self.subst(v, raw, target, source)
523 nkw[k] = v
524 return nkw
525
526 - def subst_list(self, string, raw=0, target=None, source=None, conv=None, executor=None):
535
536 - def subst_path(self, path, target=None, source=None):
537 """Substitute a path list, turning EntryProxies into Nodes
538 and leaving Nodes (and other objects) as-is."""
539
540 if not SCons.Util.is_List(path):
541 path = [path]
542
543 def s(obj):
544 """This is the "string conversion" routine that we have our
545 substitutions use to return Nodes, not strings. This relies
546 on the fact that an EntryProxy object has a get() method that
547 returns the underlying Node that it wraps, which is a bit of
548 architectural dependence that we might need to break or modify
549 in the future in response to additional requirements."""
550 try:
551 get = obj.get
552 except AttributeError:
553 obj = SCons.Util.to_String_for_subst(obj)
554 else:
555 obj = get()
556 return obj
557
558 r = []
559 for p in path:
560 if SCons.Util.is_String(p):
561 p = self.subst(p, target=target, source=source, conv=s)
562 if SCons.Util.is_List(p):
563 if len(p) == 1:
564 p = p[0]
565 else:
566
567
568
569 p = string.join(map(SCons.Util.to_String_for_subst, p), '')
570 else:
571 p = s(p)
572 r.append(p)
573 return r
574
575 subst_target_source = subst
576
578 import subprocess
579
580 kw = { 'stdin' : 'devnull',
581 'stdout' : subprocess.PIPE,
582 'stderr' : subprocess.PIPE,
583 'universal_newlines' : True,
584 }
585
586
587 if not SCons.Util.is_List(command): kw['shell'] = True
588
589
590 p = apply(SCons.Action._subproc, (self, command), kw)
591 out,err = p.communicate()
592 status = p.wait()
593 if err:
594 sys.stderr.write(err)
595 if status:
596 raise OSError("'%s' exited %d" % (command, status))
597 return out
598
600 """
601 Adds the specified function as a method of this construction
602 environment with the specified name. If the name is omitted,
603 the default name is the name of the function itself.
604 """
605 method = MethodWrapper(self, function, name)
606 self.added_methods.append(method)
607
609 """
610 Removes the specified function's MethodWrapper from the
611 added_methods list, so we don't re-bind it when making a clone.
612 """
613 is_not_func = lambda dm, f=function: not dm.method is f
614 self.added_methods = filter(is_not_func, self.added_methods)
615
617 """
618 Produce a modified environment whose variables are overriden by
619 the overrides dictionaries. "overrides" is a dictionary that
620 will override the variables of this environment.
621
622 This function is much more efficient than Clone() or creating
623 a new Environment because it doesn't copy the construction
624 environment dictionary, it just wraps the underlying construction
625 environment, and doesn't even create a wrapper object if there
626 are no overrides.
627 """
628 if not overrides: return self
629 o = copy_non_reserved_keywords(overrides)
630 if not o: return self
631 overrides = {}
632 merges = None
633 for key, value in o.items():
634 if key == 'parse_flags':
635 merges = value
636 else:
637 overrides[key] = SCons.Subst.scons_subst_once(value, self, key)
638 env = OverrideEnvironment(self, overrides)
639 if merges: env.MergeFlags(merges)
640 return env
641
643 """
644 Parse the set of flags and return a dict with the flags placed
645 in the appropriate entry. The flags are treated as a typical
646 set of command-line flags for a GNU-like toolchain and used to
647 populate the entries in the dict immediately below. If one of
648 the flag strings begins with a bang (exclamation mark), it is
649 assumed to be a command and the rest of the string is executed;
650 the result of that evaluation is then added to the dict.
651 """
652 dict = {
653 'ASFLAGS' : SCons.Util.CLVar(''),
654 'CFLAGS' : SCons.Util.CLVar(''),
655 'CCFLAGS' : SCons.Util.CLVar(''),
656 'CPPDEFINES' : [],
657 'CPPFLAGS' : SCons.Util.CLVar(''),
658 'CPPPATH' : [],
659 'FRAMEWORKPATH' : SCons.Util.CLVar(''),
660 'FRAMEWORKS' : SCons.Util.CLVar(''),
661 'LIBPATH' : [],
662 'LIBS' : [],
663 'LINKFLAGS' : SCons.Util.CLVar(''),
664 'RPATH' : [],
665 }
666
667
668
669 def do_parse(arg, me, self = self, dict = dict):
670
671 if not arg:
672 return
673
674 if not SCons.Util.is_String(arg):
675 for t in arg: me(t, me)
676 return
677
678
679 if arg[0] == '!':
680 arg = self.backtick(arg[1:])
681
682
683 def append_define(name, dict = dict):
684 t = string.split(name, '=')
685 if len(t) == 1:
686 dict['CPPDEFINES'].append(name)
687 else:
688 dict['CPPDEFINES'].append([t[0], string.join(t[1:], '=')])
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710 params = shlex.split(arg)
711 append_next_arg_to = None
712 for arg in params:
713 if append_next_arg_to:
714 if append_next_arg_to == 'CPPDEFINES':
715 append_define(arg)
716 elif append_next_arg_to == '-include':
717 t = ('-include', self.fs.File(arg))
718 dict['CCFLAGS'].append(t)
719 elif append_next_arg_to == '-isysroot':
720 t = ('-isysroot', arg)
721 dict['CCFLAGS'].append(t)
722 dict['LINKFLAGS'].append(t)
723 elif append_next_arg_to == '-arch':
724 t = ('-arch', arg)
725 dict['CCFLAGS'].append(t)
726 dict['LINKFLAGS'].append(t)
727 else:
728 dict[append_next_arg_to].append(arg)
729 append_next_arg_to = None
730 elif not arg[0] in ['-', '+']:
731 dict['LIBS'].append(self.fs.File(arg))
732 elif arg[:2] == '-L':
733 if arg[2:]:
734 dict['LIBPATH'].append(arg[2:])
735 else:
736 append_next_arg_to = 'LIBPATH'
737 elif arg[:2] == '-l':
738 if arg[2:]:
739 dict['LIBS'].append(arg[2:])
740 else:
741 append_next_arg_to = 'LIBS'
742 elif arg[:2] == '-I':
743 if arg[2:]:
744 dict['CPPPATH'].append(arg[2:])
745 else:
746 append_next_arg_to = 'CPPPATH'
747 elif arg[:4] == '-Wa,':
748 dict['ASFLAGS'].append(arg[4:])
749 dict['CCFLAGS'].append(arg)
750 elif arg[:4] == '-Wl,':
751 if arg[:11] == '-Wl,-rpath=':
752 dict['RPATH'].append(arg[11:])
753 elif arg[:7] == '-Wl,-R,':
754 dict['RPATH'].append(arg[7:])
755 elif arg[:6] == '-Wl,-R':
756 dict['RPATH'].append(arg[6:])
757 else:
758 dict['LINKFLAGS'].append(arg)
759 elif arg[:4] == '-Wp,':
760 dict['CPPFLAGS'].append(arg)
761 elif arg[:2] == '-D':
762 if arg[2:]:
763 append_define(arg[2:])
764 else:
765 append_next_arg_to = 'CPPDEFINES'
766 elif arg == '-framework':
767 append_next_arg_to = 'FRAMEWORKS'
768 elif arg[:14] == '-frameworkdir=':
769 dict['FRAMEWORKPATH'].append(arg[14:])
770 elif arg[:2] == '-F':
771 if arg[2:]:
772 dict['FRAMEWORKPATH'].append(arg[2:])
773 else:
774 append_next_arg_to = 'FRAMEWORKPATH'
775 elif arg == '-mno-cygwin':
776 dict['CCFLAGS'].append(arg)
777 dict['LINKFLAGS'].append(arg)
778 elif arg == '-mwindows':
779 dict['LINKFLAGS'].append(arg)
780 elif arg == '-pthread':
781 dict['CCFLAGS'].append(arg)
782 dict['LINKFLAGS'].append(arg)
783 elif arg[:5] == '-std=':
784 dict['CFLAGS'].append(arg)
785 elif arg[0] == '+':
786 dict['CCFLAGS'].append(arg)
787 dict['LINKFLAGS'].append(arg)
788 elif arg in ['-include', '-isysroot', '-arch']:
789 append_next_arg_to = arg
790 else:
791 dict['CCFLAGS'].append(arg)
792
793 for arg in flags:
794 do_parse(arg, do_parse)
795 return dict
796
798 """
799 Merge the dict in args into the construction variables of this
800 env, or the passed-in dict. If args is not a dict, it is
801 converted into a dict using ParseFlags. If unique is not set,
802 the flags are appended rather than merged.
803 """
804
805 if dict is None:
806 dict = self
807 if not SCons.Util.is_Dict(args):
808 args = self.ParseFlags(args)
809 if not unique:
810 apply(self.Append, (), args)
811 return self
812 for key, value in args.items():
813 if not value:
814 continue
815 try:
816 orig = self[key]
817 except KeyError:
818 orig = value
819 else:
820 if not orig:
821 orig = value
822 elif value:
823
824
825
826
827
828
829 try:
830 orig = orig + value
831 except (KeyError, TypeError):
832 try:
833 add_to_orig = orig.append
834 except AttributeError:
835 value.insert(0, orig)
836 orig = value
837 else:
838 add_to_orig(value)
839 t = []
840 if key[-4:] == 'PATH':
841
842 for v in orig:
843 if v not in t:
844 t.append(v)
845 else:
846
847 orig.reverse()
848 for v in orig:
849 if v not in t:
850 t.insert(0, v)
851 self[key] = t
852 return self
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
884
888
892
894 f = SCons.Defaults.DefaultEnvironment().copy_from_cache
895 return f(src, dst)
896
897 -class Base(SubstitutionEnvironment):
898 """Base class for "real" construction Environments. These are the
899 primary objects used to communicate dependency and construction
900 information to the build engine.
901
902 Keyword arguments supplied when the construction Environment
903 is created are construction variables used to initialize the
904 Environment.
905 """
906
907 memoizer_counters = []
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923 - def __init__(self,
924 platform=None,
925 tools=None,
926 toolpath=None,
927 variables=None,
928 parse_flags = None,
929 **kw):
930 """
931 Initialization of a basic SCons construction environment,
932 including setting up special construction variables like BUILDER,
933 PLATFORM, etc., and searching for and applying available Tools.
934
935 Note that we do *not* call the underlying base class
936 (SubsitutionEnvironment) initialization, because we need to
937 initialize things in a very specific order that doesn't work
938 with the much simpler base class initialization.
939 """
940 if __debug__: logInstanceCreation(self, 'Environment.Base')
941 self._memo = {}
942 self.fs = SCons.Node.FS.get_default_fs()
943 self.ans = SCons.Node.Alias.default_ans
944 self.lookup_list = SCons.Node.arg2nodes_lookups
945 self._dict = semi_deepcopy(SCons.Defaults.ConstructionEnvironment)
946 self._init_special()
947 self.added_methods = []
948
949
950
951
952
953
954
955 self.decide_target = default_decide_target
956 self.decide_source = default_decide_source
957
958 self.copy_from_cache = default_copy_from_cache
959
960 self._dict['BUILDERS'] = BuilderDict(self._dict['BUILDERS'], self)
961
962 if platform is None:
963 platform = self._dict.get('PLATFORM', None)
964 if platform is None:
965 platform = SCons.Platform.Platform()
966 if SCons.Util.is_String(platform):
967 platform = SCons.Platform.Platform(platform)
968 self._dict['PLATFORM'] = str(platform)
969 platform(self)
970
971 self._dict['HOST_OS'] = self._dict.get('HOST_OS',None)
972 self._dict['HOST_ARCH'] = self._dict.get('HOST_ARCH',None)
973
974
975 self._dict['TARGET_OS'] = self._dict.get('HOST_OS',None)
976 self._dict['TARGET_ARCH'] = self._dict.get('HOST_ARCH',None)
977
978
979
980
981
982 if kw.has_key('options'):
983
984
985 variables = kw['options']
986 del kw['options']
987 apply(self.Replace, (), kw)
988 keys = kw.keys()
989 if variables:
990 keys = keys + variables.keys()
991 variables.Update(self)
992
993 save = {}
994 for k in keys:
995 try:
996 save[k] = self._dict[k]
997 except KeyError:
998
999
1000 pass
1001
1002 SCons.Tool.Initializers(self)
1003
1004 if tools is None:
1005 tools = self._dict.get('TOOLS', None)
1006 if tools is None:
1007 tools = ['default']
1008 apply_tools(self, tools, toolpath)
1009
1010
1011
1012
1013 for key, val in save.items():
1014 self._dict[key] = val
1015
1016
1017 if parse_flags: self.MergeFlags(parse_flags)
1018
1019
1020
1021
1022
1023
1025 """Fetch the builder with the specified name from the environment.
1026 """
1027 try:
1028 return self._dict['BUILDERS'][name]
1029 except KeyError:
1030 return None
1031
1033 try:
1034 path = self._CacheDir_path
1035 except AttributeError:
1036 path = SCons.Defaults.DefaultEnvironment()._CacheDir_path
1037 try:
1038 if path == self._last_CacheDir_path:
1039 return self._last_CacheDir
1040 except AttributeError:
1041 pass
1042 cd = SCons.CacheDir.CacheDir(path)
1043 self._last_CacheDir_path = path
1044 self._last_CacheDir = cd
1045 return cd
1046
1048 """Return a factory function for creating Nodes for this
1049 construction environment.
1050 """
1051 name = default
1052 try:
1053 is_node = issubclass(factory, SCons.Node.FS.Base)
1054 except TypeError:
1055
1056
1057 pass
1058 else:
1059 if is_node:
1060
1061
1062
1063
1064 try: name = factory.__name__
1065 except AttributeError: pass
1066 else: factory = None
1067 if not factory:
1068
1069
1070
1071
1072
1073 factory = getattr(self.fs, name)
1074 return factory
1075
1076 memoizer_counters.append(SCons.Memoize.CountValue('_gsm'))
1077
1079 try:
1080 return self._memo['_gsm']
1081 except KeyError:
1082 pass
1083
1084 result = {}
1085
1086 try:
1087 scanners = self._dict['SCANNERS']
1088 except KeyError:
1089 pass
1090 else:
1091
1092
1093
1094
1095 if not SCons.Util.is_List(scanners):
1096 scanners = [scanners]
1097 else:
1098 scanners = scanners[:]
1099 scanners.reverse()
1100 for scanner in scanners:
1101 for k in scanner.get_skeys(self):
1102 if k and self['PLATFORM'] == 'win32':
1103 k = string.lower(k)
1104 result[k] = scanner
1105
1106 self._memo['_gsm'] = result
1107
1108 return result
1109
1111 """Find the appropriate scanner given a key (usually a file suffix).
1112 """
1113 if skey and self['PLATFORM'] == 'win32':
1114 skey = string.lower(skey)
1115 return self._gsm().get(skey)
1116
1118 """Delete the cached scanner map (if we need to).
1119 """
1120 try:
1121 del self._memo['_gsm']
1122 except KeyError:
1123 pass
1124
1126 """Update an environment's values directly, bypassing the normal
1127 checks that occur when users try to set items.
1128 """
1129 self._dict.update(dict)
1130
1132 try:
1133 return self.src_sig_type
1134 except AttributeError:
1135 t = SCons.Defaults.DefaultEnvironment().src_sig_type
1136 self.src_sig_type = t
1137 return t
1138
1140 try:
1141 return self.tgt_sig_type
1142 except AttributeError:
1143 t = SCons.Defaults.DefaultEnvironment().tgt_sig_type
1144 self.tgt_sig_type = t
1145 return t
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1157 """Append values to existing construction variables
1158 in an Environment.
1159 """
1160 kw = copy_non_reserved_keywords(kw)
1161 for key, val in kw.items():
1162
1163
1164
1165
1166 try:
1167 orig = self._dict[key]
1168 except KeyError:
1169
1170
1171 self._dict[key] = val
1172 else:
1173 try:
1174
1175
1176
1177
1178
1179 update_dict = orig.update
1180 except AttributeError:
1181 try:
1182
1183
1184
1185 self._dict[key] = orig + val
1186 except (KeyError, TypeError):
1187 try:
1188
1189 add_to_orig = orig.append
1190 except AttributeError:
1191
1192
1193
1194
1195
1196 if orig:
1197 val.insert(0, orig)
1198 self._dict[key] = val
1199 else:
1200
1201
1202 if val:
1203 add_to_orig(val)
1204 else:
1205
1206
1207 if SCons.Util.is_List(val):
1208 for v in val:
1209 orig[v] = None
1210 else:
1211 try:
1212 update_dict(val)
1213 except (AttributeError, TypeError, ValueError):
1214 if SCons.Util.is_Dict(val):
1215 for k, v in val.items():
1216 orig[k] = v
1217 else:
1218 orig[val] = None
1219 self.scanner_map_delete(kw)
1220
1221
1222
1229
1232 """Append path elements to the path 'name' in the 'ENV'
1233 dictionary for this environment. Will only add any particular
1234 path once, and will normpath and normcase all paths to help
1235 assure this. This can also handle the case where the env
1236 variable is a list instead of a string.
1237
1238 If delete_existing is 0, a newpath which is already in the path
1239 will not be moved to the end (it will be left where it is).
1240 """
1241
1242 orig = ''
1243 if self._dict.has_key(envname) and self._dict[envname].has_key(name):
1244 orig = self._dict[envname][name]
1245
1246 nv = SCons.Util.AppendPath(orig, newpath, sep, delete_existing,
1247 canonicalize=self._canonicalize)
1248
1249 if not self._dict.has_key(envname):
1250 self._dict[envname] = {}
1251
1252 self._dict[envname][name] = nv
1253
1255 """Append values to existing construction variables
1256 in an Environment, if they're not already there.
1257 If delete_existing is 1, removes existing values first, so
1258 values move to end.
1259 """
1260 kw = copy_non_reserved_keywords(kw)
1261 for key, val in kw.items():
1262 if SCons.Util.is_List(val):
1263 val = _delete_duplicates(val, delete_existing)
1264 if not self._dict.has_key(key) or self._dict[key] in ('', None):
1265 self._dict[key] = val
1266 elif SCons.Util.is_Dict(self._dict[key]) and \
1267 SCons.Util.is_Dict(val):
1268 self._dict[key].update(val)
1269 elif SCons.Util.is_List(val):
1270 dk = self._dict[key]
1271 if not SCons.Util.is_List(dk):
1272 dk = [dk]
1273 if delete_existing:
1274 dk = filter(lambda x, val=val: x not in val, dk)
1275 else:
1276 val = filter(lambda x, dk=dk: x not in dk, val)
1277 self._dict[key] = dk + val
1278 else:
1279 dk = self._dict[key]
1280 if SCons.Util.is_List(dk):
1281
1282
1283 if delete_existing:
1284 dk = filter(lambda x, val=val: x not in val, dk)
1285 self._dict[key] = dk + [val]
1286 else:
1287 if not val in dk:
1288 self._dict[key] = dk + [val]
1289 else:
1290 if delete_existing:
1291 dk = filter(lambda x, val=val: x not in val, dk)
1292 self._dict[key] = dk + val
1293 self.scanner_map_delete(kw)
1294
1295 - def Clone(self, tools=[], toolpath=None, parse_flags = None, **kw):
1296 """Return a copy of a construction Environment. The
1297 copy is like a Python "deep copy"--that is, independent
1298 copies are made recursively of each objects--except that
1299 a reference is copied when an object is not deep-copyable
1300 (like a function). There are no references to any mutable
1301 objects in the original Environment.
1302 """
1303 clone = copy.copy(self)
1304 clone._dict = semi_deepcopy(self._dict)
1305
1306 try:
1307 cbd = clone._dict['BUILDERS']
1308 except KeyError:
1309 pass
1310 else:
1311 clone._dict['BUILDERS'] = BuilderDict(cbd, clone)
1312
1313
1314
1315
1316
1317 clone.added_methods = []
1318 for mw in self.added_methods:
1319 if mw == getattr(self, mw.name):
1320 clone.added_methods.append(mw.clone(clone))
1321
1322 clone._memo = {}
1323
1324
1325
1326 kw = copy_non_reserved_keywords(kw)
1327 new = {}
1328 for key, value in kw.items():
1329 new[key] = SCons.Subst.scons_subst_once(value, self, key)
1330 apply(clone.Replace, (), new)
1331
1332 apply_tools(clone, tools, toolpath)
1333
1334
1335 apply(clone.Replace, (), new)
1336
1337
1338 if parse_flags: clone.MergeFlags(parse_flags)
1339
1340 if __debug__: logInstanceCreation(self, 'Environment.EnvironmentClone')
1341 return clone
1342
1343 - def Copy(self, *args, **kw):
1350
1355
1356 - def _changed_content(self, dependency, target, prev_ni):
1357 return dependency.changed_content(target, prev_ni)
1358
1366
1367 - def _changed_timestamp_then_content(self, dependency, target, prev_ni):
1368 return dependency.changed_timestamp_then_content(target, prev_ni)
1369
1372
1375
1377 return self.fs.copy(src, dst)
1378
1380 return self.fs.copy2(src, dst)
1381
1405
1407 """Return the first available program in progs.
1408 """
1409 if not SCons.Util.is_List(progs):
1410 progs = [ progs ]
1411 for prog in progs:
1412 path = self.WhereIs(prog)
1413 if path: return prog
1414 return None
1415
1417 if not args:
1418 return self._dict
1419 dlist = map(lambda x, s=self: s._dict[x], args)
1420 if len(dlist) == 1:
1421 dlist = dlist[0]
1422 return dlist
1423
1424 - def Dump(self, key = None):
1425 """
1426 Using the standard Python pretty printer, dump the contents of the
1427 scons build environment to stdout.
1428
1429 If the key passed in is anything other than None, then that will
1430 be used as an index into the build environment dictionary and
1431 whatever is found there will be fed into the pretty printer. Note
1432 that this key is case sensitive.
1433 """
1434 import pprint
1435 pp = pprint.PrettyPrinter(indent=2)
1436 if key:
1437 dict = self.Dictionary(key)
1438 else:
1439 dict = self.Dictionary()
1440 return pp.pformat(dict)
1441
1442 - def FindIxes(self, paths, prefix, suffix):
1443 """
1444 Search a list of paths for something that matches the prefix and suffix.
1445
1446 paths - the list of paths or nodes.
1447 prefix - construction variable for the prefix.
1448 suffix - construction variable for the suffix.
1449 """
1450
1451 suffix = self.subst('$'+suffix)
1452 prefix = self.subst('$'+prefix)
1453
1454 for path in paths:
1455 dir,name = os.path.split(str(path))
1456 if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix:
1457 return path
1458
1459 - def ParseConfig(self, command, function=None, unique=1):
1460 """
1461 Use the specified function to parse the output of the command
1462 in order to modify the current environment. The 'command' can
1463 be a string or a list of strings representing a command and
1464 its arguments. 'Function' is an optional argument that takes
1465 the environment, the output of the command, and the unique flag.
1466 If no function is specified, MergeFlags, which treats the output
1467 as the result of a typical 'X-config' command (i.e. gtk-config),
1468 will merge the output into the appropriate variables.
1469 """
1470 if function is None:
1471 def parse_conf(env, cmd, unique=unique):
1472 return env.MergeFlags(cmd, unique)
1473 function = parse_conf
1474 if SCons.Util.is_List(command):
1475 command = string.join(command)
1476 command = self.subst(command)
1477 return function(self, self.backtick(command))
1478
1479 - def ParseDepends(self, filename, must_exist=None, only_one=0):
1480 """
1481 Parse a mkdep-style file for explicit dependencies. This is
1482 completely abusable, and should be unnecessary in the "normal"
1483 case of proper SCons configuration, but it may help make
1484 the transition from a Make hierarchy easier for some people
1485 to swallow. It can also be genuinely useful when using a tool
1486 that can write a .d file, but for which writing a scanner would
1487 be too complicated.
1488 """
1489 filename = self.subst(filename)
1490 try:
1491 fp = open(filename, 'r')
1492 except IOError:
1493 if must_exist:
1494 raise
1495 return
1496 lines = SCons.Util.LogicalLines(fp).readlines()
1497 lines = filter(lambda l: l[0] != '#', lines)
1498 tdlist = []
1499 for line in lines:
1500 try:
1501 target, depends = string.split(line, ':', 1)
1502 except (AttributeError, TypeError, ValueError):
1503
1504
1505
1506
1507 pass
1508 else:
1509 tdlist.append((string.split(target), string.split(depends)))
1510 if only_one:
1511 targets = reduce(lambda x, y: x+y, map(lambda p: p[0], tdlist))
1512 if len(targets) > 1:
1513 raise SCons.Errors.UserError, "More than one dependency target found in `%s': %s" % (filename, targets)
1514 for target, depends in tdlist:
1515 self.Depends(target, depends)
1516
1520
1522 """Prepend values to existing construction variables
1523 in an Environment.
1524 """
1525 kw = copy_non_reserved_keywords(kw)
1526 for key, val in kw.items():
1527
1528
1529
1530
1531 try:
1532 orig = self._dict[key]
1533 except KeyError:
1534
1535
1536 self._dict[key] = val
1537 else:
1538 try:
1539
1540
1541
1542
1543
1544 update_dict = orig.update
1545 except AttributeError:
1546 try:
1547
1548
1549
1550 self._dict[key] = val + orig
1551 except (KeyError, TypeError):
1552 try:
1553
1554 add_to_val = val.append
1555 except AttributeError:
1556
1557
1558
1559
1560 if val:
1561 orig.insert(0, val)
1562 else:
1563
1564
1565
1566 if orig:
1567 add_to_val(orig)
1568 self._dict[key] = val
1569 else:
1570
1571
1572 if SCons.Util.is_List(val):
1573 for v in val:
1574 orig[v] = None
1575 else:
1576 try:
1577 update_dict(val)
1578 except (AttributeError, TypeError, ValueError):
1579 if SCons.Util.is_Dict(val):
1580 for k, v in val.items():
1581 orig[k] = v
1582 else:
1583 orig[val] = None
1584 self.scanner_map_delete(kw)
1585
1588 """Prepend path elements to the path 'name' in the 'ENV'
1589 dictionary for this environment. Will only add any particular
1590 path once, and will normpath and normcase all paths to help
1591 assure this. This can also handle the case where the env
1592 variable is a list instead of a string.
1593
1594 If delete_existing is 0, a newpath which is already in the path
1595 will not be moved to the front (it will be left where it is).
1596 """
1597
1598 orig = ''
1599 if self._dict.has_key(envname) and self._dict[envname].has_key(name):
1600 orig = self._dict[envname][name]
1601
1602 nv = SCons.Util.PrependPath(orig, newpath, sep, delete_existing,
1603 canonicalize=self._canonicalize)
1604
1605 if not self._dict.has_key(envname):
1606 self._dict[envname] = {}
1607
1608 self._dict[envname][name] = nv
1609
1611 """Prepend values to existing construction variables
1612 in an Environment, if they're not already there.
1613 If delete_existing is 1, removes existing values first, so
1614 values move to front.
1615 """
1616 kw = copy_non_reserved_keywords(kw)
1617 for key, val in kw.items():
1618 if SCons.Util.is_List(val):
1619 val = _delete_duplicates(val, not delete_existing)
1620 if not self._dict.has_key(key) or self._dict[key] in ('', None):
1621 self._dict[key] = val
1622 elif SCons.Util.is_Dict(self._dict[key]) and \
1623 SCons.Util.is_Dict(val):
1624 self._dict[key].update(val)
1625 elif SCons.Util.is_List(val):
1626 dk = self._dict[key]
1627 if not SCons.Util.is_List(dk):
1628 dk = [dk]
1629 if delete_existing:
1630 dk = filter(lambda x, val=val: x not in val, dk)
1631 else:
1632 val = filter(lambda x, dk=dk: x not in dk, val)
1633 self._dict[key] = val + dk
1634 else:
1635 dk = self._dict[key]
1636 if SCons.Util.is_List(dk):
1637
1638
1639 if delete_existing:
1640 dk = filter(lambda x, val=val: x not in val, dk)
1641 self._dict[key] = [val] + dk
1642 else:
1643 if not val in dk:
1644 self._dict[key] = [val] + dk
1645 else:
1646 if delete_existing:
1647 dk = filter(lambda x, val=val: x not in val, dk)
1648 self._dict[key] = val + dk
1649 self.scanner_map_delete(kw)
1650
1652 """Replace existing construction variables in an Environment
1653 with new construction variables and/or values.
1654 """
1655 try:
1656 kwbd = kw['BUILDERS']
1657 except KeyError:
1658 pass
1659 else:
1660 kwbd = semi_deepcopy(kwbd)
1661 del kw['BUILDERS']
1662 self.__setitem__('BUILDERS', kwbd)
1663 kw = copy_non_reserved_keywords(kw)
1664 self._update(semi_deepcopy(kw))
1665 self.scanner_map_delete(kw)
1666
1667 - def ReplaceIxes(self, path, old_prefix, old_suffix, new_prefix, new_suffix):
1668 """
1669 Replace old_prefix with new_prefix and old_suffix with new_suffix.
1670
1671 env - Environment used to interpolate variables.
1672 path - the path that will be modified.
1673 old_prefix - construction variable for the old prefix.
1674 old_suffix - construction variable for the old suffix.
1675 new_prefix - construction variable for the new prefix.
1676 new_suffix - construction variable for the new suffix.
1677 """
1678 old_prefix = self.subst('$'+old_prefix)
1679 old_suffix = self.subst('$'+old_suffix)
1680
1681 new_prefix = self.subst('$'+new_prefix)
1682 new_suffix = self.subst('$'+new_suffix)
1683
1684 dir,name = os.path.split(str(path))
1685 if name[:len(old_prefix)] == old_prefix:
1686 name = name[len(old_prefix):]
1687 if name[-len(old_suffix):] == old_suffix:
1688 name = name[:-len(old_suffix)]
1689 return os.path.join(dir, new_prefix+name+new_suffix)
1690
1692 for k in kw.keys():
1693 if self._dict.has_key(k):
1694 del kw[k]
1695 apply(self.Replace, (), kw)
1696
1699
1708
1709 - def WhereIs(self, prog, path=None, pathext=None, reject=[]):
1710 """Find prog in the path.
1711 """
1712 if path is None:
1713 try:
1714 path = self['ENV']['PATH']
1715 except KeyError:
1716 pass
1717 elif SCons.Util.is_String(path):
1718 path = self.subst(path)
1719 if pathext is None:
1720 try:
1721 pathext = self['ENV']['PATHEXT']
1722 except KeyError:
1723 pass
1724 elif SCons.Util.is_String(pathext):
1725 pathext = self.subst(pathext)
1726 prog = self.subst(prog)
1727 path = SCons.Util.WhereIs(prog, path, pathext, reject)
1728 if path: return path
1729 return None
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739 - def Action(self, *args, **kw):
1744 nargs = map(subst_string, args)
1745 nkw = self.subst_kw(kw)
1746 return apply(SCons.Action.Action, nargs, nkw)
1747
1757
1758 - def AddPostAction(self, files, action):
1759 nodes = self.arg2nodes(files, self.fs.Entry)
1760 action = SCons.Action.Action(action)
1761 uniq = {}
1762 for executor in map(lambda n: n.get_executor(), nodes):
1763 uniq[executor] = 1
1764 for executor in uniq.keys():
1765 executor.add_post_action(action)
1766 return nodes
1767
1768 - def Alias(self, target, source=[], action=None, **kw):
1769 tlist = self.arg2nodes(target, self.ans.Alias)
1770 if not SCons.Util.is_List(source):
1771 source = [source]
1772 source = filter(None, source)
1773
1774 if not action:
1775 if not source:
1776
1777
1778
1779
1780
1781
1782 return tlist
1783
1784
1785
1786 result = []
1787 for t in tlist:
1788 bld = t.get_builder(AliasBuilder)
1789 result.extend(bld(self, t, source))
1790 return result
1791
1792 nkw = self.subst_kw(kw)
1793 nkw.update({
1794 'action' : SCons.Action.Action(action),
1795 'source_factory' : self.fs.Entry,
1796 'multi' : 1,
1797 'is_explicit' : None,
1798 })
1799 bld = apply(SCons.Builder.Builder, (), nkw)
1800
1801
1802
1803
1804
1805 result = []
1806 for t in tlist:
1807
1808
1809
1810
1811 b = t.get_builder()
1812 if b is None or b is AliasBuilder:
1813 b = bld
1814 else:
1815 nkw['action'] = b.action + action
1816 b = apply(SCons.Builder.Builder, (), nkw)
1817 t.convert()
1818 result.extend(b(self, t, t.sources + source))
1819 return result
1820
1828
1830 if kw.has_key('build_dir'):
1831 kw['variant_dir'] = kw['build_dir']
1832 del kw['build_dir']
1833 return apply(self.VariantDir, args, kw)
1834
1838
1844
1845 - def Clean(self, targets, files):
1854
1866
1867 - def Command(self, target, source, action, **kw):
1868 """Builds the supplied target files from the supplied
1869 source files using the supplied action. Action may
1870 be any type that the Builder constructor will accept
1871 for an action."""
1872 bkw = {
1873 'action' : action,
1874 'target_factory' : self.fs.Entry,
1875 'source_factory' : self.fs.Entry,
1876 }
1877 try: bkw['source_scanner'] = kw['source_scanner']
1878 except KeyError: pass
1879 else: del kw['source_scanner']
1880 bld = apply(SCons.Builder.Builder, (), bkw)
1881 return apply(bld, (self, target, source), kw)
1882
1883 - def Depends(self, target, dependency):
1884 """Explicity specify that 'target's depend on 'dependency'."""
1885 tlist = self.arg2nodes(target, self.fs.Entry)
1886 dlist = self.arg2nodes(dependency, self.fs.Entry)
1887 for t in tlist:
1888 t.add_dependency(dlist)
1889 return tlist
1890
1891 - def Dir(self, name, *args, **kw):
1901
1903 """Tags a target so that it will not be cleaned by -c"""
1904 tlist = []
1905 for t in targets:
1906 tlist.extend(self.arg2nodes(t, self.fs.Entry))
1907 for t in tlist:
1908 t.set_noclean()
1909 return tlist
1910
1912 """Tags a target so that it will not be cached"""
1913 tlist = []
1914 for t in targets:
1915 tlist.extend(self.arg2nodes(t, self.fs.Entry))
1916 for t in tlist:
1917 t.set_nocache()
1918 return tlist
1919
1920 - def Entry(self, name, *args, **kw):
1921 """
1922 """
1923 s = self.subst(name)
1924 if SCons.Util.is_Sequence(s):
1925 result=[]
1926 for e in s:
1927 result.append(apply(self.fs.Entry, (e,) + args, kw))
1928 return result
1929 return apply(self.fs.Entry, (s,) + args, kw)
1930
1933
1934 - def Execute(self, action, *args, **kw):
1935 """Directly execute an action through an Environment
1936 """
1937 action = apply(self.Action, (action,) + args, kw)
1938 result = action([], [], self)
1939 if isinstance(result, SCons.Errors.BuildError):
1940 errstr = result.errstr
1941 if result.filename:
1942 errstr = result.filename + ': ' + errstr
1943 sys.stderr.write("scons: *** %s\n" % errstr)
1944 return result.status
1945 else:
1946 return result
1947
1948 - def File(self, name, *args, **kw):
1958
1963
1966
1973
1976
1977 - def Ignore(self, target, dependency):
1984
1987
1988 - def Local(self, *targets):
1999
2007
2011
2012 - def Requires(self, target, prerequisite):
2013 """Specify that 'prerequisite' must be built before 'target',
2014 (but 'target' does not actually depend on 'prerequisite'
2015 and need not be rebuilt if it changes)."""
2016 tlist = self.arg2nodes(target, self.fs.Entry)
2017 plist = self.arg2nodes(prerequisite, self.fs.Entry)
2018 for t in tlist:
2019 t.add_prerequisite(plist)
2020 return tlist
2021
2030
2031 - def SConsignFile(self, name=".sconsign", dbm_module=None):
2042
2044 """Tell scons that side_effects are built as side
2045 effects of building targets."""
2046 side_effects = self.arg2nodes(side_effect, self.fs.Entry)
2047 targets = self.arg2nodes(target, self.fs.Entry)
2048
2049 for side_effect in side_effects:
2050 if side_effect.multiple_side_effect_has_builder():
2051 raise SCons.Errors.UserError, "Multiple ways to build the same target were specified for: %s" % str(side_effect)
2052 side_effect.add_source(targets)
2053 side_effect.side_effect = 1
2054 self.Precious(side_effect)
2055 for target in targets:
2056 target.side_effects.append(side_effect)
2057 return side_effects
2058
2060 """Arrange for a source code builder for (part of) a tree."""
2061 entries = self.arg2nodes(entry, self.fs.Entry)
2062 for entry in entries:
2063 entry.set_src_builder(builder)
2064 return entries
2065
2083
2085 """This function converts a string or list into a list of strings
2086 or Nodes. This makes things easier for users by allowing files to
2087 be specified as a white-space separated list to be split.
2088 The input rules are:
2089 - A single string containing names separated by spaces. These will be
2090 split apart at the spaces.
2091 - A single Node instance
2092 - A list containing either strings or Node instances. Any strings
2093 in the list are not split at spaces.
2094 In all cases, the function returns a list of Nodes and strings."""
2095 if SCons.Util.is_List(arg):
2096 return map(self.subst, arg)
2097 elif SCons.Util.is_String(arg):
2098 return string.split(self.subst(arg))
2099 else:
2100 return [self.subst(arg)]
2101
2123
2124 - def Value(self, value, built_value=None):
2128
2129 - def VariantDir(self, variant_dir, src_dir, duplicate=1):
2133
2135 """ returns a list of all source files.
2136 """
2137 node = self.arg2nodes(node, self.fs.Entry)[0]
2138
2139 sources = []
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150 build_source(node.all_children(), sources)
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161 return list(set(sources))
2162
2164 """ returns the list of all targets of the Install and InstallAs Builder.
2165 """
2166 from SCons.Tool import install
2167 if install._UNIQUE_INSTALLED_FILES is None:
2168 install._UNIQUE_INSTALLED_FILES = SCons.Util.uniquer_hashables(install._INSTALLED_FILES)
2169 return install._UNIQUE_INSTALLED_FILES
2170
2172 """A proxy that overrides variables in a wrapped construction
2173 environment by returning values from an overrides dictionary in
2174 preference to values from the underlying subject environment.
2175
2176 This is a lightweight (I hope) proxy that passes through most use of
2177 attributes to the underlying Environment.Base class, but has just
2178 enough additional methods defined to act like a real construction
2179 environment with overridden values. It can wrap either a Base
2180 construction environment, or another OverrideEnvironment, which
2181 can in turn nest arbitrary OverrideEnvironments...
2182
2183 Note that we do *not* call the underlying base class
2184 (SubsitutionEnvironment) initialization, because we get most of those
2185 from proxying the attributes of the subject construction environment.
2186 But because we subclass SubstitutionEnvironment, this class also
2187 has inherited arg2nodes() and subst*() methods; those methods can't
2188 be proxied because they need *this* object's methods to fetch the
2189 values from the overrides dictionary.
2190 """
2191
2192 - def __init__(self, subject, overrides={}):
2193 if __debug__: logInstanceCreation(self, 'Environment.OverrideEnvironment')
2194 self.__dict__['__subject'] = subject
2195 self.__dict__['overrides'] = overrides
2196
2197
2199 return getattr(self.__dict__['__subject'], name)
2201 setattr(self.__dict__['__subject'], name, value)
2202
2203
2205 try:
2206 return self.__dict__['overrides'][key]
2207 except KeyError:
2208 return self.__dict__['__subject'].__getitem__(key)
2214 try:
2215 del self.__dict__['overrides'][key]
2216 except KeyError:
2217 deleted = 0
2218 else:
2219 deleted = 1
2220 try:
2221 result = self.__dict__['__subject'].__delitem__(key)
2222 except KeyError:
2223 if not deleted:
2224 raise
2225 result = None
2226 return result
2227 - def get(self, key, default=None):
2228 """Emulates the get() method of dictionaries."""
2229 try:
2230 return self.__dict__['overrides'][key]
2231 except KeyError:
2232 return self.__dict__['__subject'].get(key, default)
2234 try:
2235 self.__dict__['overrides'][key]
2236 return 1
2237 except KeyError:
2238 return self.__dict__['__subject'].has_key(key)
2240 if self.__dict__['overrides'].__contains__(key):
2241 return 1
2242 return self.__dict__['__subject'].__contains__(key)
2244 """Emulates the items() method of dictionaries."""
2245 d = self.__dict__['__subject'].Dictionary().copy()
2246 d.update(self.__dict__['overrides'])
2247 return d
2249 """Emulates the items() method of dictionaries."""
2250 return self.Dictionary().items()
2251
2252
2254 """Update an environment's values directly, bypassing the normal
2255 checks that occur when users try to set items.
2256 """
2257 self.__dict__['overrides'].update(dict)
2258
2260 return self.__dict__['__subject'].gvars()
2261
2266
2267
2271
2272
2273
2274
2275
2276
2277
2278 Environment = Base
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2293 class _NoSubstitutionProxy(Environment):
2294 def __init__(self, subject):
2295 self.__dict__['__subject'] = subject
2296 def __getattr__(self, name):
2297 return getattr(self.__dict__['__subject'], name)
2298 def __setattr__(self, name, value):
2299 return setattr(self.__dict__['__subject'], name, value)
2300 def raw_to_mode(self, dict):
2301 try:
2302 raw = dict['raw']
2303 except KeyError:
2304 pass
2305 else:
2306 del dict['raw']
2307 dict['mode'] = raw
2308 def subst(self, string, *args, **kwargs):
2309 return string
2310 def subst_kw(self, kw, *args, **kwargs):
2311 return kw
2312 def subst_list(self, string, *args, **kwargs):
2313 nargs = (string, self,) + args
2314 nkw = kwargs.copy()
2315 nkw['gvars'] = {}
2316 self.raw_to_mode(nkw)
2317 return apply(SCons.Subst.scons_subst_list, nargs, nkw)
2318 def subst_target_source(self, string, *args, **kwargs):
2319 nargs = (string, self,) + args
2320 nkw = kwargs.copy()
2321 nkw['gvars'] = {}
2322 self.raw_to_mode(nkw)
2323 return apply(SCons.Subst.scons_subst, nargs, nkw)
2324 return _NoSubstitutionProxy(subject)
2325
2326
2327
2328
2329
2330
2331