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 3603 2008/10/10 05:46:45 scons"
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.SConsign
58 import SCons.Subst
59 import SCons.Tool
60 import SCons.Util
61 import SCons.Warnings
62
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
77
78
79
80 UserError = SCons.Errors.UserError
81
84
85 AliasBuilder = SCons.Builder.Builder(action = alias_builder,
86 target_factory = SCons.Node.Alias.default_ans.Alias,
87 source_factory = SCons.Node.FS.Entry,
88 multi = 1,
89 is_explicit = None,
90 name='AliasBuilder')
91
107
108
109
110
111 reserved_construction_var_names = \
112 ['TARGET', 'TARGETS', 'SOURCE', 'SOURCES']
113
122
126
128 try:
129 bd = env._dict[key]
130 for k in bd.keys():
131 del bd[k]
132 except KeyError:
133 bd = BuilderDict(kwbd, env)
134 env._dict[key] = bd
135 bd.update(value)
136
140
144
145
146
147
148
149
150
151
152
153
154
155
156
157
159 """
160 A generic Wrapper class that associates a method (which can
161 actually be any callable) with an object. As part of creating this
162 MethodWrapper object an attribute with the specified (by default,
163 the name of the supplied method) is added to the underlying object.
164 When that new "method" is called, our __call__() method adds the
165 object as the first argument, simulating the Python behavior of
166 supplying "self" on method calls.
167
168 We hang on to the name by which the method was added to the underlying
169 base class so that we can provide a method to "clone" ourselves onto
170 a new underlying object being copied (without which we wouldn't need
171 to save that info).
172 """
173 - def __init__(self, object, method, name=None):
180
182 nargs = (self.object,) + args
183 return apply(self.method, nargs, kwargs)
184
185 - def clone(self, new_object):
186 """
187 Returns an object that re-binds the underlying "method" to
188 the specified new object.
189 """
190 return self.__class__(new_object, self.method, self.name)
191
193 """
194 A MethodWrapper subclass that that associates an environment with
195 a Builder.
196
197 This mainly exists to wrap the __call__() function so that all calls
198 to Builders can have their argument lists massaged in the same way
199 (treat a lone argument as the source, treat two arguments as target
200 then source, make sure both target and source are lists) without
201 having to have cut-and-paste code to do it.
202
203 As a bit of obsessive backwards compatibility, we also intercept
204 attempts to get or set the "env" or "builder" attributes, which were
205 the names we used before we put the common functionality into the
206 MethodWrapper base class. We'll keep this around for a while in case
207 people shipped Tool modules that reached into the wrapper (like the
208 Tool/qt.py module does, or did). There shouldn't be a lot attribute
209 fetching or setting on these, so a little extra work shouldn't hurt.
210 """
212 if source is _null:
213 source = target
214 target = None
215 if not target is None and not SCons.Util.is_List(target):
216 target = [target]
217 if not source is None and not SCons.Util.is_List(source):
218 source = [source]
219 return apply(MethodWrapper.__call__, (self, target, source) + args, kw)
220
222 return '<BuilderWrapper %s>' % repr(self.name)
223
226
228 if name == 'env':
229 return self.object
230 elif name == 'builder':
231 return self.method
232 else:
233 raise AttributeError, name
234
236 if name == 'env':
237 self.object = value
238 elif name == 'builder':
239 self.method = value
240 else:
241 self.__dict__[name] = value
242
243
244
245
246
247
248
249
250
251
252
253
255 """This is a dictionary-like class used by an Environment to hold
256 the Builders. We need to do this because every time someone changes
257 the Builders in the Environment's BUILDERS dictionary, we must
258 update the Environment's attributes."""
260
261
262
263 self.env = env
264 UserDict.__init__(self, dict)
265
267 return self.__class__(self.data, self.env)
268
270 try:
271 method = getattr(self.env, item).method
272 except AttributeError:
273 pass
274 else:
275 self.env.RemoveMethod(method)
276 UserDict.__setitem__(self, item, val)
277 BuilderWrapper(self.env, val, item)
278
280 UserDict.__delitem__(self, item)
281 delattr(self.env, item)
282
286
287
288
289 _is_valid_var = re.compile(r'[_a-zA-Z]\w*$')
290
292 """Return if the specified string is a legitimate construction
293 variable.
294 """
295 return _is_valid_var.match(varstr)
296
297
298
300 """Base class for different flavors of construction environments.
301
302 This class contains a minimal set of methods that handle contruction
303 variable expansion and conversion of strings to Nodes, which may or
304 may not be actually useful as a stand-alone class. Which methods
305 ended up in this class is pretty arbitrary right now. They're
306 basically the ones which we've empirically determined are common to
307 the different construction environment subclasses, and most of the
308 others that use or touch the underlying dictionary of construction
309 variables.
310
311 Eventually, this class should contain all the methods that we
312 determine are necessary for a "minimal" interface to the build engine.
313 A full "native Python" SCons environment has gotten pretty heavyweight
314 with all of the methods and Tools and construction variables we've
315 jammed in there, so it would be nice to have a lighter weight
316 alternative for interfaces that don't need all of the bells and
317 whistles. (At some point, we'll also probably rename this class
318 "Base," since that more reflects what we want this class to become,
319 but because we've released comments that tell people to subclass
320 Environment.Base to create their own flavors of construction
321 environment, we'll save that for a future refactoring when this
322 class actually becomes useful.)
323 """
324
325 if SCons.Memoize.use_memoizer:
326 __metaclass__ = SCons.Memoize.Memoized_Metaclass
327
338
339
341 """Initial the dispatch tables for special handling of
342 special construction variables."""
343 self._special_del = {}
344 self._special_del['SCANNERS'] = _del_SCANNERS
345
346 self._special_set = {}
347 for key in reserved_construction_var_names:
348 self._special_set[key] = _set_reserved
349 self._special_set['BUILDERS'] = _set_BUILDERS
350 self._special_set['SCANNERS'] = _set_SCANNERS
351
352
353
354
355 self._special_set_keys = self._special_set.keys()
356
358 return cmp(self._dict, other._dict)
359
361 special = self._special_del.get(key)
362 if special:
363 special(self, key)
364 else:
365 del self._dict[key]
366
368 return self._dict[key]
369
371
372
373
374
375
376
377
378
379
380
381
382
383 if key in self._special_set_keys:
384 self._special_set[key](self, key, value)
385 else:
386
387
388
389
390 if not self._dict.has_key(key) \
391 and not _is_valid_var.match(key):
392 raise SCons.Errors.UserError, "Illegal construction variable `%s'" % key
393 self._dict[key] = value
394
395 - def get(self, key, default=None):
396 "Emulates the get() method of dictionaries."""
397 return self._dict.get(key, default)
398
401
403 return self._dict.items()
404
406 if node_factory is _null:
407 node_factory = self.fs.File
408 if lookup_list is _null:
409 lookup_list = self.lookup_list
410
411 if not args:
412 return []
413
414 args = SCons.Util.flatten(args)
415
416 nodes = []
417 for v in args:
418 if SCons.Util.is_String(v):
419 n = None
420 for l in lookup_list:
421 n = l(v)
422 if not n is None:
423 break
424 if not n is None:
425 if SCons.Util.is_String(n):
426
427 kw['raw'] = 1
428 n = apply(self.subst, (n,), kw)
429 if node_factory:
430 n = node_factory(n)
431 if SCons.Util.is_List(n):
432 nodes.extend(n)
433 else:
434 nodes.append(n)
435 elif node_factory:
436
437 kw['raw'] = 1
438 v = node_factory(apply(self.subst, (v,), kw))
439 if SCons.Util.is_List(v):
440 nodes.extend(v)
441 else:
442 nodes.append(v)
443 else:
444 nodes.append(v)
445
446 return nodes
447
450
453
454 - def subst(self, string, raw=0, target=None, source=None, conv=None):
455 """Recursively interpolates construction variables from the
456 Environment into the specified string, returning the expanded
457 result. Construction variables are specified by a $ prefix
458 in the string and begin with an initial underscore or
459 alphabetic character followed by any number of underscores
460 or alphanumeric characters. The construction variable names
461 may be surrounded by curly braces to separate the name from
462 trailing characters.
463 """
464 gvars = self.gvars()
465 lvars = self.lvars()
466 lvars['__env__'] = self
467 return SCons.Subst.scons_subst(string, self, raw, target, source, gvars, lvars, conv)
468
469 - def subst_kw(self, kw, raw=0, target=None, source=None):
470 nkw = {}
471 for k, v in kw.items():
472 k = self.subst(k, raw, target, source)
473 if SCons.Util.is_String(v):
474 v = self.subst(v, raw, target, source)
475 nkw[k] = v
476 return nkw
477
478 - def subst_list(self, string, raw=0, target=None, source=None, conv=None):
485
486 - def subst_path(self, path, target=None, source=None):
487 """Substitute a path list, turning EntryProxies into Nodes
488 and leaving Nodes (and other objects) as-is."""
489
490 if not SCons.Util.is_List(path):
491 path = [path]
492
493 def s(obj):
494 """This is the "string conversion" routine that we have our
495 substitutions use to return Nodes, not strings. This relies
496 on the fact that an EntryProxy object has a get() method that
497 returns the underlying Node that it wraps, which is a bit of
498 architectural dependence that we might need to break or modify
499 in the future in response to additional requirements."""
500 try:
501 get = obj.get
502 except AttributeError:
503 obj = SCons.Util.to_String_for_subst(obj)
504 else:
505 obj = get()
506 return obj
507
508 r = []
509 for p in path:
510 if SCons.Util.is_String(p):
511 p = self.subst(p, target=target, source=source, conv=s)
512 if SCons.Util.is_List(p):
513 if len(p) == 1:
514 p = p[0]
515 else:
516
517
518
519 p = string.join(map(SCons.Util.to_String_for_subst, p), '')
520 else:
521 p = s(p)
522 r.append(p)
523 return r
524
525 subst_target_source = subst
526
528 import subprocess
529
530 kw = { 'stdout' : subprocess.PIPE,
531 'stderr' : subprocess.PIPE,
532 'universal_newlines' : True,
533 }
534
535
536 if not SCons.Util.is_List(command): kw['shell'] = True
537
538
539 p = apply(SCons.Action._subproc, (self, command), kw)
540 out,err = p.communicate()
541 status = p.wait()
542 if err:
543 sys.stderr.write(err)
544 if status:
545 raise OSError("'%s' exited %d" % (command, status))
546 return out
547
549 """
550 Adds the specified function as a method of this construction
551 environment with the specified name. If the name is omitted,
552 the default name is the name of the function itself.
553 """
554 method = MethodWrapper(self, function, name)
555 self.added_methods.append(method)
556
558 """
559 Removes the specified function's MethodWrapper from the
560 added_methods list, so we don't re-bind it when making a clone.
561 """
562 is_not_func = lambda dm, f=function: not dm.method is f
563 self.added_methods = filter(is_not_func, self.added_methods)
564
566 """
567 Produce a modified environment whose variables are overriden by
568 the overrides dictionaries. "overrides" is a dictionary that
569 will override the variables of this environment.
570
571 This function is much more efficient than Clone() or creating
572 a new Environment because it doesn't copy the construction
573 environment dictionary, it just wraps the underlying construction
574 environment, and doesn't even create a wrapper object if there
575 are no overrides.
576 """
577 if not overrides: return self
578 o = copy_non_reserved_keywords(overrides)
579 if not o: return self
580 overrides = {}
581 merges = None
582 for key, value in o.items():
583 if key == 'parse_flags':
584 merges = value
585 else:
586 overrides[key] = SCons.Subst.scons_subst_once(value, self, key)
587 env = OverrideEnvironment(self, overrides)
588 if merges: env.MergeFlags(merges)
589 return env
590
592 """
593 Parse the set of flags and return a dict with the flags placed
594 in the appropriate entry. The flags are treated as a typical
595 set of command-line flags for a GNU-like toolchain and used to
596 populate the entries in the dict immediately below. If one of
597 the flag strings begins with a bang (exclamation mark), it is
598 assumed to be a command and the rest of the string is executed;
599 the result of that evaluation is then added to the dict.
600 """
601 dict = {
602 'ASFLAGS' : SCons.Util.CLVar(''),
603 'CFLAGS' : SCons.Util.CLVar(''),
604 'CCFLAGS' : SCons.Util.CLVar(''),
605 'CPPDEFINES' : [],
606 'CPPFLAGS' : SCons.Util.CLVar(''),
607 'CPPPATH' : [],
608 'FRAMEWORKPATH' : SCons.Util.CLVar(''),
609 'FRAMEWORKS' : SCons.Util.CLVar(''),
610 'LIBPATH' : [],
611 'LIBS' : [],
612 'LINKFLAGS' : SCons.Util.CLVar(''),
613 'RPATH' : [],
614 }
615
616
617
618 def do_parse(arg, me, self = self, dict = dict):
619
620 if not arg:
621 return
622
623 if not SCons.Util.is_String(arg):
624 for t in arg: me(t, me)
625 return
626
627
628 if arg[0] == '!':
629 arg = self.backtick(arg[1:])
630
631
632 def append_define(name, dict = dict):
633 t = string.split(name, '=')
634 if len(t) == 1:
635 dict['CPPDEFINES'].append(name)
636 else:
637 dict['CPPDEFINES'].append([t[0], string.join(t[1:], '=')])
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659 params = shlex.split(arg)
660 append_next_arg_to = None
661 for arg in params:
662 if append_next_arg_to:
663 if append_next_arg_to == 'CPPDEFINES':
664 append_define(arg)
665 elif append_next_arg_to == '-include':
666 t = ('-include', self.fs.File(arg))
667 dict['CCFLAGS'].append(t)
668 elif append_next_arg_to == '-isysroot':
669 t = ('-isysroot', arg)
670 dict['CCFLAGS'].append(t)
671 dict['LINKFLAGS'].append(t)
672 elif append_next_arg_to == '-arch':
673 t = ('-arch', arg)
674 dict['CCFLAGS'].append(t)
675 dict['LINKFLAGS'].append(t)
676 else:
677 dict[append_next_arg_to].append(arg)
678 append_next_arg_to = None
679 elif not arg[0] in ['-', '+']:
680 dict['LIBS'].append(self.fs.File(arg))
681 elif arg[:2] == '-L':
682 if arg[2:]:
683 dict['LIBPATH'].append(arg[2:])
684 else:
685 append_next_arg_to = 'LIBPATH'
686 elif arg[:2] == '-l':
687 if arg[2:]:
688 dict['LIBS'].append(arg[2:])
689 else:
690 append_next_arg_to = 'LIBS'
691 elif arg[:2] == '-I':
692 if arg[2:]:
693 dict['CPPPATH'].append(arg[2:])
694 else:
695 append_next_arg_to = 'CPPPATH'
696 elif arg[:4] == '-Wa,':
697 dict['ASFLAGS'].append(arg[4:])
698 dict['CCFLAGS'].append(arg)
699 elif arg[:4] == '-Wl,':
700 if arg[:11] == '-Wl,-rpath=':
701 dict['RPATH'].append(arg[11:])
702 elif arg[:7] == '-Wl,-R,':
703 dict['RPATH'].append(arg[7:])
704 elif arg[:6] == '-Wl,-R':
705 dict['RPATH'].append(arg[6:])
706 else:
707 dict['LINKFLAGS'].append(arg)
708 elif arg[:4] == '-Wp,':
709 dict['CPPFLAGS'].append(arg)
710 elif arg[:2] == '-D':
711 if arg[2:]:
712 append_define(arg[2:])
713 else:
714 append_next_arg_to = 'CPPDEFINES'
715 elif arg == '-framework':
716 append_next_arg_to = 'FRAMEWORKS'
717 elif arg[:14] == '-frameworkdir=':
718 dict['FRAMEWORKPATH'].append(arg[14:])
719 elif arg[:2] == '-F':
720 if arg[2:]:
721 dict['FRAMEWORKPATH'].append(arg[2:])
722 else:
723 append_next_arg_to = 'FRAMEWORKPATH'
724 elif arg == '-mno-cygwin':
725 dict['CCFLAGS'].append(arg)
726 dict['LINKFLAGS'].append(arg)
727 elif arg == '-mwindows':
728 dict['LINKFLAGS'].append(arg)
729 elif arg == '-pthread':
730 dict['CCFLAGS'].append(arg)
731 dict['LINKFLAGS'].append(arg)
732 elif arg[:5] == '-std=':
733 dict['CFLAGS'].append(arg)
734 elif arg[0] == '+':
735 dict['CCFLAGS'].append(arg)
736 dict['LINKFLAGS'].append(arg)
737 elif arg in ['-include', '-isysroot', '-arch']:
738 append_next_arg_to = arg
739 else:
740 dict['CCFLAGS'].append(arg)
741
742 for arg in flags:
743 do_parse(arg, do_parse)
744 return dict
745
747 """
748 Merge the dict in args into the construction variables of this
749 env, or the passed-in dict. If args is not a dict, it is
750 converted into a dict using ParseFlags. If unique is not set,
751 the flags are appended rather than merged.
752 """
753
754 if dict is None:
755 dict = self
756 if not SCons.Util.is_Dict(args):
757 args = self.ParseFlags(args)
758 if not unique:
759 apply(self.Append, (), args)
760 return self
761 for key, value in args.items():
762 if not value:
763 continue
764 try:
765 orig = self[key]
766 except KeyError:
767 orig = value
768 else:
769 if not orig:
770 orig = value
771 elif value:
772
773
774
775
776
777
778 try:
779 orig = orig + value
780 except (KeyError, TypeError):
781 try:
782 add_to_orig = orig.append
783 except AttributeError:
784 value.insert(0, orig)
785 orig = value
786 else:
787 add_to_orig(value)
788 t = []
789 if key[-4:] == 'PATH':
790
791 for v in orig:
792 if v not in t:
793 t.append(v)
794 else:
795
796 orig.reverse()
797 for v in orig:
798 if v not in t:
799 t.insert(0, v)
800 self[key] = t
801 return self
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
833
837
841
843 f = SCons.Defaults.DefaultEnvironment().copy_from_cache
844 return f(src, dst)
845
846 -class Base(SubstitutionEnvironment):
847 """Base class for "real" construction Environments. These are the
848 primary objects used to communicate dependency and construction
849 information to the build engine.
850
851 Keyword arguments supplied when the construction Environment
852 is created are construction variables used to initialize the
853 Environment.
854 """
855
856 if SCons.Memoize.use_memoizer:
857 __metaclass__ = SCons.Memoize.Memoized_Metaclass
858
859 memoizer_counters = []
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875 - def __init__(self,
876 platform=None,
877 tools=None,
878 toolpath=None,
879 variables=None,
880 parse_flags = None,
881 **kw):
882 """
883 Initialization of a basic SCons construction environment,
884 including setting up special construction variables like BUILDER,
885 PLATFORM, etc., and searching for and applying available Tools.
886
887 Note that we do *not* call the underlying base class
888 (SubsitutionEnvironment) initialization, because we need to
889 initialize things in a very specific order that doesn't work
890 with the much simpler base class initialization.
891 """
892 if __debug__: logInstanceCreation(self, 'Environment.Base')
893 self._memo = {}
894 self.fs = SCons.Node.FS.get_default_fs()
895 self.ans = SCons.Node.Alias.default_ans
896 self.lookup_list = SCons.Node.arg2nodes_lookups
897 self._dict = semi_deepcopy(SCons.Defaults.ConstructionEnvironment)
898 self._init_special()
899 self.added_methods = []
900
901
902
903
904
905
906
907 self.decide_target = default_decide_target
908 self.decide_source = default_decide_source
909
910 self.copy_from_cache = default_copy_from_cache
911
912 self._dict['BUILDERS'] = BuilderDict(self._dict['BUILDERS'], self)
913
914 if platform is None:
915 platform = self._dict.get('PLATFORM', None)
916 if platform is None:
917 platform = SCons.Platform.Platform()
918 if SCons.Util.is_String(platform):
919 platform = SCons.Platform.Platform(platform)
920 self._dict['PLATFORM'] = str(platform)
921 platform(self)
922
923
924
925
926 if kw.has_key('options'):
927
928
929 variables = kw['options']
930 del kw['options']
931 apply(self.Replace, (), kw)
932 keys = kw.keys()
933 if variables:
934 keys = keys + variables.keys()
935 variables.Update(self)
936
937 save = {}
938 for k in keys:
939 try:
940 save[k] = self._dict[k]
941 except KeyError:
942
943
944 pass
945
946 SCons.Tool.Initializers(self)
947
948 if tools is None:
949 tools = self._dict.get('TOOLS', None)
950 if tools is None:
951 tools = ['default']
952 apply_tools(self, tools, toolpath)
953
954
955
956
957 for key, val in save.items():
958 self._dict[key] = val
959
960
961 if parse_flags: self.MergeFlags(parse_flags)
962
963
964
965
966
967
969 """Fetch the builder with the specified name from the environment.
970 """
971 try:
972 return self._dict['BUILDERS'][name]
973 except KeyError:
974 return None
975
977 try:
978 path = self._CacheDir_path
979 except AttributeError:
980 path = SCons.Defaults.DefaultEnvironment()._CacheDir_path
981 try:
982 if path == self._last_CacheDir_path:
983 return self._last_CacheDir
984 except AttributeError:
985 pass
986 cd = SCons.CacheDir.CacheDir(path)
987 self._last_CacheDir_path = path
988 self._last_CacheDir = cd
989 return cd
990
992 """Return a factory function for creating Nodes for this
993 construction environment.
994 """
995 name = default
996 try:
997 is_node = issubclass(factory, SCons.Node.Node)
998 except TypeError:
999
1000
1001 pass
1002 else:
1003 if is_node:
1004
1005
1006
1007
1008 try: name = factory.__name__
1009 except AttributeError: pass
1010 else: factory = None
1011 if not factory:
1012
1013
1014
1015
1016
1017 factory = getattr(self.fs, name)
1018 return factory
1019
1020 memoizer_counters.append(SCons.Memoize.CountValue('_gsm'))
1021
1023 try:
1024 return self._memo['_gsm']
1025 except KeyError:
1026 pass
1027
1028 result = {}
1029
1030 try:
1031 scanners = self._dict['SCANNERS']
1032 except KeyError:
1033 pass
1034 else:
1035
1036
1037
1038
1039 if not SCons.Util.is_List(scanners):
1040 scanners = [scanners]
1041 else:
1042 scanners = scanners[:]
1043 scanners.reverse()
1044 for scanner in scanners:
1045 for k in scanner.get_skeys(self):
1046 result[k] = scanner
1047
1048 self._memo['_gsm'] = result
1049
1050 return result
1051
1053 """Find the appropriate scanner given a key (usually a file suffix).
1054 """
1055 return self._gsm().get(skey)
1056
1058 """Delete the cached scanner map (if we need to).
1059 """
1060 try:
1061 del self._memo['_gsm']
1062 except KeyError:
1063 pass
1064
1066 """Update an environment's values directly, bypassing the normal
1067 checks that occur when users try to set items.
1068 """
1069 self._dict.update(dict)
1070
1072 try:
1073 return self.src_sig_type
1074 except AttributeError:
1075 t = SCons.Defaults.DefaultEnvironment().src_sig_type
1076 self.src_sig_type = t
1077 return t
1078
1080 try:
1081 return self.tgt_sig_type
1082 except AttributeError:
1083 t = SCons.Defaults.DefaultEnvironment().tgt_sig_type
1084 self.tgt_sig_type = t
1085 return t
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1097 """Append values to existing construction variables
1098 in an Environment.
1099 """
1100 kw = copy_non_reserved_keywords(kw)
1101 for key, val in kw.items():
1102
1103
1104
1105
1106 try:
1107 orig = self._dict[key]
1108 except KeyError:
1109
1110
1111 self._dict[key] = val
1112 else:
1113 try:
1114
1115
1116
1117
1118
1119 update_dict = orig.update
1120 except AttributeError:
1121 try:
1122
1123
1124
1125 self._dict[key] = orig + val
1126 except (KeyError, TypeError):
1127 try:
1128
1129 add_to_orig = orig.append
1130 except AttributeError:
1131
1132
1133
1134
1135
1136 if orig:
1137 val.insert(0, orig)
1138 self._dict[key] = val
1139 else:
1140
1141
1142 if val:
1143 add_to_orig(val)
1144 else:
1145
1146
1147 if SCons.Util.is_List(val):
1148 for v in val:
1149 orig[v] = None
1150 else:
1151 try:
1152 update_dict(val)
1153 except (AttributeError, TypeError, ValueError):
1154 if SCons.Util.is_Dict(val):
1155 for k, v in val.items():
1156 orig[k] = v
1157 else:
1158 orig[val] = None
1159 self.scanner_map_delete(kw)
1160
1163 """Append path elements to the path 'name' in the 'ENV'
1164 dictionary for this environment. Will only add any particular
1165 path once, and will normpath and normcase all paths to help
1166 assure this. This can also handle the case where the env
1167 variable is a list instead of a string.
1168
1169 If delete_existing is 0, a newpath which is already in the path
1170 will not be moved to the end (it will be left where it is).
1171 """
1172
1173 orig = ''
1174 if self._dict.has_key(envname) and self._dict[envname].has_key(name):
1175 orig = self._dict[envname][name]
1176
1177 nv = SCons.Util.AppendPath(orig, newpath, sep, delete_existing)
1178
1179 if not self._dict.has_key(envname):
1180 self._dict[envname] = {}
1181
1182 self._dict[envname][name] = nv
1183
1185 """Append values to existing construction variables
1186 in an Environment, if they're not already there.
1187 If delete_existing is 1, removes existing values first, so
1188 values move to end.
1189 """
1190 kw = copy_non_reserved_keywords(kw)
1191 for key, val in kw.items():
1192 if not self._dict.has_key(key) or self._dict[key] in ('', None):
1193 self._dict[key] = val
1194 elif SCons.Util.is_Dict(self._dict[key]) and \
1195 SCons.Util.is_Dict(val):
1196 self._dict[key].update(val)
1197 elif SCons.Util.is_List(val):
1198 dk = self._dict[key]
1199 if not SCons.Util.is_List(dk):
1200 dk = [dk]
1201 if delete_existing:
1202 dk = filter(lambda x, val=val: x not in val, dk)
1203 else:
1204 val = filter(lambda x, dk=dk: x not in dk, val)
1205 self._dict[key] = dk + val
1206 else:
1207 dk = self._dict[key]
1208 if SCons.Util.is_List(dk):
1209
1210
1211 if delete_existing:
1212 dk = filter(lambda x, val=val: x not in val, dk)
1213 self._dict[key] = dk + [val]
1214 else:
1215 if not val in dk:
1216 self._dict[key] = dk + [val]
1217 else:
1218 if delete_existing:
1219 dk = filter(lambda x, val=val: x not in val, dk)
1220 self._dict[key] = dk + val
1221 self.scanner_map_delete(kw)
1222
1223 - def Clone(self, tools=[], toolpath=None, parse_flags = None, **kw):
1224 """Return a copy of a construction Environment. The
1225 copy is like a Python "deep copy"--that is, independent
1226 copies are made recursively of each objects--except that
1227 a reference is copied when an object is not deep-copyable
1228 (like a function). There are no references to any mutable
1229 objects in the original Environment.
1230 """
1231 clone = copy.copy(self)
1232 clone._dict = semi_deepcopy(self._dict)
1233
1234 try:
1235 cbd = clone._dict['BUILDERS']
1236 except KeyError:
1237 pass
1238 else:
1239 clone._dict['BUILDERS'] = BuilderDict(cbd, clone)
1240
1241
1242
1243
1244
1245 clone.added_methods = []
1246 for mw in self.added_methods:
1247 if mw == getattr(self, mw.name):
1248 clone.added_methods.append(mw.clone(clone))
1249
1250 clone._memo = {}
1251
1252
1253
1254 kw = copy_non_reserved_keywords(kw)
1255 new = {}
1256 for key, value in kw.items():
1257 new[key] = SCons.Subst.scons_subst_once(value, self, key)
1258 apply(clone.Replace, (), new)
1259
1260 apply_tools(clone, tools, toolpath)
1261
1262
1263 apply(clone.Replace, (), new)
1264
1265
1266 if parse_flags: clone.MergeFlags(parse_flags)
1267
1268 if __debug__: logInstanceCreation(self, 'Environment.EnvironmentClone')
1269 return clone
1270
1271 - def Copy(self, *args, **kw):
1278
1283
1284 - def _changed_content(self, dependency, target, prev_ni):
1285 return dependency.changed_content(target, prev_ni)
1286
1294
1295 - def _changed_timestamp_then_content(self, dependency, target, prev_ni):
1296 return dependency.changed_timestamp_then_content(target, prev_ni)
1297
1300
1303
1305 return self.fs.copy(src, dst)
1306
1308 return self.fs.copy2(src, dst)
1309
1333
1335 """Return the first available program in progs.
1336 """
1337 if not SCons.Util.is_List(progs):
1338 progs = [ progs ]
1339 for prog in progs:
1340 path = self.WhereIs(prog)
1341 if path: return prog
1342 return None
1343
1345 if not args:
1346 return self._dict
1347 dlist = map(lambda x, s=self: s._dict[x], args)
1348 if len(dlist) == 1:
1349 dlist = dlist[0]
1350 return dlist
1351
1352 - def Dump(self, key = None):
1353 """
1354 Using the standard Python pretty printer, dump the contents of the
1355 scons build environment to stdout.
1356
1357 If the key passed in is anything other than None, then that will
1358 be used as an index into the build environment dictionary and
1359 whatever is found there will be fed into the pretty printer. Note
1360 that this key is case sensitive.
1361 """
1362 import pprint
1363 pp = pprint.PrettyPrinter(indent=2)
1364 if key:
1365 dict = self.Dictionary(key)
1366 else:
1367 dict = self.Dictionary()
1368 return pp.pformat(dict)
1369
1370 - def FindIxes(self, paths, prefix, suffix):
1371 """
1372 Search a list of paths for something that matches the prefix and suffix.
1373
1374 paths - the list of paths or nodes.
1375 prefix - construction variable for the prefix.
1376 suffix - construction variable for the suffix.
1377 """
1378
1379 suffix = self.subst('$'+suffix)
1380 prefix = self.subst('$'+prefix)
1381
1382 for path in paths:
1383 dir,name = os.path.split(str(path))
1384 if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix:
1385 return path
1386
1387 - def ParseConfig(self, command, function=None, unique=1):
1388 """
1389 Use the specified function to parse the output of the command
1390 in order to modify the current environment. The 'command' can
1391 be a string or a list of strings representing a command and
1392 its arguments. 'Function' is an optional argument that takes
1393 the environment, the output of the command, and the unique flag.
1394 If no function is specified, MergeFlags, which treats the output
1395 as the result of a typical 'X-config' command (i.e. gtk-config),
1396 will merge the output into the appropriate variables.
1397 """
1398 if function is None:
1399 def parse_conf(env, cmd, unique=unique):
1400 return env.MergeFlags(cmd, unique)
1401 function = parse_conf
1402 if SCons.Util.is_List(command):
1403 command = string.join(command)
1404 command = self.subst(command)
1405 return function(self, self.backtick(command))
1406
1407 - def ParseDepends(self, filename, must_exist=None, only_one=0):
1408 """
1409 Parse a mkdep-style file for explicit dependencies. This is
1410 completely abusable, and should be unnecessary in the "normal"
1411 case of proper SCons configuration, but it may help make
1412 the transition from a Make hierarchy easier for some people
1413 to swallow. It can also be genuinely useful when using a tool
1414 that can write a .d file, but for which writing a scanner would
1415 be too complicated.
1416 """
1417 filename = self.subst(filename)
1418 try:
1419 fp = open(filename, 'r')
1420 except IOError:
1421 if must_exist:
1422 raise
1423 return
1424 lines = SCons.Util.LogicalLines(fp).readlines()
1425 lines = filter(lambda l: l[0] != '#', lines)
1426 tdlist = []
1427 for line in lines:
1428 try:
1429 target, depends = string.split(line, ':', 1)
1430 except (AttributeError, TypeError, ValueError):
1431
1432
1433
1434
1435 pass
1436 else:
1437 tdlist.append((string.split(target), string.split(depends)))
1438 if only_one:
1439 targets = reduce(lambda x, y: x+y, map(lambda p: p[0], tdlist))
1440 if len(targets) > 1:
1441 raise SCons.Errors.UserError, "More than one dependency target found in `%s': %s" % (filename, targets)
1442 for target, depends in tdlist:
1443 self.Depends(target, depends)
1444
1448
1450 """Prepend values to existing construction variables
1451 in an Environment.
1452 """
1453 kw = copy_non_reserved_keywords(kw)
1454 for key, val in kw.items():
1455
1456
1457
1458
1459 try:
1460 orig = self._dict[key]
1461 except KeyError:
1462
1463
1464 self._dict[key] = val
1465 else:
1466 try:
1467
1468
1469
1470
1471
1472 update_dict = orig.update
1473 except AttributeError:
1474 try:
1475
1476
1477
1478 self._dict[key] = val + orig
1479 except (KeyError, TypeError):
1480 try:
1481
1482 add_to_val = val.append
1483 except AttributeError:
1484
1485
1486
1487
1488 if val:
1489 orig.insert(0, val)
1490 else:
1491
1492
1493
1494 if orig:
1495 add_to_val(orig)
1496 self._dict[key] = val
1497 else:
1498
1499
1500 if SCons.Util.is_List(val):
1501 for v in val:
1502 orig[v] = None
1503 else:
1504 try:
1505 update_dict(val)
1506 except (AttributeError, TypeError, ValueError):
1507 if SCons.Util.is_Dict(val):
1508 for k, v in val.items():
1509 orig[k] = v
1510 else:
1511 orig[val] = None
1512 self.scanner_map_delete(kw)
1513
1516 """Prepend path elements to the path 'name' in the 'ENV'
1517 dictionary for this environment. Will only add any particular
1518 path once, and will normpath and normcase all paths to help
1519 assure this. This can also handle the case where the env
1520 variable is a list instead of a string.
1521
1522 If delete_existing is 0, a newpath which is already in the path
1523 will not be moved to the front (it will be left where it is).
1524 """
1525
1526 orig = ''
1527 if self._dict.has_key(envname) and self._dict[envname].has_key(name):
1528 orig = self._dict[envname][name]
1529
1530 nv = SCons.Util.PrependPath(orig, newpath, sep, delete_existing)
1531
1532 if not self._dict.has_key(envname):
1533 self._dict[envname] = {}
1534
1535 self._dict[envname][name] = nv
1536
1538 """Prepend values to existing construction variables
1539 in an Environment, if they're not already there.
1540 If delete_existing is 1, removes existing values first, so
1541 values move to front.
1542 """
1543 kw = copy_non_reserved_keywords(kw)
1544 for key, val in kw.items():
1545 if not self._dict.has_key(key) or self._dict[key] in ('', None):
1546 self._dict[key] = val
1547 elif SCons.Util.is_Dict(self._dict[key]) and \
1548 SCons.Util.is_Dict(val):
1549 self._dict[key].update(val)
1550 elif SCons.Util.is_List(val):
1551 dk = self._dict[key]
1552 if not SCons.Util.is_List(dk):
1553 dk = [dk]
1554 if delete_existing:
1555 dk = filter(lambda x, val=val: x not in val, dk)
1556 else:
1557 val = filter(lambda x, dk=dk: x not in dk, val)
1558 self._dict[key] = val + dk
1559 else:
1560 dk = self._dict[key]
1561 if SCons.Util.is_List(dk):
1562
1563
1564 if delete_existing:
1565 dk = filter(lambda x, val=val: x not in val, dk)
1566 self._dict[key] = [val] + dk
1567 else:
1568 if not val in dk:
1569 self._dict[key] = [val] + dk
1570 else:
1571 if delete_existing:
1572 dk = filter(lambda x, val=val: x not in val, dk)
1573 self._dict[key] = val + dk
1574 self.scanner_map_delete(kw)
1575
1577 """Replace existing construction variables in an Environment
1578 with new construction variables and/or values.
1579 """
1580 try:
1581 kwbd = kw['BUILDERS']
1582 except KeyError:
1583 pass
1584 else:
1585 kwbd = semi_deepcopy(kwbd)
1586 del kw['BUILDERS']
1587 self.__setitem__('BUILDERS', kwbd)
1588 kw = copy_non_reserved_keywords(kw)
1589 self._update(semi_deepcopy(kw))
1590 self.scanner_map_delete(kw)
1591
1592 - def ReplaceIxes(self, path, old_prefix, old_suffix, new_prefix, new_suffix):
1593 """
1594 Replace old_prefix with new_prefix and old_suffix with new_suffix.
1595
1596 env - Environment used to interpolate variables.
1597 path - the path that will be modified.
1598 old_prefix - construction variable for the old prefix.
1599 old_suffix - construction variable for the old suffix.
1600 new_prefix - construction variable for the new prefix.
1601 new_suffix - construction variable for the new suffix.
1602 """
1603 old_prefix = self.subst('$'+old_prefix)
1604 old_suffix = self.subst('$'+old_suffix)
1605
1606 new_prefix = self.subst('$'+new_prefix)
1607 new_suffix = self.subst('$'+new_suffix)
1608
1609 dir,name = os.path.split(str(path))
1610 if name[:len(old_prefix)] == old_prefix:
1611 name = name[len(old_prefix):]
1612 if name[-len(old_suffix):] == old_suffix:
1613 name = name[:-len(old_suffix)]
1614 return os.path.join(dir, new_prefix+name+new_suffix)
1615
1617 for k in kw.keys():
1618 if self._dict.has_key(k):
1619 del kw[k]
1620 apply(self.Replace, (), kw)
1621
1624
1633
1634 - def WhereIs(self, prog, path=None, pathext=None, reject=[]):
1635 """Find prog in the path.
1636 """
1637 if path is None:
1638 try:
1639 path = self['ENV']['PATH']
1640 except KeyError:
1641 pass
1642 elif SCons.Util.is_String(path):
1643 path = self.subst(path)
1644 if pathext is None:
1645 try:
1646 pathext = self['ENV']['PATHEXT']
1647 except KeyError:
1648 pass
1649 elif SCons.Util.is_String(pathext):
1650 pathext = self.subst(pathext)
1651 prog = self.subst(prog)
1652 path = SCons.Util.WhereIs(prog, path, pathext, reject)
1653 if path: return path
1654 return None
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664 - def Action(self, *args, **kw):
1669 nargs = map(subst_string, args)
1670 nkw = self.subst_kw(kw)
1671 return apply(SCons.Action.Action, nargs, nkw)
1672
1682
1683 - def AddPostAction(self, files, action):
1684 nodes = self.arg2nodes(files, self.fs.Entry)
1685 action = SCons.Action.Action(action)
1686 uniq = {}
1687 for executor in map(lambda n: n.get_executor(), nodes):
1688 uniq[executor] = 1
1689 for executor in uniq.keys():
1690 executor.add_post_action(action)
1691 return nodes
1692
1693 - def Alias(self, target, source=[], action=None, **kw):
1694 tlist = self.arg2nodes(target, self.ans.Alias)
1695 if not SCons.Util.is_List(source):
1696 source = [source]
1697 source = filter(None, source)
1698
1699 if not action:
1700 if not source:
1701
1702
1703
1704
1705
1706
1707 return tlist
1708
1709
1710
1711 result = []
1712 for t in tlist:
1713 bld = t.get_builder(AliasBuilder)
1714 result.extend(bld(self, t, source))
1715 return result
1716
1717 nkw = self.subst_kw(kw)
1718 nkw.update({
1719 'action' : SCons.Action.Action(action),
1720 'source_factory' : self.fs.Entry,
1721 'multi' : 1,
1722 'is_explicit' : None,
1723 })
1724 bld = apply(SCons.Builder.Builder, (), nkw)
1725
1726
1727
1728
1729
1730 result = []
1731 for t in tlist:
1732
1733
1734
1735
1736 b = t.get_builder()
1737 if b is None or b is AliasBuilder:
1738 b = bld
1739 else:
1740 nkw['action'] = b.action + action
1741 b = apply(SCons.Builder.Builder, (), nkw)
1742 t.convert()
1743 result.extend(b(self, t, t.sources + source))
1744 return result
1745
1753
1755 if kw.has_key('build_dir'):
1756 kw['variant_dir'] = kw['build_dir']
1757 del kw['build_dir']
1758 return apply(self.VariantDir, args, kw)
1759
1763
1769
1770 - def Clean(self, targets, files):
1779
1791
1792 - def Command(self, target, source, action, **kw):
1793 """Builds the supplied target files from the supplied
1794 source files using the supplied action. Action may
1795 be any type that the Builder constructor will accept
1796 for an action."""
1797 bkw = {
1798 'action' : action,
1799 'target_factory' : self.fs.Entry,
1800 'source_factory' : self.fs.Entry,
1801 }
1802 try: bkw['source_scanner'] = kw['source_scanner']
1803 except KeyError: pass
1804 else: del kw['source_scanner']
1805 bld = apply(SCons.Builder.Builder, (), bkw)
1806 return apply(bld, (self, target, source), kw)
1807
1808 - def Depends(self, target, dependency):
1809 """Explicity specify that 'target's depend on 'dependency'."""
1810 tlist = self.arg2nodes(target, self.fs.Entry)
1811 dlist = self.arg2nodes(dependency, self.fs.Entry)
1812 for t in tlist:
1813 t.add_dependency(dlist)
1814 return tlist
1815
1816 - def Dir(self, name, *args, **kw):
1826
1828 """Tags a target so that it will not be cleaned by -c"""
1829 tlist = []
1830 for t in targets:
1831 tlist.extend(self.arg2nodes(t, self.fs.Entry))
1832 for t in tlist:
1833 t.set_noclean()
1834 return tlist
1835
1837 """Tags a target so that it will not be cached"""
1838 tlist = []
1839 for t in targets:
1840 tlist.extend(self.arg2nodes(t, self.fs.Entry))
1841 for t in tlist:
1842 t.set_nocache()
1843 return tlist
1844
1845 - def Entry(self, name, *args, **kw):
1846 """
1847 """
1848 s = self.subst(name)
1849 if SCons.Util.is_Sequence(s):
1850 result=[]
1851 for e in s:
1852 result.append(apply(self.fs.Entry, (e,) + args, kw))
1853 return result
1854 return apply(self.fs.Entry, (s,) + args, kw)
1855
1858
1859 - def Execute(self, action, *args, **kw):
1860 """Directly execute an action through an Environment
1861 """
1862 action = apply(self.Action, (action,) + args, kw)
1863 result = action([], [], self)
1864 if isinstance(result, SCons.Errors.BuildError):
1865 errstr = result.errstr
1866 if result.filename:
1867 errstr = result.filename + ': ' + errstr
1868 sys.stderr.write("scons: *** %s\n" % errstr)
1869 return result.status
1870 else:
1871 return result
1872
1873 - def File(self, name, *args, **kw):
1883
1888
1891
1898
1901
1902 - def Ignore(self, target, dependency):
1909
1912
1913 - def Local(self, *targets):
1924
1932
1936
1937 - def Requires(self, target, prerequisite):
1938 """Specify that 'prerequisite' must be built before 'target',
1939 (but 'target' does not actually depend on 'prerequisite'
1940 and need not be rebuilt if it changes)."""
1941 tlist = self.arg2nodes(target, self.fs.Entry)
1942 plist = self.arg2nodes(prerequisite, self.fs.Entry)
1943 for t in tlist:
1944 t.add_prerequisite(plist)
1945 return tlist
1946
1955
1956 - def SConsignFile(self, name=".sconsign", dbm_module=None):
1967
1969 """Tell scons that side_effects are built as side
1970 effects of building targets."""
1971 side_effects = self.arg2nodes(side_effect, self.fs.Entry)
1972 targets = self.arg2nodes(target, self.fs.Entry)
1973
1974 for side_effect in side_effects:
1975 if side_effect.multiple_side_effect_has_builder():
1976 raise SCons.Errors.UserError, "Multiple ways to build the same target were specified for: %s" % str(side_effect)
1977 side_effect.add_source(targets)
1978 side_effect.side_effect = 1
1979 self.Precious(side_effect)
1980 for target in targets:
1981 target.side_effects.append(side_effect)
1982 return side_effects
1983
1985 """Arrange for a source code builder for (part of) a tree."""
1986 entries = self.arg2nodes(entry, self.fs.Entry)
1987 for entry in entries:
1988 entry.set_src_builder(builder)
1989 return entries
1990
2008
2010 """This function converts a string or list into a list of strings
2011 or Nodes. This makes things easier for users by allowing files to
2012 be specified as a white-space separated list to be split.
2013 The input rules are:
2014 - A single string containing names separated by spaces. These will be
2015 split apart at the spaces.
2016 - A single Node instance
2017 - A list containing either strings or Node instances. Any strings
2018 in the list are not split at spaces.
2019 In all cases, the function returns a list of Nodes and strings."""
2020 if SCons.Util.is_List(arg):
2021 return map(self.subst, arg)
2022 elif SCons.Util.is_String(arg):
2023 return string.split(self.subst(arg))
2024 else:
2025 return [self.subst(arg)]
2026
2048
2049 - def Value(self, value, built_value=None):
2053
2054 - def VariantDir(self, variant_dir, src_dir, duplicate=1):
2058
2084
2085
2086
2087 map( get_final_srcnode, sources )
2088
2089
2090 return list(set(sources))
2091
2093 """ returns the list of all targets of the Install and InstallAs Builder.
2094 """
2095 from SCons.Tool import install
2096 if install._UNIQUE_INSTALLED_FILES is None:
2097 install._UNIQUE_INSTALLED_FILES = SCons.Util.uniquer_hashables(install._INSTALLED_FILES)
2098 return install._UNIQUE_INSTALLED_FILES
2099
2101 """A proxy that overrides variables in a wrapped construction
2102 environment by returning values from an overrides dictionary in
2103 preference to values from the underlying subject environment.
2104
2105 This is a lightweight (I hope) proxy that passes through most use of
2106 attributes to the underlying Environment.Base class, but has just
2107 enough additional methods defined to act like a real construction
2108 environment with overridden values. It can wrap either a Base
2109 construction environment, or another OverrideEnvironment, which
2110 can in turn nest arbitrary OverrideEnvironments...
2111
2112 Note that we do *not* call the underlying base class
2113 (SubsitutionEnvironment) initialization, because we get most of those
2114 from proxying the attributes of the subject construction environment.
2115 But because we subclass SubstitutionEnvironment, this class also
2116 has inherited arg2nodes() and subst*() methods; those methods can't
2117 be proxied because they need *this* object's methods to fetch the
2118 values from the overrides dictionary.
2119 """
2120
2121 if SCons.Memoize.use_memoizer:
2122 __metaclass__ = SCons.Memoize.Memoized_Metaclass
2123
2124 - def __init__(self, subject, overrides={}):
2125 if __debug__: logInstanceCreation(self, 'Environment.OverrideEnvironment')
2126 self.__dict__['__subject'] = subject
2127 self.__dict__['overrides'] = overrides
2128
2129
2131 return getattr(self.__dict__['__subject'], name)
2133 setattr(self.__dict__['__subject'], name, value)
2134
2135
2137 try:
2138 return self.__dict__['overrides'][key]
2139 except KeyError:
2140 return self.__dict__['__subject'].__getitem__(key)
2146 try:
2147 del self.__dict__['overrides'][key]
2148 except KeyError:
2149 deleted = 0
2150 else:
2151 deleted = 1
2152 try:
2153 result = self.__dict__['__subject'].__delitem__(key)
2154 except KeyError:
2155 if not deleted:
2156 raise
2157 result = None
2158 return result
2159 - def get(self, key, default=None):
2160 """Emulates the get() method of dictionaries."""
2161 try:
2162 return self.__dict__['overrides'][key]
2163 except KeyError:
2164 return self.__dict__['__subject'].get(key, default)
2166 try:
2167 self.__dict__['overrides'][key]
2168 return 1
2169 except KeyError:
2170 return self.__dict__['__subject'].has_key(key)
2172 """Emulates the items() method of dictionaries."""
2173 d = self.__dict__['__subject'].Dictionary().copy()
2174 d.update(self.__dict__['overrides'])
2175 return d
2177 """Emulates the items() method of dictionaries."""
2178 return self.Dictionary().items()
2179
2180
2182 """Update an environment's values directly, bypassing the normal
2183 checks that occur when users try to set items.
2184 """
2185 self.__dict__['overrides'].update(dict)
2186
2188 return self.__dict__['__subject'].gvars()
2189
2194
2195
2199
2200
2201
2202
2203
2204
2205
2206 Environment = Base
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2221 class _NoSubstitutionProxy(Environment):
2222 def __init__(self, subject):
2223 self.__dict__['__subject'] = subject
2224 def __getattr__(self, name):
2225 return getattr(self.__dict__['__subject'], name)
2226 def __setattr__(self, name, value):
2227 return setattr(self.__dict__['__subject'], name, value)
2228 def raw_to_mode(self, dict):
2229 try:
2230 raw = dict['raw']
2231 except KeyError:
2232 pass
2233 else:
2234 del dict['raw']
2235 dict['mode'] = raw
2236 def subst(self, string, *args, **kwargs):
2237 return string
2238 def subst_kw(self, kw, *args, **kwargs):
2239 return kw
2240 def subst_list(self, string, *args, **kwargs):
2241 nargs = (string, self,) + args
2242 nkw = kwargs.copy()
2243 nkw['gvars'] = {}
2244 self.raw_to_mode(nkw)
2245 return apply(SCons.Subst.scons_subst_list, nargs, nkw)
2246 def subst_target_source(self, string, *args, **kwargs):
2247 nargs = (string, self,) + args
2248 nkw = kwargs.copy()
2249 nkw['gvars'] = {}
2250 self.raw_to_mode(nkw)
2251 return apply(SCons.Subst.scons_subst, nargs, nkw)
2252 return _NoSubstitutionProxy(subject)
2253