1 """SCons.Environment
2
3 Base class for construction Environments. These are
4 the primary objects used to communicate dependency and
5 construction information to the build engine.
6
7 Keyword arguments supplied when the construction Environment
8 is created are construction variables used to initialize the
9 Environment
10 """
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 __revision__ = "src/engine/SCons/Environment.py 5023 2010/06/14 22:05:46 scons"
35
36
37 import copy
38 import os
39 import sys
40 import re
41 import shlex
42 from collections import UserDict
43
44 import SCons.Action
45 import SCons.Builder
46 from SCons.Debug import logInstanceCreation
47 import SCons.Defaults
48 import SCons.Errors
49 import SCons.Memoize
50 import SCons.Node
51 import SCons.Node.Alias
52 import SCons.Node.FS
53 import SCons.Node.Python
54 import SCons.Platform
55 import SCons.SConf
56 import SCons.SConsign
57 import SCons.Subst
58 import SCons.Tool
59 import SCons.Util
60 import SCons.Warnings
61
64
65 _null = _Null
66
67 _warn_copy_deprecated = True
68 _warn_source_signatures_deprecated = True
69 _warn_target_signatures_deprecated = True
70
71 CleanTargets = {}
72 CalculatorArgs = {}
73
74 semi_deepcopy = SCons.Util.semi_deepcopy
75
76
77
78
79 UserError = SCons.Errors.UserError
80
83
84 AliasBuilder = SCons.Builder.Builder(action = alias_builder,
85 target_factory = SCons.Node.Alias.default_ans.Alias,
86 source_factory = SCons.Node.FS.Entry,
87 multi = 1,
88 is_explicit = None,
89 name='AliasBuilder')
90
106
107
108
109
110 reserved_construction_var_names = [
111 'CHANGED_SOURCES',
112 'CHANGED_TARGETS',
113 'SOURCE',
114 'SOURCES',
115 'TARGET',
116 'TARGETS',
117 'UNCHANGED_SOURCES',
118 'UNCHANGED_TARGETS',
119 ]
120
121 future_reserved_construction_var_names = [
122
123
124
125 ]
126
135
139
144
157
161
165
167 """Delete duplicates from a sequence, keeping the first or last."""
168 seen={}
169 result=[]
170 if keep_last:
171 l.reverse()
172 for i in l:
173 try:
174 if i not in seen:
175 result.append(i)
176 seen[i]=1
177 except TypeError:
178
179 result.append(i)
180 if keep_last:
181 result.reverse()
182 return result
183
184
185
186
187
188
189
190
191
192
193
194
195
196
198 """
199 A generic Wrapper class that associates a method (which can
200 actually be any callable) with an object. As part of creating this
201 MethodWrapper object an attribute with the specified (by default,
202 the name of the supplied method) is added to the underlying object.
203 When that new "method" is called, our __call__() method adds the
204 object as the first argument, simulating the Python behavior of
205 supplying "self" on method calls.
206
207 We hang on to the name by which the method was added to the underlying
208 base class so that we can provide a method to "clone" ourselves onto
209 a new underlying object being copied (without which we wouldn't need
210 to save that info).
211 """
212 - def __init__(self, object, method, name=None):
213 if name is None:
214 name = method.__name__
215 self.object = object
216 self.method = method
217 self.name = name
218 setattr(self.object, name, self)
219
221 nargs = (self.object,) + args
222 return self.method(*nargs, **kwargs)
223
224 - def clone(self, new_object):
225 """
226 Returns an object that re-binds the underlying "method" to
227 the specified new object.
228 """
229 return self.__class__(new_object, self.method, self.name)
230
232 """
233 A MethodWrapper subclass that that associates an environment with
234 a Builder.
235
236 This mainly exists to wrap the __call__() function so that all calls
237 to Builders can have their argument lists massaged in the same way
238 (treat a lone argument as the source, treat two arguments as target
239 then source, make sure both target and source are lists) without
240 having to have cut-and-paste code to do it.
241
242 As a bit of obsessive backwards compatibility, we also intercept
243 attempts to get or set the "env" or "builder" attributes, which were
244 the names we used before we put the common functionality into the
245 MethodWrapper base class. We'll keep this around for a while in case
246 people shipped Tool modules that reached into the wrapper (like the
247 Tool/qt.py module does, or did). There shouldn't be a lot attribute
248 fetching or setting on these, so a little extra work shouldn't hurt.
249 """
251 if source is _null:
252 source = target
253 target = None
254 if target is not None and not SCons.Util.is_List(target):
255 target = [target]
256 if source is not None and not SCons.Util.is_List(source):
257 source = [source]
258 return MethodWrapper.__call__(self, target, source, *args, **kw)
259
261 return '<BuilderWrapper %s>' % repr(self.name)
262
265
267 if name == 'env':
268 return self.object
269 elif name == 'builder':
270 return self.method
271 else:
272 raise AttributeError(name)
273
275 if name == 'env':
276 self.object = value
277 elif name == 'builder':
278 self.method = value
279 else:
280 self.__dict__[name] = value
281
282
283
284
285
286
287
288
289
290
291
292
294 """This is a dictionary-like class used by an Environment to hold
295 the Builders. We need to do this because every time someone changes
296 the Builders in the Environment's BUILDERS dictionary, we must
297 update the Environment's attributes."""
299
300
301
302 self.env = env
303 UserDict.__init__(self, dict)
304
306 return self.__class__(self.data, self.env)
307
309 try:
310 method = getattr(self.env, item).method
311 except AttributeError:
312 pass
313 else:
314 self.env.RemoveMethod(method)
315 UserDict.__setitem__(self, item, val)
316 BuilderWrapper(self.env, val, item)
317
319 UserDict.__delitem__(self, item)
320 delattr(self.env, item)
321
325
326
327
328 _is_valid_var = re.compile(r'[_a-zA-Z]\w*$')
329
331 """Return if the specified string is a legitimate construction
332 variable.
333 """
334 return _is_valid_var.match(varstr)
335
336
337
339 """Base class for different flavors of construction environments.
340
341 This class contains a minimal set of methods that handle contruction
342 variable expansion and conversion of strings to Nodes, which may or
343 may not be actually useful as a stand-alone class. Which methods
344 ended up in this class is pretty arbitrary right now. They're
345 basically the ones which we've empirically determined are common to
346 the different construction environment subclasses, and most of the
347 others that use or touch the underlying dictionary of construction
348 variables.
349
350 Eventually, this class should contain all the methods that we
351 determine are necessary for a "minimal" interface to the build engine.
352 A full "native Python" SCons environment has gotten pretty heavyweight
353 with all of the methods and Tools and construction variables we've
354 jammed in there, so it would be nice to have a lighter weight
355 alternative for interfaces that don't need all of the bells and
356 whistles. (At some point, we'll also probably rename this class
357 "Base," since that more reflects what we want this class to become,
358 but because we've released comments that tell people to subclass
359 Environment.Base to create their own flavors of construction
360 environment, we'll save that for a future refactoring when this
361 class actually becomes useful.)
362 """
363
364 if SCons.Memoize.use_memoizer:
365 __metaclass__ = SCons.Memoize.Memoized_Metaclass
366
377
378
397
399 return cmp(self._dict, other._dict)
400
402 special = self._special_del.get(key)
403 if special:
404 special(self, key)
405 else:
406 del self._dict[key]
407
409 return self._dict[key]
410
412
413
414
415
416
417
418
419
420
421
422
423
424 if key in self._special_set_keys:
425 self._special_set[key](self, key, value)
426 else:
427
428
429
430
431 if key not in self._dict \
432 and not _is_valid_var.match(key):
433 raise SCons.Errors.UserError("Illegal construction variable `%s'" % key)
434 self._dict[key] = value
435
436 - def get(self, key, default=None):
437 """Emulates the get() method of dictionaries."""
438 return self._dict.get(key, default)
439
441 return key in self._dict
442
445
447 return list(self._dict.items())
448
450 if node_factory is _null:
451 node_factory = self.fs.File
452 if lookup_list is _null:
453 lookup_list = self.lookup_list
454
455 if not args:
456 return []
457
458 args = SCons.Util.flatten(args)
459
460 nodes = []
461 for v in args:
462 if SCons.Util.is_String(v):
463 n = None
464 for l in lookup_list:
465 n = l(v)
466 if n is not None:
467 break
468 if n is not None:
469 if SCons.Util.is_String(n):
470
471 kw['raw'] = 1
472 n = self.subst(n, **kw)
473 if node_factory:
474 n = node_factory(n)
475 if SCons.Util.is_List(n):
476 nodes.extend(n)
477 else:
478 nodes.append(n)
479 elif node_factory:
480
481 kw['raw'] = 1
482 v = node_factory(self.subst(v, **kw))
483 if SCons.Util.is_List(v):
484 nodes.extend(v)
485 else:
486 nodes.append(v)
487 else:
488 nodes.append(v)
489
490 return nodes
491
494
497
498 - def subst(self, string, raw=0, target=None, source=None, conv=None, executor=None):
499 """Recursively interpolates construction variables from the
500 Environment into the specified string, returning the expanded
501 result. Construction variables are specified by a $ prefix
502 in the string and begin with an initial underscore or
503 alphabetic character followed by any number of underscores
504 or alphanumeric characters. The construction variable names
505 may be surrounded by curly braces to separate the name from
506 trailing characters.
507 """
508 gvars = self.gvars()
509 lvars = self.lvars()
510 lvars['__env__'] = self
511 if executor:
512 lvars.update(executor.get_lvars())
513 return SCons.Subst.scons_subst(string, self, raw, target, source, gvars, lvars, conv)
514
515 - def subst_kw(self, kw, raw=0, target=None, source=None):
516 nkw = {}
517 for k, v in kw.items():
518 k = self.subst(k, raw, target, source)
519 if SCons.Util.is_String(v):
520 v = self.subst(v, raw, target, source)
521 nkw[k] = v
522 return nkw
523
524 - def subst_list(self, string, raw=0, target=None, source=None, conv=None, executor=None):
533
534 - def subst_path(self, path, target=None, source=None):
535 """Substitute a path list, turning EntryProxies into Nodes
536 and leaving Nodes (and other objects) as-is."""
537
538 if not SCons.Util.is_List(path):
539 path = [path]
540
541 def s(obj):
542 """This is the "string conversion" routine that we have our
543 substitutions use to return Nodes, not strings. This relies
544 on the fact that an EntryProxy object has a get() method that
545 returns the underlying Node that it wraps, which is a bit of
546 architectural dependence that we might need to break or modify
547 in the future in response to additional requirements."""
548 try:
549 get = obj.get
550 except AttributeError:
551 obj = SCons.Util.to_String_for_subst(obj)
552 else:
553 obj = get()
554 return obj
555
556 r = []
557 for p in path:
558 if SCons.Util.is_String(p):
559 p = self.subst(p, target=target, source=source, conv=s)
560 if SCons.Util.is_List(p):
561 if len(p) == 1:
562 p = p[0]
563 else:
564
565
566
567 p = ''.join(map(SCons.Util.to_String_for_subst, p))
568 else:
569 p = s(p)
570 r.append(p)
571 return r
572
573 subst_target_source = subst
574
576 import subprocess
577
578 kw = { 'stdin' : 'devnull',
579 'stdout' : subprocess.PIPE,
580 'stderr' : subprocess.PIPE,
581 'universal_newlines' : True,
582 }
583
584
585 if not SCons.Util.is_List(command): kw['shell'] = True
586
587 p = SCons.Action._subproc(self, command, **kw)
588 out,err = p.communicate()
589 status = p.wait()
590 if err:
591 sys.stderr.write(unicode(err))
592 if status:
593 raise OSError("'%s' exited %d" % (command, status))
594 return out
595
597 """
598 Adds the specified function as a method of this construction
599 environment with the specified name. If the name is omitted,
600 the default name is the name of the function itself.
601 """
602 method = MethodWrapper(self, function, name)
603 self.added_methods.append(method)
604
606 """
607 Removes the specified function's MethodWrapper from the
608 added_methods list, so we don't re-bind it when making a clone.
609 """
610 self.added_methods = [dm for dm in self.added_methods if not dm.method is function]
611
613 """
614 Produce a modified environment whose variables are overriden by
615 the overrides dictionaries. "overrides" is a dictionary that
616 will override the variables of this environment.
617
618 This function is much more efficient than Clone() or creating
619 a new Environment because it doesn't copy the construction
620 environment dictionary, it just wraps the underlying construction
621 environment, and doesn't even create a wrapper object if there
622 are no overrides.
623 """
624 if not overrides: return self
625 o = copy_non_reserved_keywords(overrides)
626 if not o: return self
627 overrides = {}
628 merges = None
629 for key, value in o.items():
630 if key == 'parse_flags':
631 merges = value
632 else:
633 overrides[key] = SCons.Subst.scons_subst_once(value, self, key)
634 env = OverrideEnvironment(self, overrides)
635 if merges: env.MergeFlags(merges)
636 return env
637
639 """
640 Parse the set of flags and return a dict with the flags placed
641 in the appropriate entry. The flags are treated as a typical
642 set of command-line flags for a GNU-like toolchain and used to
643 populate the entries in the dict immediately below. If one of
644 the flag strings begins with a bang (exclamation mark), it is
645 assumed to be a command and the rest of the string is executed;
646 the result of that evaluation is then added to the dict.
647 """
648 dict = {
649 'ASFLAGS' : SCons.Util.CLVar(''),
650 'CFLAGS' : SCons.Util.CLVar(''),
651 'CCFLAGS' : SCons.Util.CLVar(''),
652 'CPPDEFINES' : [],
653 'CPPFLAGS' : SCons.Util.CLVar(''),
654 'CPPPATH' : [],
655 'FRAMEWORKPATH' : SCons.Util.CLVar(''),
656 'FRAMEWORKS' : SCons.Util.CLVar(''),
657 'LIBPATH' : [],
658 'LIBS' : [],
659 'LINKFLAGS' : SCons.Util.CLVar(''),
660 'RPATH' : [],
661 }
662
663 def do_parse(arg):
664
665 if not arg:
666 return
667
668 if not SCons.Util.is_String(arg):
669 for t in arg: do_parse(t)
670 return
671
672
673 if arg[0] == '!':
674 arg = self.backtick(arg[1:])
675
676
677 def append_define(name, dict = dict):
678 t = name.split('=')
679 if len(t) == 1:
680 dict['CPPDEFINES'].append(name)
681 else:
682 dict['CPPDEFINES'].append([t[0], '='.join(t[1:])])
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704 params = shlex.split(arg)
705 append_next_arg_to = None
706 for arg in params:
707 if append_next_arg_to:
708 if append_next_arg_to == 'CPPDEFINES':
709 append_define(arg)
710 elif append_next_arg_to == '-include':
711 t = ('-include', self.fs.File(arg))
712 dict['CCFLAGS'].append(t)
713 elif append_next_arg_to == '-isysroot':
714 t = ('-isysroot', arg)
715 dict['CCFLAGS'].append(t)
716 dict['LINKFLAGS'].append(t)
717 elif append_next_arg_to == '-arch':
718 t = ('-arch', arg)
719 dict['CCFLAGS'].append(t)
720 dict['LINKFLAGS'].append(t)
721 else:
722 dict[append_next_arg_to].append(arg)
723 append_next_arg_to = None
724 elif not arg[0] in ['-', '+']:
725 dict['LIBS'].append(self.fs.File(arg))
726 elif arg[:2] == '-L':
727 if arg[2:]:
728 dict['LIBPATH'].append(arg[2:])
729 else:
730 append_next_arg_to = 'LIBPATH'
731 elif arg[:2] == '-l':
732 if arg[2:]:
733 dict['LIBS'].append(arg[2:])
734 else:
735 append_next_arg_to = 'LIBS'
736 elif arg[:2] == '-I':
737 if arg[2:]:
738 dict['CPPPATH'].append(arg[2:])
739 else:
740 append_next_arg_to = 'CPPPATH'
741 elif arg[:4] == '-Wa,':
742 dict['ASFLAGS'].append(arg[4:])
743 dict['CCFLAGS'].append(arg)
744 elif arg[:4] == '-Wl,':
745 if arg[:11] == '-Wl,-rpath=':
746 dict['RPATH'].append(arg[11:])
747 elif arg[:7] == '-Wl,-R,':
748 dict['RPATH'].append(arg[7:])
749 elif arg[:6] == '-Wl,-R':
750 dict['RPATH'].append(arg[6:])
751 else:
752 dict['LINKFLAGS'].append(arg)
753 elif arg[:4] == '-Wp,':
754 dict['CPPFLAGS'].append(arg)
755 elif arg[:2] == '-D':
756 if arg[2:]:
757 append_define(arg[2:])
758 else:
759 append_next_arg_to = 'CPPDEFINES'
760 elif arg == '-framework':
761 append_next_arg_to = 'FRAMEWORKS'
762 elif arg[:14] == '-frameworkdir=':
763 dict['FRAMEWORKPATH'].append(arg[14:])
764 elif arg[:2] == '-F':
765 if arg[2:]:
766 dict['FRAMEWORKPATH'].append(arg[2:])
767 else:
768 append_next_arg_to = 'FRAMEWORKPATH'
769 elif arg == '-mno-cygwin':
770 dict['CCFLAGS'].append(arg)
771 dict['LINKFLAGS'].append(arg)
772 elif arg == '-mwindows':
773 dict['LINKFLAGS'].append(arg)
774 elif arg == '-pthread':
775 dict['CCFLAGS'].append(arg)
776 dict['LINKFLAGS'].append(arg)
777 elif arg[:5] == '-std=':
778 dict['CFLAGS'].append(arg)
779 elif arg[0] == '+':
780 dict['CCFLAGS'].append(arg)
781 dict['LINKFLAGS'].append(arg)
782 elif arg in ['-include', '-isysroot', '-arch']:
783 append_next_arg_to = arg
784 else:
785 dict['CCFLAGS'].append(arg)
786
787 for arg in flags:
788 do_parse(arg)
789 return dict
790
792 """
793 Merge the dict in args into the construction variables of this
794 env, or the passed-in dict. If args is not a dict, it is
795 converted into a dict using ParseFlags. If unique is not set,
796 the flags are appended rather than merged.
797 """
798
799 if dict is None:
800 dict = self
801 if not SCons.Util.is_Dict(args):
802 args = self.ParseFlags(args)
803 if not unique:
804 self.Append(**args)
805 return self
806 for key, value in args.items():
807 if not value:
808 continue
809 try:
810 orig = self[key]
811 except KeyError:
812 orig = value
813 else:
814 if not orig:
815 orig = value
816 elif value:
817
818
819
820
821
822
823 try:
824 orig = orig + value
825 except (KeyError, TypeError):
826 try:
827 add_to_orig = orig.append
828 except AttributeError:
829 value.insert(0, orig)
830 orig = value
831 else:
832 add_to_orig(value)
833 t = []
834 if key[-4:] == 'PATH':
835
836 for v in orig:
837 if v not in t:
838 t.append(v)
839 else:
840
841 orig.reverse()
842 for v in orig:
843 if v not in t:
844 t.insert(0, v)
845 self[key] = t
846 return self
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
871
875
877 f = SCons.Defaults.DefaultEnvironment().copy_from_cache
878 return f(src, dst)
879
880 -class Base(SubstitutionEnvironment):
881 """Base class for "real" construction Environments. These are the
882 primary objects used to communicate dependency and construction
883 information to the build engine.
884
885 Keyword arguments supplied when the construction Environment
886 is created are construction variables used to initialize the
887 Environment.
888 """
889
890 memoizer_counters = []
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906 - def __init__(self,
907 platform=None,
908 tools=None,
909 toolpath=None,
910 variables=None,
911 parse_flags = None,
912 **kw):
913 """
914 Initialization of a basic SCons construction environment,
915 including setting up special construction variables like BUILDER,
916 PLATFORM, etc., and searching for and applying available Tools.
917
918 Note that we do *not* call the underlying base class
919 (SubsitutionEnvironment) initialization, because we need to
920 initialize things in a very specific order that doesn't work
921 with the much simpler base class initialization.
922 """
923 if __debug__: logInstanceCreation(self, 'Environment.Base')
924 self._memo = {}
925 self.fs = SCons.Node.FS.get_default_fs()
926 self.ans = SCons.Node.Alias.default_ans
927 self.lookup_list = SCons.Node.arg2nodes_lookups
928 self._dict = semi_deepcopy(SCons.Defaults.ConstructionEnvironment)
929 self._init_special()
930 self.added_methods = []
931
932
933
934
935
936
937
938 self.decide_target = default_decide_target
939 self.decide_source = default_decide_source
940
941 self.copy_from_cache = default_copy_from_cache
942
943 self._dict['BUILDERS'] = BuilderDict(self._dict['BUILDERS'], self)
944
945 if platform is None:
946 platform = self._dict.get('PLATFORM', None)
947 if platform is None:
948 platform = SCons.Platform.Platform()
949 if SCons.Util.is_String(platform):
950 platform = SCons.Platform.Platform(platform)
951 self._dict['PLATFORM'] = str(platform)
952 platform(self)
953
954 self._dict['HOST_OS'] = self._dict.get('HOST_OS',None)
955 self._dict['HOST_ARCH'] = self._dict.get('HOST_ARCH',None)
956
957
958 self._dict['TARGET_OS'] = self._dict.get('HOST_OS',None)
959 self._dict['TARGET_ARCH'] = self._dict.get('HOST_ARCH',None)
960
961
962
963
964
965 if 'options' in kw:
966
967
968 variables = kw['options']
969 del kw['options']
970 self.Replace(**kw)
971 keys = list(kw.keys())
972 if variables:
973 keys = keys + list(variables.keys())
974 variables.Update(self)
975
976 save = {}
977 for k in keys:
978 try:
979 save[k] = self._dict[k]
980 except KeyError:
981
982
983 pass
984
985 SCons.Tool.Initializers(self)
986
987 if tools is None:
988 tools = self._dict.get('TOOLS', None)
989 if tools is None:
990 tools = ['default']
991 apply_tools(self, tools, toolpath)
992
993
994
995
996 for key, val in save.items():
997 self._dict[key] = val
998
999
1000 if parse_flags: self.MergeFlags(parse_flags)
1001
1002
1003
1004
1005
1006
1008 """Fetch the builder with the specified name from the environment.
1009 """
1010 try:
1011 return self._dict['BUILDERS'][name]
1012 except KeyError:
1013 return None
1014
1016 try:
1017 path = self._CacheDir_path
1018 except AttributeError:
1019 path = SCons.Defaults.DefaultEnvironment()._CacheDir_path
1020 try:
1021 if path == self._last_CacheDir_path:
1022 return self._last_CacheDir
1023 except AttributeError:
1024 pass
1025 cd = SCons.CacheDir.CacheDir(path)
1026 self._last_CacheDir_path = path
1027 self._last_CacheDir = cd
1028 return cd
1029
1031 """Return a factory function for creating Nodes for this
1032 construction environment.
1033 """
1034 name = default
1035 try:
1036 is_node = issubclass(factory, SCons.Node.FS.Base)
1037 except TypeError:
1038
1039
1040 pass
1041 else:
1042 if is_node:
1043
1044
1045
1046
1047 try: name = factory.__name__
1048 except AttributeError: pass
1049 else: factory = None
1050 if not factory:
1051
1052
1053
1054
1055
1056 factory = getattr(self.fs, name)
1057 return factory
1058
1059 memoizer_counters.append(SCons.Memoize.CountValue('_gsm'))
1060
1062 try:
1063 return self._memo['_gsm']
1064 except KeyError:
1065 pass
1066
1067 result = {}
1068
1069 try:
1070 scanners = self._dict['SCANNERS']
1071 except KeyError:
1072 pass
1073 else:
1074
1075
1076
1077
1078 if not SCons.Util.is_List(scanners):
1079 scanners = [scanners]
1080 else:
1081 scanners = scanners[:]
1082 scanners.reverse()
1083 for scanner in scanners:
1084 for k in scanner.get_skeys(self):
1085 if k and self['PLATFORM'] == 'win32':
1086 k = k.lower()
1087 result[k] = scanner
1088
1089 self._memo['_gsm'] = result
1090
1091 return result
1092
1094 """Find the appropriate scanner given a key (usually a file suffix).
1095 """
1096 if skey and self['PLATFORM'] == 'win32':
1097 skey = skey.lower()
1098 return self._gsm().get(skey)
1099
1101 """Delete the cached scanner map (if we need to).
1102 """
1103 try:
1104 del self._memo['_gsm']
1105 except KeyError:
1106 pass
1107
1109 """Update an environment's values directly, bypassing the normal
1110 checks that occur when users try to set items.
1111 """
1112 self._dict.update(dict)
1113
1115 try:
1116 return self.src_sig_type
1117 except AttributeError:
1118 t = SCons.Defaults.DefaultEnvironment().src_sig_type
1119 self.src_sig_type = t
1120 return t
1121
1123 try:
1124 return self.tgt_sig_type
1125 except AttributeError:
1126 t = SCons.Defaults.DefaultEnvironment().tgt_sig_type
1127 self.tgt_sig_type = t
1128 return t
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1140 """Append values to existing construction variables
1141 in an Environment.
1142 """
1143 kw = copy_non_reserved_keywords(kw)
1144 for key, val in kw.items():
1145
1146
1147
1148
1149 try:
1150 orig = self._dict[key]
1151 except KeyError:
1152
1153
1154 self._dict[key] = val
1155 else:
1156 try:
1157
1158
1159
1160
1161
1162 update_dict = orig.update
1163 except AttributeError:
1164 try:
1165
1166
1167
1168 self._dict[key] = orig + val
1169 except (KeyError, TypeError):
1170 try:
1171
1172 add_to_orig = orig.append
1173 except AttributeError:
1174
1175
1176
1177
1178
1179 if orig:
1180 val.insert(0, orig)
1181 self._dict[key] = val
1182 else:
1183
1184
1185 if val:
1186 add_to_orig(val)
1187 else:
1188
1189
1190 if SCons.Util.is_List(val):
1191 for v in val:
1192 orig[v] = None
1193 else:
1194 try:
1195 update_dict(val)
1196 except (AttributeError, TypeError, ValueError):
1197 if SCons.Util.is_Dict(val):
1198 for k, v in val.items():
1199 orig[k] = v
1200 else:
1201 orig[val] = None
1202 self.scanner_map_delete(kw)
1203
1204
1205
1212
1215 """Append path elements to the path 'name' in the 'ENV'
1216 dictionary for this environment. Will only add any particular
1217 path once, and will normpath and normcase all paths to help
1218 assure this. This can also handle the case where the env
1219 variable is a list instead of a string.
1220
1221 If delete_existing is 0, a newpath which is already in the path
1222 will not be moved to the end (it will be left where it is).
1223 """
1224
1225 orig = ''
1226 if envname in self._dict and name in self._dict[envname]:
1227 orig = self._dict[envname][name]
1228
1229 nv = SCons.Util.AppendPath(orig, newpath, sep, delete_existing,
1230 canonicalize=self._canonicalize)
1231
1232 if envname not in self._dict:
1233 self._dict[envname] = {}
1234
1235 self._dict[envname][name] = nv
1236
1238 """Append values to existing construction variables
1239 in an Environment, if they're not already there.
1240 If delete_existing is 1, removes existing values first, so
1241 values move to end.
1242 """
1243 kw = copy_non_reserved_keywords(kw)
1244 for key, val in kw.items():
1245 if SCons.Util.is_List(val):
1246 val = _delete_duplicates(val, delete_existing)
1247 if key not in self._dict or self._dict[key] in ('', None):
1248 self._dict[key] = val
1249 elif SCons.Util.is_Dict(self._dict[key]) and \
1250 SCons.Util.is_Dict(val):
1251 self._dict[key].update(val)
1252 elif SCons.Util.is_List(val):
1253 dk = self._dict[key]
1254 if not SCons.Util.is_List(dk):
1255 dk = [dk]
1256 if delete_existing:
1257 dk = [x for x in dk if x not in val]
1258 else:
1259 val = [x for x in val if x not in dk]
1260 self._dict[key] = dk + val
1261 else:
1262 dk = self._dict[key]
1263 if SCons.Util.is_List(dk):
1264
1265
1266 if delete_existing:
1267 dk = [x for x in dk if x not in val]
1268 self._dict[key] = dk + [val]
1269 else:
1270 if not val in dk:
1271 self._dict[key] = dk + [val]
1272 else:
1273 if delete_existing:
1274 dk = [x for x in dk if x not in val]
1275 self._dict[key] = dk + val
1276 self.scanner_map_delete(kw)
1277
1278 - def Clone(self, tools=[], toolpath=None, parse_flags = None, **kw):
1279 """Return a copy of a construction Environment. The
1280 copy is like a Python "deep copy"--that is, independent
1281 copies are made recursively of each objects--except that
1282 a reference is copied when an object is not deep-copyable
1283 (like a function). There are no references to any mutable
1284 objects in the original Environment.
1285 """
1286 clone = copy.copy(self)
1287 clone._dict = semi_deepcopy(self._dict)
1288
1289 try:
1290 cbd = clone._dict['BUILDERS']
1291 except KeyError:
1292 pass
1293 else:
1294 clone._dict['BUILDERS'] = BuilderDict(cbd, clone)
1295
1296
1297
1298
1299
1300 clone.added_methods = []
1301 for mw in self.added_methods:
1302 if mw == getattr(self, mw.name):
1303 clone.added_methods.append(mw.clone(clone))
1304
1305 clone._memo = {}
1306
1307
1308
1309 kw = copy_non_reserved_keywords(kw)
1310 new = {}
1311 for key, value in kw.items():
1312 new[key] = SCons.Subst.scons_subst_once(value, self, key)
1313 clone.Replace(**new)
1314
1315 apply_tools(clone, tools, toolpath)
1316
1317
1318 clone.Replace(**new)
1319
1320
1321 if parse_flags: clone.MergeFlags(parse_flags)
1322
1323 if __debug__: logInstanceCreation(self, 'Environment.EnvironmentClone')
1324 return clone
1325
1326 - def Copy(self, *args, **kw):
1333
1338
1339 - def _changed_content(self, dependency, target, prev_ni):
1340 return dependency.changed_content(target, prev_ni)
1341
1349
1350 - def _changed_timestamp_then_content(self, dependency, target, prev_ni):
1351 return dependency.changed_timestamp_then_content(target, prev_ni)
1352
1355
1358
1360 return self.fs.copy(src, dst)
1361
1363 return self.fs.copy2(src, dst)
1364
1388
1390 """Return the first available program in progs.
1391 """
1392 if not SCons.Util.is_List(progs):
1393 progs = [ progs ]
1394 for prog in progs:
1395 path = self.WhereIs(prog)
1396 if path: return prog
1397 return None
1398
1400 if not args:
1401 return self._dict
1402 dlist = [self._dict[x] for x in args]
1403 if len(dlist) == 1:
1404 dlist = dlist[0]
1405 return dlist
1406
1407 - def Dump(self, key = None):
1408 """
1409 Using the standard Python pretty printer, dump the contents of the
1410 scons build environment to stdout.
1411
1412 If the key passed in is anything other than None, then that will
1413 be used as an index into the build environment dictionary and
1414 whatever is found there will be fed into the pretty printer. Note
1415 that this key is case sensitive.
1416 """
1417 import pprint
1418 pp = pprint.PrettyPrinter(indent=2)
1419 if key:
1420 dict = self.Dictionary(key)
1421 else:
1422 dict = self.Dictionary()
1423 return pp.pformat(dict)
1424
1425 - def FindIxes(self, paths, prefix, suffix):
1426 """
1427 Search a list of paths for something that matches the prefix and suffix.
1428
1429 paths - the list of paths or nodes.
1430 prefix - construction variable for the prefix.
1431 suffix - construction variable for the suffix.
1432 """
1433
1434 suffix = self.subst('$'+suffix)
1435 prefix = self.subst('$'+prefix)
1436
1437 for path in paths:
1438 dir,name = os.path.split(str(path))
1439 if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix:
1440 return path
1441
1442 - def ParseConfig(self, command, function=None, unique=1):
1443 """
1444 Use the specified function to parse the output of the command
1445 in order to modify the current environment. The 'command' can
1446 be a string or a list of strings representing a command and
1447 its arguments. 'Function' is an optional argument that takes
1448 the environment, the output of the command, and the unique flag.
1449 If no function is specified, MergeFlags, which treats the output
1450 as the result of a typical 'X-config' command (i.e. gtk-config),
1451 will merge the output into the appropriate variables.
1452 """
1453 if function is None:
1454 def parse_conf(env, cmd, unique=unique):
1455 return env.MergeFlags(cmd, unique)
1456 function = parse_conf
1457 if SCons.Util.is_List(command):
1458 command = ' '.join(command)
1459 command = self.subst(command)
1460 return function(self, self.backtick(command))
1461
1462 - def ParseDepends(self, filename, must_exist=None, only_one=0):
1463 """
1464 Parse a mkdep-style file for explicit dependencies. This is
1465 completely abusable, and should be unnecessary in the "normal"
1466 case of proper SCons configuration, but it may help make
1467 the transition from a Make hierarchy easier for some people
1468 to swallow. It can also be genuinely useful when using a tool
1469 that can write a .d file, but for which writing a scanner would
1470 be too complicated.
1471 """
1472 filename = self.subst(filename)
1473 try:
1474 fp = open(filename, 'r')
1475 except IOError:
1476 if must_exist:
1477 raise
1478 return
1479 lines = SCons.Util.LogicalLines(fp).readlines()
1480 lines = [l for l in lines if l[0] != '#']
1481 tdlist = []
1482 for line in lines:
1483 try:
1484 target, depends = line.split(':', 1)
1485 except (AttributeError, ValueError):
1486
1487
1488 pass
1489 else:
1490 tdlist.append((target.split(), depends.split()))
1491 if only_one:
1492 targets = []
1493 for td in tdlist:
1494 targets.extend(td[0])
1495 if len(targets) > 1:
1496 raise SCons.Errors.UserError(
1497 "More than one dependency target found in `%s': %s"
1498 % (filename, targets))
1499 for target, depends in tdlist:
1500 self.Depends(target, depends)
1501
1505
1507 """Prepend values to existing construction variables
1508 in an Environment.
1509 """
1510 kw = copy_non_reserved_keywords(kw)
1511 for key, val in kw.items():
1512
1513
1514
1515
1516 try:
1517 orig = self._dict[key]
1518 except KeyError:
1519
1520
1521 self._dict[key] = val
1522 else:
1523 try:
1524
1525
1526
1527
1528
1529 update_dict = orig.update
1530 except AttributeError:
1531 try:
1532
1533
1534
1535 self._dict[key] = val + orig
1536 except (KeyError, TypeError):
1537 try:
1538
1539 add_to_val = val.append
1540 except AttributeError:
1541
1542
1543
1544
1545 if val:
1546 orig.insert(0, val)
1547 else:
1548
1549
1550
1551 if orig:
1552 add_to_val(orig)
1553 self._dict[key] = val
1554 else:
1555
1556
1557 if SCons.Util.is_List(val):
1558 for v in val:
1559 orig[v] = None
1560 else:
1561 try:
1562 update_dict(val)
1563 except (AttributeError, TypeError, ValueError):
1564 if SCons.Util.is_Dict(val):
1565 for k, v in val.items():
1566 orig[k] = v
1567 else:
1568 orig[val] = None
1569 self.scanner_map_delete(kw)
1570
1573 """Prepend path elements to the path 'name' in the 'ENV'
1574 dictionary for this environment. Will only add any particular
1575 path once, and will normpath and normcase all paths to help
1576 assure this. This can also handle the case where the env
1577 variable is a list instead of a string.
1578
1579 If delete_existing is 0, a newpath which is already in the path
1580 will not be moved to the front (it will be left where it is).
1581 """
1582
1583 orig = ''
1584 if envname in self._dict and name in self._dict[envname]:
1585 orig = self._dict[envname][name]
1586
1587 nv = SCons.Util.PrependPath(orig, newpath, sep, delete_existing,
1588 canonicalize=self._canonicalize)
1589
1590 if envname not in self._dict:
1591 self._dict[envname] = {}
1592
1593 self._dict[envname][name] = nv
1594
1596 """Prepend values to existing construction variables
1597 in an Environment, if they're not already there.
1598 If delete_existing is 1, removes existing values first, so
1599 values move to front.
1600 """
1601 kw = copy_non_reserved_keywords(kw)
1602 for key, val in kw.items():
1603 if SCons.Util.is_List(val):
1604 val = _delete_duplicates(val, not delete_existing)
1605 if key not in self._dict or self._dict[key] in ('', None):
1606 self._dict[key] = val
1607 elif SCons.Util.is_Dict(self._dict[key]) and \
1608 SCons.Util.is_Dict(val):
1609 self._dict[key].update(val)
1610 elif SCons.Util.is_List(val):
1611 dk = self._dict[key]
1612 if not SCons.Util.is_List(dk):
1613 dk = [dk]
1614 if delete_existing:
1615 dk = [x for x in dk if x not in val]
1616 else:
1617 val = [x for x in val if x not in dk]
1618 self._dict[key] = val + dk
1619 else:
1620 dk = self._dict[key]
1621 if SCons.Util.is_List(dk):
1622
1623
1624 if delete_existing:
1625 dk = [x for x in dk if x not in val]
1626 self._dict[key] = [val] + dk
1627 else:
1628 if not val in dk:
1629 self._dict[key] = [val] + dk
1630 else:
1631 if delete_existing:
1632 dk = [x for x in dk if x not in val]
1633 self._dict[key] = val + dk
1634 self.scanner_map_delete(kw)
1635
1637 """Replace existing construction variables in an Environment
1638 with new construction variables and/or values.
1639 """
1640 try:
1641 kwbd = kw['BUILDERS']
1642 except KeyError:
1643 pass
1644 else:
1645 kwbd = semi_deepcopy(kwbd)
1646 del kw['BUILDERS']
1647 self.__setitem__('BUILDERS', kwbd)
1648 kw = copy_non_reserved_keywords(kw)
1649 self._update(semi_deepcopy(kw))
1650 self.scanner_map_delete(kw)
1651
1652 - def ReplaceIxes(self, path, old_prefix, old_suffix, new_prefix, new_suffix):
1653 """
1654 Replace old_prefix with new_prefix and old_suffix with new_suffix.
1655
1656 env - Environment used to interpolate variables.
1657 path - the path that will be modified.
1658 old_prefix - construction variable for the old prefix.
1659 old_suffix - construction variable for the old suffix.
1660 new_prefix - construction variable for the new prefix.
1661 new_suffix - construction variable for the new suffix.
1662 """
1663 old_prefix = self.subst('$'+old_prefix)
1664 old_suffix = self.subst('$'+old_suffix)
1665
1666 new_prefix = self.subst('$'+new_prefix)
1667 new_suffix = self.subst('$'+new_suffix)
1668
1669 dir,name = os.path.split(str(path))
1670 if name[:len(old_prefix)] == old_prefix:
1671 name = name[len(old_prefix):]
1672 if name[-len(old_suffix):] == old_suffix:
1673 name = name[:-len(old_suffix)]
1674 return os.path.join(dir, new_prefix+name+new_suffix)
1675
1677 for k in kw.keys():
1678 if k in self._dict:
1679 del kw[k]
1680 self.Replace(**kw)
1681
1684
1693
1694 - def WhereIs(self, prog, path=None, pathext=None, reject=[]):
1695 """Find prog in the path.
1696 """
1697 if path is None:
1698 try:
1699 path = self['ENV']['PATH']
1700 except KeyError:
1701 pass
1702 elif SCons.Util.is_String(path):
1703 path = self.subst(path)
1704 if pathext is None:
1705 try:
1706 pathext = self['ENV']['PATHEXT']
1707 except KeyError:
1708 pass
1709 elif SCons.Util.is_String(pathext):
1710 pathext = self.subst(pathext)
1711 prog = self.subst(prog)
1712 path = SCons.Util.WhereIs(prog, path, pathext, reject)
1713 if path: return path
1714 return None
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724 - def Action(self, *args, **kw):
1725 def subst_string(a, self=self):
1726 if SCons.Util.is_String(a):
1727 a = self.subst(a)
1728 return a
1729 nargs = list(map(subst_string, args))
1730 nkw = self.subst_kw(kw)
1731 return SCons.Action.Action(*nargs, **nkw)
1732
1742
1743 - def AddPostAction(self, files, action):
1744 nodes = self.arg2nodes(files, self.fs.Entry)
1745 action = SCons.Action.Action(action)
1746 uniq = {}
1747 for executor in [n.get_executor() for n in nodes]:
1748 uniq[executor] = 1
1749 for executor in uniq.keys():
1750 executor.add_post_action(action)
1751 return nodes
1752
1753 - def Alias(self, target, source=[], action=None, **kw):
1805
1813
1821
1825
1831
1832 - def Clean(self, targets, files):
1841
1853
1854 - def Command(self, target, source, action, **kw):
1855 """Builds the supplied target files from the supplied
1856 source files using the supplied action. Action may
1857 be any type that the Builder constructor will accept
1858 for an action."""
1859 bkw = {
1860 'action' : action,
1861 'target_factory' : self.fs.Entry,
1862 'source_factory' : self.fs.Entry,
1863 }
1864 try: bkw['source_scanner'] = kw['source_scanner']
1865 except KeyError: pass
1866 else: del kw['source_scanner']
1867 bld = SCons.Builder.Builder(**bkw)
1868 return bld(self, target, source, **kw)
1869
1870 - def Depends(self, target, dependency):
1871 """Explicity specify that 'target's depend on 'dependency'."""
1872 tlist = self.arg2nodes(target, self.fs.Entry)
1873 dlist = self.arg2nodes(dependency, self.fs.Entry)
1874 for t in tlist:
1875 t.add_dependency(dlist)
1876 return tlist
1877
1878 - def Dir(self, name, *args, **kw):
1888
1890 """Tags a target so that it will not be cleaned by -c"""
1891 tlist = []
1892 for t in targets:
1893 tlist.extend(self.arg2nodes(t, self.fs.Entry))
1894 for t in tlist:
1895 t.set_noclean()
1896 return tlist
1897
1899 """Tags a target so that it will not be cached"""
1900 tlist = []
1901 for t in targets:
1902 tlist.extend(self.arg2nodes(t, self.fs.Entry))
1903 for t in tlist:
1904 t.set_nocache()
1905 return tlist
1906
1907 - def Entry(self, name, *args, **kw):
1908 """
1909 """
1910 s = self.subst(name)
1911 if SCons.Util.is_Sequence(s):
1912 result=[]
1913 for e in s:
1914 result.append(self.fs.Entry(e, *args, **kw))
1915 return result
1916 return self.fs.Entry(s, *args, **kw)
1917
1920
1921 - def Execute(self, action, *args, **kw):
1922 """Directly execute an action through an Environment
1923 """
1924 action = self.Action(action, *args, **kw)
1925 result = action([], [], self)
1926 if isinstance(result, SCons.Errors.BuildError):
1927 errstr = result.errstr
1928 if result.filename:
1929 errstr = result.filename + ': ' + errstr
1930 sys.stderr.write("scons: *** %s\n" % errstr)
1931 return result.status
1932 else:
1933 return result
1934
1935 - def File(self, name, *args, **kw):
1945
1950
1953
1960
1961 - def Glob(self, pattern, ondisk=True, source=False, strings=False):
1962 return self.fs.Glob(self.subst(pattern), ondisk, source, strings)
1963
1964 - def Ignore(self, target, dependency):
1971
1974
1975 - def Local(self, *targets):
1986
1994
1998
1999 - def Requires(self, target, prerequisite):
2000 """Specify that 'prerequisite' must be built before 'target',
2001 (but 'target' does not actually depend on 'prerequisite'
2002 and need not be rebuilt if it changes)."""
2003 tlist = self.arg2nodes(target, self.fs.Entry)
2004 plist = self.arg2nodes(prerequisite, self.fs.Entry)
2005 for t in tlist:
2006 t.add_prerequisite(plist)
2007 return tlist
2008
2017
2018 - def SConsignFile(self, name=".sconsign", dbm_module=None):
2029
2031 """Tell scons that side_effects are built as side
2032 effects of building targets."""
2033 side_effects = self.arg2nodes(side_effect, self.fs.Entry)
2034 targets = self.arg2nodes(target, self.fs.Entry)
2035
2036 for side_effect in side_effects:
2037 if side_effect.multiple_side_effect_has_builder():
2038 raise SCons.Errors.UserError("Multiple ways to build the same target were specified for: %s" % str(side_effect))
2039 side_effect.add_source(targets)
2040 side_effect.side_effect = 1
2041 self.Precious(side_effect)
2042 for target in targets:
2043 target.side_effects.append(side_effect)
2044 return side_effects
2045
2055
2073
2075 """This function converts a string or list into a list of strings
2076 or Nodes. This makes things easier for users by allowing files to
2077 be specified as a white-space separated list to be split.
2078 The input rules are:
2079 - A single string containing names separated by spaces. These will be
2080 split apart at the spaces.
2081 - A single Node instance
2082 - A list containing either strings or Node instances. Any strings
2083 in the list are not split at spaces.
2084 In all cases, the function returns a list of Nodes and strings."""
2085 if SCons.Util.is_List(arg):
2086 return list(map(self.subst, arg))
2087 elif SCons.Util.is_String(arg):
2088 return self.subst(arg).split()
2089 else:
2090 return [self.subst(arg)]
2091
2113
2114 - def Value(self, value, built_value=None):
2118
2119 - def VariantDir(self, variant_dir, src_dir, duplicate=1):
2123
2138 build_source(node.all_children())
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149 return list(set(sources))
2150
2152 """ returns the list of all targets of the Install and InstallAs Builder.
2153 """
2154 from SCons.Tool import install
2155 if install._UNIQUE_INSTALLED_FILES is None:
2156 install._UNIQUE_INSTALLED_FILES = SCons.Util.uniquer_hashables(install._INSTALLED_FILES)
2157 return install._UNIQUE_INSTALLED_FILES
2158
2160 """A proxy that overrides variables in a wrapped construction
2161 environment by returning values from an overrides dictionary in
2162 preference to values from the underlying subject environment.
2163
2164 This is a lightweight (I hope) proxy that passes through most use of
2165 attributes to the underlying Environment.Base class, but has just
2166 enough additional methods defined to act like a real construction
2167 environment with overridden values. It can wrap either a Base
2168 construction environment, or another OverrideEnvironment, which
2169 can in turn nest arbitrary OverrideEnvironments...
2170
2171 Note that we do *not* call the underlying base class
2172 (SubsitutionEnvironment) initialization, because we get most of those
2173 from proxying the attributes of the subject construction environment.
2174 But because we subclass SubstitutionEnvironment, this class also
2175 has inherited arg2nodes() and subst*() methods; those methods can't
2176 be proxied because they need *this* object's methods to fetch the
2177 values from the overrides dictionary.
2178 """
2179
2180 - def __init__(self, subject, overrides={}):
2181 if __debug__: logInstanceCreation(self, 'Environment.OverrideEnvironment')
2182 self.__dict__['__subject'] = subject
2183 self.__dict__['overrides'] = overrides
2184
2185
2187 return getattr(self.__dict__['__subject'], name)
2189 setattr(self.__dict__['__subject'], name, value)
2190
2191
2193 try:
2194 return self.__dict__['overrides'][key]
2195 except KeyError:
2196 return self.__dict__['__subject'].__getitem__(key)
2202 try:
2203 del self.__dict__['overrides'][key]
2204 except KeyError:
2205 deleted = 0
2206 else:
2207 deleted = 1
2208 try:
2209 result = self.__dict__['__subject'].__delitem__(key)
2210 except KeyError:
2211 if not deleted:
2212 raise
2213 result = None
2214 return result
2215 - def get(self, key, default=None):
2216 """Emulates the get() method of dictionaries."""
2217 try:
2218 return self.__dict__['overrides'][key]
2219 except KeyError:
2220 return self.__dict__['__subject'].get(key, default)
2222 try:
2223 self.__dict__['overrides'][key]
2224 return 1
2225 except KeyError:
2226 return key in self.__dict__['__subject']
2228 if self.__dict__['overrides'].__contains__(key):
2229 return 1
2230 return self.__dict__['__subject'].__contains__(key)
2232 """Emulates the items() method of dictionaries."""
2233 d = self.__dict__['__subject'].Dictionary().copy()
2234 d.update(self.__dict__['overrides'])
2235 return d
2237 """Emulates the items() method of dictionaries."""
2238 return list(self.Dictionary().items())
2239
2240
2242 """Update an environment's values directly, bypassing the normal
2243 checks that occur when users try to set items.
2244 """
2245 self.__dict__['overrides'].update(dict)
2246
2248 return self.__dict__['__subject'].gvars()
2249
2254
2255
2259
2260
2261
2262
2263
2264
2265
2266 Environment = Base
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2281 class _NoSubstitutionProxy(Environment):
2282 def __init__(self, subject):
2283 self.__dict__['__subject'] = subject
2284 def __getattr__(self, name):
2285 return getattr(self.__dict__['__subject'], name)
2286 def __setattr__(self, name, value):
2287 return setattr(self.__dict__['__subject'], name, value)
2288 def raw_to_mode(self, dict):
2289 try:
2290 raw = dict['raw']
2291 except KeyError:
2292 pass
2293 else:
2294 del dict['raw']
2295 dict['mode'] = raw
2296 def subst(self, string, *args, **kwargs):
2297 return string
2298 def subst_kw(self, kw, *args, **kwargs):
2299 return kw
2300 def subst_list(self, string, *args, **kwargs):
2301 nargs = (string, self,) + args
2302 nkw = kwargs.copy()
2303 nkw['gvars'] = {}
2304 self.raw_to_mode(nkw)
2305 return SCons.Subst.scons_subst_list(*nargs, **nkw)
2306 def subst_target_source(self, string, *args, **kwargs):
2307 nargs = (string, self,) + args
2308 nkw = kwargs.copy()
2309 nkw['gvars'] = {}
2310 self.raw_to_mode(nkw)
2311 return SCons.Subst.scons_subst(*nargs, **nkw)
2312 return _NoSubstitutionProxy(subject)
2313
2314
2315
2316
2317
2318
2319