From 13dcf8c4ebad065d6296e7a3da24b21a1666a974 Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Sat, 2 Apr 2005 19:50:33 +0000 Subject: Remove widespread reliance on SCons.Node.FS.default_fs so we can initialize it once (later than we used to) and eliminate all the __setTopLevelDir() calls. --- src/engine/SCons/Builder.py | 24 +-- src/engine/SCons/BuilderTests.py | 12 +- src/engine/SCons/Environment.py | 46 +++++- src/engine/SCons/EnvironmentTests.py | 181 ++++++++------------- src/engine/SCons/Node/FS.py | 37 ++--- src/engine/SCons/Node/FSTests.py | 2 +- src/engine/SCons/Node/NodeTests.py | 2 + src/engine/SCons/Node/__init__.py | 3 +- src/engine/SCons/SConf.py | 5 +- src/engine/SCons/Scanner/C.py | 5 +- src/engine/SCons/Scanner/CTests.py | 77 +++++---- src/engine/SCons/Scanner/D.py | 5 +- src/engine/SCons/Scanner/Dir.py | 12 +- src/engine/SCons/Scanner/DirTests.py | 19 ++- src/engine/SCons/Scanner/Fortran.py | 12 +- src/engine/SCons/Scanner/FortranTests.py | 100 ++++++------ src/engine/SCons/Scanner/IDL.py | 5 +- src/engine/SCons/Scanner/IDLTests.py | 85 +++++----- src/engine/SCons/Scanner/Prog.py | 6 +- src/engine/SCons/Scanner/ProgTests.py | 18 ++- src/engine/SCons/Scanner/ScannerTests.py | 25 ++- src/engine/SCons/Scanner/__init__.py | 39 +++-- src/engine/SCons/Script/Main.py | 264 ++++++++++++++++++------------- src/engine/SCons/Script/SConscript.py | 8 +- src/engine/SCons/Tool/Perforce.py | 2 +- src/engine/SCons/Tool/jar.py | 2 +- src/engine/SCons/Tool/javac.py | 4 +- src/engine/SCons/Tool/javah.py | 6 +- src/engine/SCons/Tool/msvs.py | 6 +- src/engine/SCons/Tool/qt.py | 5 +- src/engine/SCons/Tool/rmic.py | 6 +- src/engine/SCons/Tool/tar.py | 2 +- src/engine/SCons/Tool/zip.py | 2 +- 33 files changed, 546 insertions(+), 481 deletions(-) diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index 7069ef0..ec78d89 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -342,7 +342,7 @@ def _init_nodes(builder, env, overrides, executor_kw, tlist, slist): # Now set up the relevant information in the target Nodes themselves. for t in tlist: - t.cwd = SCons.Node.FS.default_fs.getcwd() + t.cwd = env.fs.getcwd() t.builder_set(builder) t.env_set(env) t.add_source(slist) @@ -390,8 +390,8 @@ class BuilderBase: prefix = '', suffix = '', src_suffix = '', - target_factory = SCons.Node.FS.default_fs.File, - source_factory = SCons.Node.FS.default_fs.File, + target_factory = None, + source_factory = None, target_scanner = None, source_scanner = None, emitter = None, @@ -498,8 +498,11 @@ class BuilderBase: src_suf = self.get_src_suffix(env) + target_factory = env.get_factory(self.target_factory) + source_factory = env.get_factory(self.source_factory) + source = _adjustixes(source, None, src_suf) - slist = env.arg2nodes(source, self.source_factory) + slist = env.arg2nodes(source, source_factory) pre = self.get_prefix(env, slist) suf = self.get_suffix(env, slist) @@ -516,7 +519,7 @@ class BuilderBase: tlist = [ t_from_s(pre, suf, splitext) ] else: target = _adjustixes(target, pre, suf) - tlist = env.arg2nodes(target, self.target_factory) + tlist = env.arg2nodes(target, target_factory) if self.emitter: # The emitter is going to do str(node), but because we're @@ -543,8 +546,8 @@ class BuilderBase: # Have to call arg2nodes yet again, since it is legal for # emitters to spit out strings as well as Node instances. - slist = env.arg2nodes(source, self.source_factory) - tlist = env.arg2nodes(target, self.target_factory) + slist = env.arg2nodes(source, source_factory) + tlist = env.arg2nodes(target, target_factory) return tlist, slist @@ -693,8 +696,8 @@ class MultiStepBuilder(BuilderBase): prefix = '', suffix = '', src_suffix = '', - target_factory = SCons.Node.FS.default_fs.File, - source_factory = SCons.Node.FS.default_fs.File, + target_factory = None, + source_factory = None, target_scanner = None, source_scanner = None, emitter=None, @@ -723,7 +726,8 @@ class MultiStepBuilder(BuilderBase): def _execute(self, env, target, source, overwarn={}, executor_kw={}): # We now assume that target and source are lists or None. - slist = env.arg2nodes(source, self.source_factory) + source_factory = env.get_factory(self.source_factory) + slist = env.arg2nodes(source, source_factory) final_sources = [] sdict = self._get_sdict(env) diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py index 09927f1..fbf79f4 100644 --- a/src/engine/SCons/BuilderTests.py +++ b/src/engine/SCons/BuilderTests.py @@ -55,6 +55,9 @@ test = TestCmd.TestCmd(workdir = '') outfile = test.workpath('outfile') outfile2 = test.workpath('outfile2') +infile = test.workpath('infile') +test.write(infile, "infile\n") + show_string = None scons_env = SCons.Environment.Environment() @@ -72,6 +75,7 @@ class Environment: global env_arg2nodes_called env_arg2nodes_called = None self.scanner = None + self.fs = SCons.Node.FS.FS() def subst(self, s): if not SCons.Util.is_String(s): return s @@ -102,6 +106,8 @@ class Environment: a = factory(a) list.append(a) return list + def get_factory(self, factory): + return factory or self.fs.File def get_scanner(self, ext): return self.scanner def Dictionary(self): @@ -552,7 +558,7 @@ class BuilderTestCase(unittest.TestCase): suffix='.c') tgt = b8(env, target=None, source='foo_source.a') assert str(tgt[0]) == 'foo_obj.c', str(tgt[0]) - src = SCons.Node.FS.default_fs.File('foo_source.a') + src = env.fs.File('foo_source.a') tgt = b8(env, target=None, source=src) assert str(tgt[0]) == 'foo_obj.c', str(tgt[0]) @@ -674,7 +680,7 @@ class BuilderTestCase(unittest.TestCase): tgts = builder(env, source=[]) assert tgts == [], tgts - tgts = builder(env, target = [outfile, outfile2], source = 'foo') + tgts = builder(env, target = [outfile, outfile2], source = infile) for t in tgts: t.prepare() try: @@ -698,7 +704,7 @@ class BuilderTestCase(unittest.TestCase): return 1 builder = SCons.Builder.Builder(action = function3) - tgts = builder(env, target = [sub1_out, sub2_out], source = 'foo') + tgts = builder(env, target = [sub1_out, sub2_out], source = infile) for t in tgts: t.prepare() try: diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 77ce3c2..b813cf1 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -94,7 +94,7 @@ def alias_builder(env, target, source): AliasBuilder = SCons.Builder.Builder(action = alias_builder, target_factory = SCons.Node.Alias.default_ans.Alias, - source_factory = SCons.Node.FS.default_fs.Entry, + source_factory = SCons.Node.FS.Entry, multi = 1, is_explicit = None, name='AliasBuilder') @@ -250,7 +250,7 @@ class SubstitutionEnvironment: """Initialization of an underlying SubstitutionEnvironment class. """ if __debug__: logInstanceCreation(self, 'Environment.SubstitutionEnvironment') - self.fs = SCons.Node.FS.default_fs + self.fs = SCons.Node.FS.default_fs or SCons.Node.FS.FS() self.ans = SCons.Node.Alias.default_ans self.lookup_list = SCons.Node.arg2nodes_lookups self._dict = kw.copy() @@ -483,7 +483,7 @@ class Base(SubstitutionEnvironment): with the much simpler base class initialization. """ if __debug__: logInstanceCreation(self, 'Environment.Base') - self.fs = SCons.Node.FS.default_fs + self.fs = SCons.Node.FS.default_fs or SCons.Node.FS.FS() self.ans = SCons.Node.Alias.default_ans self.lookup_list = SCons.Node.arg2nodes_lookups self._dict = our_deepcopy(SCons.Defaults.ConstructionEnvironment) @@ -529,6 +529,14 @@ class Base(SubstitutionEnvironment): # These begin with lower-case letters. ####################################################################### + def get_builder(self, name): + """Fetch the builder with the specified name from the environment. + """ + try: + return self._dict['BUILDERS'][name] + except KeyError: + return None + def get_calculator(self): "__cacheable__" try: @@ -541,13 +549,35 @@ class Base(SubstitutionEnvironment): c = SCons.Defaults.DefaultEnvironment().get_calculator() return c - def get_builder(self, name): - """Fetch the builder with the specified name from the environment. + def get_factory(self, factory, default='File'): + """Return a factory function for creating Nodes for this + construction environment. + __cacheable__ """ + name = default try: - return self._dict['BUILDERS'][name] - except KeyError: - return None + is_node = issubclass(factory, SCons.Node.Node) + except TypeError: + # The specified factory isn't a Node itself--it's + # most likely None, or possibly a callable. + pass + else: + if is_node: + # The specified factory is a Node (sub)class. Try to + # return the FS method that corresponds to the Node's + # name--that is, we return self.fs.Dir if they want a Dir, + # self.fs.File for a File, etc. + try: name = factory.__name__ + except AttributeError: pass + else: factory = None + if not factory: + # They passed us None, or we picked up a name from a specified + # class, so return the FS method. (Note that we *don't* + # use our own self.{Dir,File} methods because that would + # cause env.subst() to be called twice on the file name, + # interfering with files that have $$ in them.) + factory = getattr(self.fs, name) + return factory def _gsm(self): "__cacheable__" diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index a508529..6b4bc60 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -794,128 +794,81 @@ class BaseTestCase(unittest.TestCase): def test_autogenerate(dict): """Test autogenerating variables in a dictionary.""" - def RDirs(pathlist): - return SCons.Node.FS.default_fs.Rsearchall(pathlist, - clazz=SCons.Node.FS.Dir, - must_exist=0, - cwd=SCons.Node.FS.default_fs.Dir('xx')) - env = Environment(LIBS = [ 'foo', 'bar', 'baz' ], LIBLINKPREFIX = 'foo', - LIBLINKSUFFIX = 'bar', - RDirs=RDirs) + LIBLINKSUFFIX = 'bar') + + def RDirs(pathlist, fs=env.fs): + return fs.Rsearchall(pathlist, + clazz=SCons.Node.FS.Dir, + must_exist=0, + cwd=fs.Dir('xx')) + + env['RDirs'] = RDirs flags = env.subst_list('$_LIBFLAGS', 1)[0] - assert len(flags) == 3, flags - assert flags[0] == 'foobar', \ - flags[0] - assert flags[1] == 'foobar', \ - flags[1] - assert flags[2] == 'foobazbar', \ - flags[2] - - blat = SCons.Node.FS.default_fs.Dir('blat') - - env = Environment(CPPPATH = [ 'foo', '$FOO/bar', blat ], - INCPREFIX = 'foo ', - INCSUFFIX = 'bar', - FOO = 'baz', - RDirs=RDirs) + assert flags == ['foobar', 'foobar', 'foobazbar'], flags + + blat = env.fs.Dir('blat') + + env.Replace(CPPPATH = [ 'foo', '$FOO/bar', blat ], + INCPREFIX = 'foo ', + INCSUFFIX = 'bar', + FOO = 'baz') flags = env.subst_list('$_CPPINCFLAGS', 1)[0] - assert len(flags) == 8, flags - assert flags[0] == '$(', \ - flags[0] - assert flags[1] == os.path.normpath('foo'), \ - flags[1] - assert flags[2] == os.path.normpath('xx/foobar'), \ - flags[2] - assert flags[3] == os.path.normpath('foo'), \ - flags[3] - assert flags[4] == os.path.normpath('xx/baz/bar'), \ - flags[4] - assert flags[5] == os.path.normpath('foo'), \ - flags[5] - assert flags[6] == os.path.normpath('blatbar'), \ - flags[6] - assert flags[7] == '$)', \ - flags[7] - - env = Environment(F77PATH = [ 'foo', '$FOO/bar', blat ], - INCPREFIX = 'foo ', - INCSUFFIX = 'bar', - FOO = 'baz', - RDirs=RDirs) + expect = [ '$(', + os.path.normpath('foo'), + os.path.normpath('xx/foobar'), + os.path.normpath('foo'), + os.path.normpath('xx/baz/bar'), + os.path.normpath('foo'), + os.path.normpath('blatbar'), + '$)', + ] + assert flags == expect, flags + + env.Replace(F77PATH = [ 'foo', '$FOO/bar', blat ], + INCPREFIX = 'foo ', + INCSUFFIX = 'bar', + FOO = 'baz') flags = env.subst_list('$_F77INCFLAGS', 1)[0] - assert len(flags) == 8, flags - assert flags[0] == '$(', \ - flags[0] - assert flags[1] == os.path.normpath('foo'), \ - flags[1] - assert flags[2] == os.path.normpath('xx/foobar'), \ - flags[2] - assert flags[3] == os.path.normpath('foo'), \ - flags[3] - assert flags[4] == os.path.normpath('xx/baz/bar'), \ - flags[4] - assert flags[5] == os.path.normpath('foo'), \ - flags[5] - assert flags[6] == os.path.normpath('blatbar'), \ - flags[6] - assert flags[7] == '$)', \ - flags[7] - - env = Environment(CPPPATH = '', F77PATH = '', LIBPATH = '', - RDirs=RDirs) + expect = [ '$(', + os.path.normpath('foo'), + os.path.normpath('xx/foobar'), + os.path.normpath('foo'), + os.path.normpath('xx/baz/bar'), + os.path.normpath('foo'), + os.path.normpath('blatbar'), + '$)', + ] + assert flags == expect, flags + + env.Replace(CPPPATH = '', F77PATH = '', LIBPATH = '') l = env.subst_list('$_CPPINCFLAGS') - assert len(l[0]) == 0, l[0] + assert l == [[]], l l = env.subst_list('$_F77INCFLAGS') - assert len(l[0]) == 0, l[0] + assert l == [[]], l l = env.subst_list('$_LIBDIRFLAGS') - assert len(l[0]) == 0, l[0] - - SCons.Node.FS.default_fs.Repository('/rep1') - SCons.Node.FS.default_fs.Repository('/rep2') - env = Environment(CPPPATH = [ 'foo', '/a/b', '$FOO/bar', blat], - INCPREFIX = '-I ', - INCSUFFIX = 'XXX', - FOO = 'baz', - RDirs=RDirs) + assert l == [[]], l + + env.fs.Repository('/rep1') + env.fs.Repository('/rep2') + env.Replace(CPPPATH = [ 'foo', '/a/b', '$FOO/bar', blat], + INCPREFIX = '-I ', + INCSUFFIX = 'XXX', + FOO = 'baz') flags = env.subst_list('$_CPPINCFLAGS', 1)[0] - assert flags[0] == '$(', \ - flags[0] - assert flags[1] == '-I', \ - flags[1] - assert flags[2] == os.path.normpath('xx/fooXXX'), \ - flags[2] - assert flags[3] == '-I', \ - flags[3] - assert flags[4] == os.path.normpath('/rep1/xx/fooXXX'), \ - flags[4] - assert flags[5] == '-I', \ - flags[5] - assert flags[6] == os.path.normpath('/rep2/xx/fooXXX'), \ - flags[6] - assert flags[7] == '-I', \ - flags[7] - assert flags[8] == os.path.normpath('/a/bXXX'), \ - flags[8] - assert flags[9] == '-I', \ - flags[9] - assert flags[10] == os.path.normpath('xx/baz/barXXX'), \ - flags[10] - assert flags[11] == '-I', \ - flags[11] - assert flags[12] == os.path.normpath('/rep1/xx/baz/barXXX'), \ - flags[12] - assert flags[13] == '-I', \ - flags[13] - assert flags[14] == os.path.normpath('/rep2/xx/baz/barXXX'), \ - flags[14] - assert flags[15] == '-I', \ - flags[15] - assert flags[16] == os.path.normpath('blatXXX'), \ - flags[16] - assert flags[17] == '$)', \ - flags[17] + expect = [ '$(', + '-I', os.path.normpath('xx/fooXXX'), + '-I', os.path.normpath('/rep1/xx/fooXXX'), + '-I', os.path.normpath('/rep2/xx/fooXXX'), + '-I', os.path.normpath('/a/bXXX'), + '-I', os.path.normpath('xx/baz/barXXX'), + '-I', os.path.normpath('/rep1/xx/baz/barXXX'), + '-I', os.path.normpath('/rep2/xx/baz/barXXX'), + '-I', os.path.normpath('blatXXX'), + '$)' + ] + assert flags == expect, flags def test_platform(self): """Test specifying a platform callable when instantiating.""" @@ -2189,7 +2142,7 @@ def generate(env): assert 'foo1.in' in map(lambda x: x.path, t.sources) assert 'foo2.in' in map(lambda x: x.path, t.sources) - sub = SCons.Node.FS.default_fs.Dir('sub') + sub = env.fs.Dir('sub') t = env.Command(target='bar.out', source='sub', action='buildbar $target $source')[0] assert 'sub' in map(lambda x: x.path, t.sources) diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index fe014f8..90bc70a 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -5,9 +5,8 @@ File system nodes. These Nodes represent the canonical external objects that people think of when they think of building software: files and directories. -This initializes a "default_fs" Node with an FS at the current directory -for its own purposes, and for use by scripts or modules looking for the -canonical default. +This holds a "default_fs" variable that should be initialized with an FS +that can be used by scripts or modules looking for the canonical default. """ @@ -759,20 +758,20 @@ class FS(LocalFS): The path argument must be a valid absolute path. """ if __debug__: logInstanceCreation(self, 'Node.FS') - self.Top = None - if path == None: - self.pathTop = os.getcwd() - else: - self.pathTop = path self.Root = {} self.SConstruct_dir = None self.CachePath = None self.cache_force = None self.cache_show = None - def set_toplevel_dir(self, path): - assert not self.Top, "You can only set the top-level path on an FS object that has not had its File, Dir, or Entry methods called yet." - self.pathTop = path + if path is None: + self.pathTop = os.getcwd() + else: + self.pathTop = path + + self.Top = self._doLookup(Dir, os.path.normpath(self.pathTop)) + self.Top.path = '.' + self._cwd = self.Top def clear_cache(self): "__cache_reset__" @@ -780,15 +779,8 @@ class FS(LocalFS): def set_SConstruct_dir(self, dir): self.SConstruct_dir = dir - - def __setTopLevelDir(self): - if not self.Top: - self.Top = self._doLookup(Dir, os.path.normpath(self.pathTop)) - self.Top.path = '.' - self._cwd = self.Top - + def getcwd(self): - self.__setTopLevelDir() return self._cwd def __checkClass(self, node, klass): @@ -912,7 +904,6 @@ class FS(LocalFS): If directory is None, and name is a relative path, then the same applies. """ - self.__setTopLevelDir() if name and name[0] == '#': directory = self.Top name = name[1:] @@ -930,7 +921,6 @@ class FS(LocalFS): If change_os_dir is true, we will also change the "real" cwd to match. """ - self.__setTopLevelDir() curr=self._cwd try: if not dir is None: @@ -990,7 +980,6 @@ class FS(LocalFS): """Link the supplied build directory to the source directory for purposes of building files.""" - self.__setTopLevelDir() if not isinstance(src_dir, SCons.Node.Node): src_dir = self.Dir(src_dir) if not isinstance(build_dir, SCons.Node.Node): @@ -1010,7 +999,6 @@ class FS(LocalFS): for d in dirs: if not isinstance(d, SCons.Node.Node): d = self.Dir(d) - self.__setTopLevelDir() self.Top.addRepository(d) def do_Rsearch(self, path, dir, func, clazz=_classEntry): @@ -1150,7 +1138,6 @@ class FS(LocalFS): message = fmt % string.join(map(str, targets)) return targets, message - class Dir(Base): """A class for directories in a file system. """ @@ -1914,7 +1901,7 @@ class File(Base): File, this is a TypeError...""" raise TypeError, "Tried to lookup File '%s' as a Dir." % self.path -default_fs = FS() +default_fs = None def find_file(filename, paths, verbose=None): """ diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 94e9790..e2c787e 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -972,7 +972,7 @@ class FSTestCase(_tempdirTestCase): # the reading of files in text mode. This tests that # get_contents() returns the binary contents. test.write("binary_file", "Foo\x1aBar") - f1 = SCons.Node.FS.default_fs.File(test.workpath("binary_file")) + f1 = fs.File(test.workpath("binary_file")) assert f1.get_contents() == "Foo\x1aBar", f1.get_contents() def nonexistent(method, s): diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index 5f03377..67ac05f 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -141,6 +141,8 @@ class Environment: self._dict.update(dict) def get_calculator(self): return SCons.Sig.default_calc + def get_factory(self, factory): + return factory or MyNode def get_scanner(self, scanner_key): return self._dict['SCANNERS'][0] diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index db80985..bc10e21 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -424,7 +424,8 @@ class Node: here is a significant performance boost. __cacheable__ """ - return self.builder.source_factory(path) + env = self.get_build_env() + return env.get_factory(self.builder.source_factory)(path) def get_scanner(self, env, kw={}): return env.get_scanner(self.scanner_key()) diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index 7bd9c1a..b89ca4a 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -76,7 +76,7 @@ def SetProgressDisplay(display): global progress_display progress_display = display -SConfFS=SCons.Node.FS.default_fs +SConfFS = None _ac_build_counter = 0 # incremented, whenever TryBuild is called _ac_config_logs = {} # all config.log files created in this build @@ -338,7 +338,8 @@ class SConf: """ global SConfFS if not SConfFS: - SConfFS = SCons.Node.FS.FS(SCons.Node.FS.default_fs.pathTop) + SConfFS = SCons.Node.FS.default_fs or \ + SCons.Node.FS.FS(env.fs.pathTop) if not sconf_global is None: raise (SCons.Errors.UserError, "Only one SConf object may be active at one time") diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py index 62a6842..276570e 100644 --- a/src/engine/SCons/Scanner/C.py +++ b/src/engine/SCons/Scanner/C.py @@ -32,12 +32,11 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Node.FS import SCons.Scanner -def CScanner(fs = SCons.Node.FS.default_fs): +def CScanner(): """Return a prototype Scanner instance for scanning source files that use the C pre-processor""" cs = SCons.Scanner.ClassicCPP("CScanner", "$CPPSUFFIXES", "CPPPATH", - '^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")', - fs = fs) + '^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")') return cs diff --git a/src/engine/SCons/Scanner/CTests.py b/src/engine/SCons/Scanner/CTests.py index fd17ee1..138b788 100644 --- a/src/engine/SCons/Scanner/CTests.py +++ b/src/engine/SCons/Scanner/CTests.py @@ -174,6 +174,7 @@ class DummyEnvironment(UserDict.UserDict): def __init__(self, **kw): UserDict.UserDict.__init__(self) self.data.update(kw) + self.fs = SCons.Node.FS.FS(test.workpath('')) def Dictionary(self, *args): return self.data @@ -196,6 +197,15 @@ class DummyEnvironment(UserDict.UserDict): def get_calculator(self): return None + def get_factory(self, factory): + return factory or self.fs.File + + def Dir(self, filename): + return self.fs.Dir(test.workpath(filename)) + + def File(self, filename): + return self.fs.File(test.workpath(filename)) + if os.path.normcase('foo') == os.path.normcase('FOO'): my_normpath = os.path.normcase else: @@ -207,9 +217,6 @@ def deps_match(self, deps, headers): expect = map(my_normpath, headers) self.failUnless(scanned == expect, "expect %s != scanned %s" % (expect, scanned)) -def make_node(filename, fs=SCons.Node.FS.default_fs): - return fs.File(test.workpath(filename)) - # define some tests: class CScannerTestCase1(unittest.TestCase): @@ -217,36 +224,36 @@ class CScannerTestCase1(unittest.TestCase): env = DummyEnvironment(CPPPATH=[]) s = SCons.Scanner.C.CScanner() path = s.path(env) - deps = s(make_node('f1.cpp'), env, path) + deps = s(env.File('f1.cpp'), env, path) headers = ['f1.h', 'f2.h'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) class CScannerTestCase2(unittest.TestCase): def runTest(self): env = DummyEnvironment(CPPPATH=[test.workpath("d1")]) s = SCons.Scanner.C.CScanner() path = s.path(env) - deps = s(make_node('f1.cpp'), env, path) + deps = s(env.File('f1.cpp'), env, path) headers = ['f1.h', 'd1/f2.h'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) class CScannerTestCase3(unittest.TestCase): def runTest(self): env = DummyEnvironment(CPPPATH=[test.workpath("d1")]) s = SCons.Scanner.C.CScanner() path = s.path(env) - deps = s(make_node('f2.cpp'), env, path) + deps = s(env.File('f2.cpp'), env, path) headers = ['d1/f1.h', 'f1.h', 'd1/d2/f1.h'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) class CScannerTestCase4(unittest.TestCase): def runTest(self): env = DummyEnvironment(CPPPATH=[test.workpath("d1"), test.workpath("d1/d2")]) s = SCons.Scanner.C.CScanner() path = s.path(env) - deps = s(make_node('f2.cpp'), env, path) + deps = s(env.File('f2.cpp'), env, path) headers = ['d1/f1.h', 'f1.h', 'd1/d2/f1.h', 'd1/d2/f4.h'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) class CScannerTestCase5(unittest.TestCase): def runTest(self): @@ -254,7 +261,7 @@ class CScannerTestCase5(unittest.TestCase): s = SCons.Scanner.C.CScanner() path = s.path(env) - n = make_node('f3.cpp') + n = env.File('f3.cpp') def my_rexists(s=n): s.rexists_called = 1 return s.old_rexists() @@ -269,7 +276,7 @@ class CScannerTestCase5(unittest.TestCase): headers = ['f1.h', 'f2.h', 'f3-test.h', 'd1/f1.h', 'd1/f2.h', 'd1/f3-test.h'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) class CScannerTestCase6(unittest.TestCase): def runTest(self): @@ -278,25 +285,24 @@ class CScannerTestCase6(unittest.TestCase): s = SCons.Scanner.C.CScanner() path1 = s.path(env1) path2 = s.path(env2) - deps1 = s(make_node('f1.cpp'), env1, path1) - deps2 = s(make_node('f1.cpp'), env2, path2) + deps1 = s(env1.File('f1.cpp'), env1, path1) + deps2 = s(env2.File('f1.cpp'), env2, path2) headers1 = ['f1.h', 'd1/f2.h'] headers2 = ['f1.h', 'd1/d2/f2.h'] - deps_match(self, deps1, map(test.workpath, headers1)) - deps_match(self, deps2, map(test.workpath, headers2)) + deps_match(self, deps1, headers1) + deps_match(self, deps2, headers2) class CScannerTestCase8(unittest.TestCase): def runTest(self): - fs = SCons.Node.FS.FS(test.workpath('')) env = DummyEnvironment(CPPPATH=["include"]) - s = SCons.Scanner.C.CScanner(fs = fs) + s = SCons.Scanner.C.CScanner() path = s.path(env) - deps1 = s(fs.File('fa.cpp'), env, path) - fs.chdir(fs.Dir('subdir')) - dir = fs.getcwd() - fs.chdir(fs.Dir('..')) + deps1 = s(env.File('fa.cpp'), env, path) + env.fs.chdir(env.Dir('subdir')) + dir = env.fs.getcwd() + env.fs.chdir(env.Dir('')) path = s.path(env, dir) - deps2 = s(fs.File('#fa.cpp'), env, path) + deps2 = s(env.File('#fa.cpp'), env, path) headers1 = ['include/fa.h', 'include/fb.h'] headers2 = ['subdir/include/fa.h', 'subdir/include/fb.h'] deps_match(self, deps1, headers1) @@ -315,7 +321,8 @@ class CScannerTestCase9(unittest.TestCase): test.write('fa.h','\n') fs = SCons.Node.FS.FS(test.workpath('')) env = DummyEnvironment(CPPPATH=[]) - s = SCons.Scanner.C.CScanner(fs=fs) + env.fs = fs + s = SCons.Scanner.C.CScanner() path = s.path(env) deps = s(fs.File('fa.cpp'), env, path) @@ -330,7 +337,8 @@ class CScannerTestCase10(unittest.TestCase): fs = SCons.Node.FS.FS(test.workpath('')) fs.chdir(fs.Dir('include')) env = DummyEnvironment(CPPPATH=[]) - s = SCons.Scanner.C.CScanner(fs=fs) + env.fs = fs + s = SCons.Scanner.C.CScanner() path = s.path(env) test.write('include/fa.cpp', test.read('fa.cpp')) fs.chdir(fs.Dir('..')) @@ -349,10 +357,12 @@ class CScannerTestCase11(unittest.TestCase): f1=fs.File('include2/jjj.h') f1.builder=1 env = DummyEnvironment(CPPPATH=['include', 'include2']) - s = SCons.Scanner.C.CScanner(fs=fs) + env.fs = fs + s = SCons.Scanner.C.CScanner() path = s.path(env) deps = s(fs.File('src/fff.c'), env, path) - deps_match(self, deps, [ test.workpath('repository/include/iii.h'), 'include2/jjj.h' ]) + deps_match(self, deps, [ test.workpath('repository/include/iii.h'), + 'include2/jjj.h' ]) os.chdir(test.workpath('')) class CScannerTestCase12(unittest.TestCase): @@ -363,7 +373,8 @@ class CScannerTestCase12(unittest.TestCase): fs.BuildDir('build2', 'src', 0) fs.Repository(test.workpath('repository')) env = DummyEnvironment(CPPPATH=[]) - s = SCons.Scanner.C.CScanner(fs = fs) + env.fs = fs + s = SCons.Scanner.C.CScanner() path = s.path(env) deps1 = s(fs.File('build1/aaa.c'), env, path) deps_match(self, deps1, [ 'build1/bbb.h' ]) @@ -383,18 +394,18 @@ class CScannerTestCase13(unittest.TestCase): env = SubstEnvironment(CPPPATH=["blah"]) s = SCons.Scanner.C.CScanner() path = s.path(env) - deps = s(make_node('f1.cpp'), env, path) + deps = s(env.File('f1.cpp'), env, path) headers = ['f1.h', 'd1/f2.h'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) class CScannerTestCase14(unittest.TestCase): def runTest(self): env = DummyEnvironment(CPPPATH=[]) s = SCons.Scanner.C.CScanner() path = s.path(env) - deps = s(make_node('f5.c'), env, path) + deps = s(env.File('f5.c'), env, path) headers = ['f5a.h', 'f5b.h'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) class CScannerTestCase15(unittest.TestCase): def runTest(self): diff --git a/src/engine/SCons/Scanner/D.py b/src/engine/SCons/Scanner/D.py index cd93a69..2ea2614 100644 --- a/src/engine/SCons/Scanner/D.py +++ b/src/engine/SCons/Scanner/D.py @@ -36,13 +36,12 @@ import string import SCons.Scanner -def DScanner(fs = SCons.Node.FS.default_fs): +def DScanner(): """Return a prototype Scanner instance for scanning D source files""" ds = D(name = "DScanner", suffixes = '$DSUFFIXES', path_variable = 'DPATH', - regex = 'import\s+([^\;]*)\;', - fs = fs) + regex = 'import\s+([^\;]*)\;') return ds class D(SCons.Scanner.Classic): diff --git a/src/engine/SCons/Scanner/Dir.py b/src/engine/SCons/Scanner/Dir.py index 6161059..ae20749 100644 --- a/src/engine/SCons/Scanner/Dir.py +++ b/src/engine/SCons/Scanner/Dir.py @@ -28,14 +28,16 @@ import string import SCons.Node.FS import SCons.Scanner -def DirScanner(fs = SCons.Node.FS.default_fs, **kw): +def DirScanner(**kw): """Return a prototype Scanner instance for scanning directories for on-disk files""" - def only_dirs(nodes, fs=fs): - return filter(lambda n: isinstance(n.disambiguate(), SCons.Node.FS.Dir), nodes) - kw['node_factory'] = fs.Entry + def only_dirs(nodes): + return filter(lambda n: isinstance(n.disambiguate(), + SCons.Node.FS.Dir), + nodes) + kw['node_factory'] = SCons.Node.FS.Entry kw['recursive'] = only_dirs - ds = apply(SCons.Scanner.Base, [scan, "DirScanner"], kw) + ds = apply(SCons.Scanner.Base, (scan, "DirScanner"), kw) return ds skip_entry = { diff --git a/src/engine/SCons/Scanner/DirTests.py b/src/engine/SCons/Scanner/DirTests.py index e735ca2..257e76b 100644 --- a/src/engine/SCons/Scanner/DirTests.py +++ b/src/engine/SCons/Scanner/DirTests.py @@ -47,24 +47,35 @@ test.write(['dir', 'sub', '.sconsign'], "dir/.sconsign\n") test.write(['dir', 'sub', '.sconsign.dblite'], "dir/.sconsign.dblite\n") class DummyNode: - def __init__(self, name): + def __init__(self, name, fs): self.name = name self.abspath = test.workpath(name) - self.fs = SCons.Node.FS.default_fs + self.fs = fs def __str__(self): return self.name def Entry(self, name): return self.fs.Entry(name) +class DummyEnvironment: + def __init__(self): + self.fs = SCons.Node.FS.FS() + def Entry(self, name): + node = DummyNode(name, self.fs) + return node + def get_factory(self, factory): + return factory or self.fs.Entry + class DirScannerTestCase1(unittest.TestCase): def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Dir.DirScanner() - deps = s(DummyNode('dir'), {}, ()) + deps = s(env.Entry('dir'), env, ()) sss = map(str, deps) assert sss == ['f1', 'f2', 'sub'], sss - deps = s(DummyNode('dir/sub'), {}, ()) + deps = s(env.Entry('dir/sub'), env, ()) sss = map(str, deps) assert sss == ['f3', 'f4'], sss diff --git a/src/engine/SCons/Scanner/Fortran.py b/src/engine/SCons/Scanner/Fortran.py index 4da0914..66bec0c 100644 --- a/src/engine/SCons/Scanner/Fortran.py +++ b/src/engine/SCons/Scanner/Fortran.py @@ -55,13 +55,12 @@ class F90Scanner(SCons.Scanner.Classic): """ def __init__(self, name, suffixes, path_variable, use_regex, - incl_regex, fs=SCons.Node.FS.default_fs, *args, **kw): + incl_regex, *args, **kw): self.cre_use = re.compile(use_regex, re.M) self.cre_incl = re.compile(incl_regex, re.M) - self.fs = fs - def _scan(node, env, path, self=self, fs=fs): + def _scan(node, env, path, self=self): node = node.rfile() if not node.exists(): @@ -70,7 +69,7 @@ class F90Scanner(SCons.Scanner.Classic): return self.scan(node, env, path) kw['function'] = _scan - kw['path_function'] = SCons.Scanner.FindPathDirs(path_variable, fs) + kw['path_function'] = SCons.Scanner.FindPathDirs(path_variable) kw['recursive'] = 1 kw['skeys'] = suffixes kw['name'] = name @@ -117,7 +116,7 @@ class F90Scanner(SCons.Scanner.Classic): nodes = map(lambda pair: pair[1], nodes) return nodes -def FortranScan(path_variable="FORTRANPATH", fs=SCons.Node.FS.default_fs): +def FortranScan(path_variable="FORTRANPATH"): """Return a prototype Scanner instance for scanning source files for Fortran USE & INCLUDE statements""" @@ -275,6 +274,5 @@ def FortranScan(path_variable="FORTRANPATH", fs=SCons.Node.FS.default_fs): "$FORTRANSUFFIXES", path_variable, use_regex, - include_regex, - fs = fs) + include_regex) return scanner diff --git a/src/engine/SCons/Scanner/FortranTests.py b/src/engine/SCons/Scanner/FortranTests.py index 4c82522..141f375 100644 --- a/src/engine/SCons/Scanner/FortranTests.py +++ b/src/engine/SCons/Scanner/FortranTests.py @@ -210,6 +210,7 @@ test.write(['modules', 'use.mod'], "\n") class DummyEnvironment: def __init__(self, listCppPath): self.path = listCppPath + self.fs = SCons.Node.FS.FS(test.workpath('')) def Dictionary(self, *args): if not args: @@ -244,14 +245,20 @@ class DummyEnvironment: def get_calculator(self): return None + def get_factory(self, factory): + return factory or self.fs.File + + def Dir(self, filename): + return self.fs.Dir(test.workpath(filename)) + + def File(self, filename): + return self.fs.File(test.workpath(filename)) + def deps_match(self, deps, headers): scanned = map(os.path.normpath, map(str, deps)) expect = map(os.path.normpath, headers) self.failUnless(scanned == expect, "expect %s != scanned %s" % (expect, scanned)) -def make_node(filename, fs=SCons.Node.FS.default_fs): - return fs.File(test.workpath(filename)) - # define some tests: class FortranScannerTestCase1(unittest.TestCase): @@ -261,10 +268,9 @@ class FortranScannerTestCase1(unittest.TestCase): env = DummyEnvironment([]) s = SCons.Scanner.Fortran.FortranScan() path = s.path(env) - fs = SCons.Node.FS.FS(original) - deps = s(make_node('fff1.f', fs), env, path) + deps = s(env.File('fff1.f'), env, path) headers = ['f1.f', 'f2.f'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) test.unlink('f1.f') test.unlink('f2.f') @@ -275,10 +281,9 @@ class FortranScannerTestCase2(unittest.TestCase): env = DummyEnvironment([test.workpath("d1")]) s = SCons.Scanner.Fortran.FortranScan() path = s.path(env) - fs = SCons.Node.FS.FS(original) - deps = s(make_node('fff1.f', fs), env, path) + deps = s(env.File('fff1.f'), env, path) headers = ['f1.f', 'f2.f'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) test.unlink('f1.f') test.unlink('f2.f') @@ -287,10 +292,9 @@ class FortranScannerTestCase3(unittest.TestCase): env = DummyEnvironment([test.workpath("d1")]) s = SCons.Scanner.Fortran.FortranScan() path = s.path(env) - fs = SCons.Node.FS.FS(original) - deps = s(make_node('fff1.f', fs), env, path) + deps = s(env.File('fff1.f'), env, path) headers = ['d1/f1.f', 'd1/f2.f'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) class FortranScannerTestCase4(unittest.TestCase): def runTest(self): @@ -298,10 +302,9 @@ class FortranScannerTestCase4(unittest.TestCase): env = DummyEnvironment([test.workpath("d1")]) s = SCons.Scanner.Fortran.FortranScan() path = s.path(env) - fs = SCons.Node.FS.FS(original) - deps = s(make_node('fff1.f', fs), env, path) + deps = s(env.File('fff1.f'), env, path) headers = ['d1/f1.f', 'd1/f2.f'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) test.write(['d1', 'f2.f'], "\n") class FortranScannerTestCase5(unittest.TestCase): @@ -309,10 +312,9 @@ class FortranScannerTestCase5(unittest.TestCase): env = DummyEnvironment([test.workpath("d1")]) s = SCons.Scanner.Fortran.FortranScan() path = s.path(env) - fs = SCons.Node.FS.FS(original) - deps = s(make_node('fff2.f', fs), env, path) + deps = s(env.File('fff2.f'), env, path) headers = ['d1/f2.f', 'd1/d2/f2.f', 'd1/f2.f'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) class FortranScannerTestCase6(unittest.TestCase): def runTest(self): @@ -320,10 +322,9 @@ class FortranScannerTestCase6(unittest.TestCase): env = DummyEnvironment([test.workpath("d1")]) s = SCons.Scanner.Fortran.FortranScan() path = s.path(env) - fs = SCons.Node.FS.FS(original) - deps = s(make_node('fff2.f', fs), env, path) + deps = s(env.File('fff2.f'), env, path) headers = ['d1/f2.f', 'd1/d2/f2.f', 'f2.f'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) test.unlink('f2.f') class FortranScannerTestCase7(unittest.TestCase): @@ -331,10 +332,9 @@ class FortranScannerTestCase7(unittest.TestCase): env = DummyEnvironment([test.workpath("d1/d2"), test.workpath("d1")]) s = SCons.Scanner.Fortran.FortranScan() path = s.path(env) - fs = SCons.Node.FS.FS(original) - deps = s(make_node('fff2.f', fs), env, path) + deps = s(env.File('fff2.f'), env, path) headers = ['d1/f2.f', 'd1/d2/f2.f', 'd1/d2/f2.f'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) class FortranScannerTestCase8(unittest.TestCase): def runTest(self): @@ -342,10 +342,9 @@ class FortranScannerTestCase8(unittest.TestCase): env = DummyEnvironment([test.workpath("d1/d2"), test.workpath("d1")]) s = SCons.Scanner.Fortran.FortranScan() path = s.path(env) - fs = SCons.Node.FS.FS(original) - deps = s(make_node('fff2.f', fs), env, path) + deps = s(env.File('fff2.f'), env, path) headers = ['d1/f2.f', 'd1/d2/f2.f', 'f2.f'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) test.unlink('f2.f') class FortranScannerTestCase9(unittest.TestCase): @@ -355,7 +354,7 @@ class FortranScannerTestCase9(unittest.TestCase): s = SCons.Scanner.Fortran.FortranScan() path = s.path(env) - n = make_node('fff3.f') + n = env.File('fff3.f') def my_rexists(s=n): s.rexists_called = 1 return s.old_rexists() @@ -369,21 +368,20 @@ class FortranScannerTestCase9(unittest.TestCase): assert n.rexists_called headers = ['d1/f3.f', 'f3.f'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) test.unlink('f3.f') class FortranScannerTestCase10(unittest.TestCase): def runTest(self): - fs = SCons.Node.FS.FS(test.workpath('')) env = DummyEnvironment(["include"]) - s = SCons.Scanner.Fortran.FortranScan(fs = fs) + s = SCons.Scanner.Fortran.FortranScan() path = s.path(env) - deps1 = s(fs.File('fff4.f'), env, path) - fs.chdir(fs.Dir('subdir')) - dir = fs.getcwd() - fs.chdir(fs.Dir('..')) + deps1 = s(env.File('fff4.f'), env, path) + env.fs.chdir(env.Dir('subdir')) + dir = env.fs.getcwd() + env.fs.chdir(env.Dir('')) path = s.path(env, dir) - deps2 = s(fs.File('#fff4.f'), env, path) + deps2 = s(env.File('#fff4.f'), env, path) headers1 = ['include/f4.f'] headers2 = ['subdir/include/f4.f'] deps_match(self, deps1, headers1) @@ -399,11 +397,10 @@ class FortranScannerTestCase11(unittest.TestCase): to = TestOut() to.out = None SCons.Warnings._warningOut = to - fs = SCons.Node.FS.FS(test.workpath('')) env = DummyEnvironment([]) - s = SCons.Scanner.Fortran.FortranScan(fs=fs) + s = SCons.Scanner.Fortran.FortranScan() path = s.path(env) - deps = s(fs.File('fff5.f'), env, path) + deps = s(env.File('fff5.f'), env, path) # Did we catch the warning from not finding not_there.f? assert to.out @@ -412,14 +409,13 @@ class FortranScannerTestCase11(unittest.TestCase): class FortranScannerTestCase12(unittest.TestCase): def runTest(self): - fs = SCons.Node.FS.FS(test.workpath('')) - fs.chdir(fs.Dir('include')) env = DummyEnvironment([]) - s = SCons.Scanner.Fortran.FortranScan(fs=fs) + env.fs.chdir(env.Dir('include')) + s = SCons.Scanner.Fortran.FortranScan() path = s.path(env) test.write('include/fff4.f', test.read('fff4.f')) - deps = s(fs.File('#include/fff4.f'), env, path) - fs.chdir(fs.Dir('..')) + deps = s(env.File('#include/fff4.f'), env, path) + env.fs.chdir(env.Dir('')) deps_match(self, deps, ['include/f4.f']) test.unlink('include/fff4.f') @@ -434,7 +430,8 @@ class FortranScannerTestCase13(unittest.TestCase): f1=fs.File('include2/jjj.f') f1.builder=1 env = DummyEnvironment(['include','include2']) - s = SCons.Scanner.Fortran.FortranScan(fs=fs) + env.fs = fs + s = SCons.Scanner.Fortran.FortranScan() path = s.path(env) deps = s(fs.File('src/fff.f'), env, path) deps_match(self, deps, [test.workpath('repository/include/iii.f'), 'include2/jjj.f']) @@ -448,7 +445,8 @@ class FortranScannerTestCase14(unittest.TestCase): fs.BuildDir('build2', 'src', 0) fs.Repository(test.workpath('repository')) env = DummyEnvironment([]) - s = SCons.Scanner.Fortran.FortranScan(fs = fs) + env.fs = fs + s = SCons.Scanner.Fortran.FortranScan() path = s.path(env) deps1 = s(fs.File('build1/aaa.f'), env, path) deps_match(self, deps1, [ 'build1/bbb.f' ]) @@ -469,10 +467,9 @@ class FortranScannerTestCase15(unittest.TestCase): env = SubstEnvironment(["junk"]) s = SCons.Scanner.Fortran.FortranScan() path = s.path(env) - fs = SCons.Node.FS.FS(original) - deps = s(make_node('fff1.f', fs), env, path) + deps = s(env.File('fff1.f'), env, path) headers = ['d1/f1.f', 'd1/f2.f'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) test.write(['d1', 'f2.f'], "\n") class FortranScannerTestCase16(unittest.TestCase): @@ -490,8 +487,7 @@ class FortranScannerTestCase16(unittest.TestCase): env = DummyEnvironment([test.workpath('modules')]) s = SCons.Scanner.Fortran.FortranScan() path = s.path(env) - fs = SCons.Node.FS.FS(original) - deps = s(make_node('fff90a.f90', fs), env, path) + deps = s(env.File('fff90a.f90'), env, path) headers = ['f1.f', 'f2.f', 'f3.f', 'f4.f', 'f5.f', 'f6.f', 'f7.f', 'f8.f', 'f9.f'] modules = ['mod01.mod', 'mod02.mod', 'mod03.mod', 'mod04.mod', 'mod05.mod', 'mod06.mod', 'mod07.mod', 'mod08.mod', 'mod09.mod', 'mod10.mod', @@ -499,7 +495,7 @@ class FortranScannerTestCase16(unittest.TestCase): 'mod16.mod', 'mod17.mod', 'mod18.mod', 'mod19.mod', 'mod20.mod', 'mod21.mod', 'mod22.mod', 'mod23.mod', 'mod24.mod', 'mod25.mod', 'modules/use.mod'] deps_expected = headers + modules - deps_match(self, deps, map(test.workpath, deps_expected)) + deps_match(self, deps, deps_expected) test.unlink('f1.f') test.unlink('f2.f') test.unlink('f3.f') diff --git a/src/engine/SCons/Scanner/IDL.py b/src/engine/SCons/Scanner/IDL.py index 8c4f68d..b0fd8ed 100644 --- a/src/engine/SCons/Scanner/IDL.py +++ b/src/engine/SCons/Scanner/IDL.py @@ -33,11 +33,10 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Node.FS import SCons.Scanner -def IDLScan(fs = SCons.Node.FS.default_fs): +def IDLScan(): """Return a prototype Scanner instance for scanning IDL source files""" cs = SCons.Scanner.ClassicCPP("IDLScan", "$IDLSUFFIXES", "CPPPATH", - '^[ \t]*(?:#[ \t]*include|[ \t]*import)[ \t]+(<|")([^>"]+)(>|")', - fs = fs) + '^[ \t]*(?:#[ \t]*include|[ \t]*import)[ \t]+(<|")([^>"]+)(>|")') return cs diff --git a/src/engine/SCons/Scanner/IDLTests.py b/src/engine/SCons/Scanner/IDLTests.py index db842c3..d1a0941 100644 --- a/src/engine/SCons/Scanner/IDLTests.py +++ b/src/engine/SCons/Scanner/IDLTests.py @@ -189,6 +189,7 @@ test.write([ 'repository', 'src', 'ddd.idl'], "\n") class DummyEnvironment: def __init__(self, listCppPath): self.path = listCppPath + self.fs = SCons.Node.FS.FS(test.workpath('')) def Dictionary(self, *args): if not args: @@ -221,6 +222,15 @@ class DummyEnvironment: def get_calculator(self): return None + def get_factory(self, factory): + return factory or self.fs.File + + def Dir(self, filename): + return self.fs.Dir(test.workpath(filename)) + + def File(self, filename): + return self.fs.File(test.workpath(filename)) + global my_normpath my_normpath = os.path.normpath @@ -232,9 +242,6 @@ def deps_match(self, deps, headers): expect = map(my_normpath, headers) self.failUnless(scanned == expect, "expect %s != scanned %s" % (expect, scanned)) -def make_node(filename, fs=SCons.Node.FS.default_fs): - return fs.File(test.workpath(filename)) - # define some tests: class IDLScannerTestCase1(unittest.TestCase): @@ -242,36 +249,36 @@ class IDLScannerTestCase1(unittest.TestCase): env = DummyEnvironment([]) s = SCons.Scanner.IDL.IDLScan() path = s.path(env) - deps = s(make_node('t1.idl'), env, path) + deps = s(env.File('t1.idl'), env, path) headers = ['f1.idl', 'f3.idl', 'f2.idl'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) class IDLScannerTestCase2(unittest.TestCase): def runTest(self): env = DummyEnvironment([test.workpath("d1")]) s = SCons.Scanner.IDL.IDLScan() path = s.path(env) - deps = s(make_node('t1.idl'), env, path) + deps = s(env.File('t1.idl'), env, path) headers = ['f1.idl', 'f3.idl', 'd1/f2.idl'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) class IDLScannerTestCase3(unittest.TestCase): def runTest(self): env = DummyEnvironment([test.workpath("d1")]) s = SCons.Scanner.IDL.IDLScan() path = s.path(env) - deps = s(make_node('t2.idl'), env, path) + deps = s(env.File('t2.idl'), env, path) headers = ['d1/f1.idl', 'f1.idl', 'd1/d2/f1.idl', 'f3.idl'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) class IDLScannerTestCase4(unittest.TestCase): def runTest(self): env = DummyEnvironment([test.workpath("d1"), test.workpath("d1/d2")]) s = SCons.Scanner.IDL.IDLScan() path = s.path(env) - deps = s(make_node('t2.idl'), env, path) + deps = s(env.File('t2.idl'), env, path) headers = ['d1/f1.idl', 'f1.idl', 'd1/d2/f1.idl', 'f3.idl'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) class IDLScannerTestCase5(unittest.TestCase): def runTest(self): @@ -279,7 +286,7 @@ class IDLScannerTestCase5(unittest.TestCase): s = SCons.Scanner.IDL.IDLScan() path = s.path(env) - n = make_node('t3.idl') + n = env.File('t3.idl') def my_rexists(s=n): s.rexists_called = 1 return s.old_rexists() @@ -295,7 +302,7 @@ class IDLScannerTestCase5(unittest.TestCase): headers = ['d1/f1.idl', 'd1/f2.idl', 'f1.idl', 'f2.idl', 'f3-test.idl', 'd1/f1.idl', 'd1/f2.idl', 'd1/f3-test.idl'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) class IDLScannerTestCase6(unittest.TestCase): def runTest(self): @@ -304,25 +311,24 @@ class IDLScannerTestCase6(unittest.TestCase): s = SCons.Scanner.IDL.IDLScan() path1 = s.path(env1) path2 = s.path(env2) - deps1 = s(make_node('t1.idl'), env1, path1) - deps2 = s(make_node('t1.idl'), env2, path2) + deps1 = s(env1.File('t1.idl'), env1, path1) + deps2 = s(env2.File('t1.idl'), env2, path2) headers1 = ['f1.idl', 'f3.idl', 'd1/f2.idl'] headers2 = ['f1.idl', 'f3.idl', 'd1/d2/f2.idl'] - deps_match(self, deps1, map(test.workpath, headers1)) - deps_match(self, deps2, map(test.workpath, headers2)) + deps_match(self, deps1, headers1) + deps_match(self, deps2, headers2) class IDLScannerTestCase7(unittest.TestCase): def runTest(self): - fs = SCons.Node.FS.FS(test.workpath('')) env = DummyEnvironment(["include"]) - s = SCons.Scanner.IDL.IDLScan(fs = fs) + s = SCons.Scanner.IDL.IDLScan() path = s.path(env) - deps1 = s(fs.File('t4.idl'), env, path) - fs.chdir(fs.Dir('subdir')) - dir = fs.getcwd() - fs.chdir(fs.Dir('..')) + deps1 = s(env.File('t4.idl'), env, path) + env.fs.chdir(env.Dir('subdir')) + dir = env.fs.getcwd() + env.fs.chdir(env.Dir('')) path = s.path(env, dir) - deps2 = s(fs.File('#t4.idl'), env, path) + deps2 = s(env.File('#t4.idl'), env, path) headers1 = ['include/fa.idl', 'include/fb.idl'] headers2 = ['subdir/include/fa.idl', 'subdir/include/fb.idl'] deps_match(self, deps1, headers1) @@ -339,11 +345,10 @@ class IDLScannerTestCase8(unittest.TestCase): to.out = None SCons.Warnings._warningOut = to test.write('fa.idl','\n') - fs = SCons.Node.FS.FS(test.workpath('')) env = DummyEnvironment([]) - s = SCons.Scanner.IDL.IDLScan(fs=fs) + s = SCons.Scanner.IDL.IDLScan() path = s.path(env) - deps = s(fs.File('t4.idl'), env, path) + deps = s(env.File('t4.idl'), env, path) # Did we catch the warning associated with not finding fb.idl? assert to.out @@ -353,14 +358,13 @@ class IDLScannerTestCase8(unittest.TestCase): class IDLScannerTestCase9(unittest.TestCase): def runTest(self): - fs = SCons.Node.FS.FS(test.workpath('')) - fs.chdir(fs.Dir('include')) env = DummyEnvironment([]) - s = SCons.Scanner.IDL.IDLScan(fs=fs) + env.fs.chdir(env.Dir('include')) + s = SCons.Scanner.IDL.IDLScan() path = s.path(env) test.write('include/t4.idl', test.read('t4.idl')) - deps = s(fs.File('#include/t4.idl'), env, path) - fs.chdir(fs.Dir('..')) + deps = s(env.File('#include/t4.idl'), env, path) + env.fs.chdir(env.Dir('')) deps_match(self, deps, [ 'include/fa.idl', 'include/fb.idl' ]) test.unlink('include/t4.idl') @@ -372,13 +376,15 @@ class IDLScannerTestCase10(unittest.TestCase): # Create a derived file in a directory that does not exist yet. # This was a bug at one time. - f1=fs.File('include2/jjj.idl') - f1.builder=1 env = DummyEnvironment(['include', 'include2']) - s = SCons.Scanner.IDL.IDLScan(fs=fs) + env.fs = fs + f1 = fs.File('include2/jjj.idl') + f1.builder = 1 + s = SCons.Scanner.IDL.IDLScan() path = s.path(env) deps = s(fs.File('src/fff.c'), env, path) - deps_match(self, deps, [ test.workpath('repository/include/iii.idl'), 'include2/jjj.idl' ]) + deps_match(self, deps, [ test.workpath('repository/include/iii.idl'), + 'include2/jjj.idl' ]) os.chdir(test.workpath('')) class IDLScannerTestCase11(unittest.TestCase): @@ -389,7 +395,8 @@ class IDLScannerTestCase11(unittest.TestCase): fs.BuildDir('build2', 'src', 0) fs.Repository(test.workpath('repository')) env = DummyEnvironment([]) - s = SCons.Scanner.IDL.IDLScan(fs = fs) + env.fs = fs + s = SCons.Scanner.IDL.IDLScan() path = s.path(env) deps1 = s(fs.File('build1/aaa.c'), env, path) deps_match(self, deps1, [ 'build1/bbb.idl' ]) @@ -409,9 +416,9 @@ class IDLScannerTestCase12(unittest.TestCase): env = SubstEnvironment(["blah"]) s = SCons.Scanner.IDL.IDLScan() path = s.path(env) - deps = s(make_node('t1.idl'), env, path) + deps = s(env.File('t1.idl'), env, path) headers = ['f1.idl', 'f3.idl', 'd1/f2.idl'] - deps_match(self, deps, map(test.workpath, headers)) + deps_match(self, deps, headers) def suite(): diff --git a/src/engine/SCons/Scanner/Prog.py b/src/engine/SCons/Scanner/Prog.py index 206c6de..54db9a8 100644 --- a/src/engine/SCons/Scanner/Prog.py +++ b/src/engine/SCons/Scanner/Prog.py @@ -33,14 +33,14 @@ import SCons.Util # global, set by --debug=findlibs print_find_libs = None -def ProgramScanner(fs = SCons.Node.FS.default_fs, **kw): +def ProgramScanner(**kw): """Return a prototype Scanner instance for scanning executable files for static-lib dependencies""" - kw['path_function'] = SCons.Scanner.FindPathDirs('LIBPATH', fs) + kw['path_function'] = SCons.Scanner.FindPathDirs('LIBPATH') ps = apply(SCons.Scanner.Base, [scan, "ProgramScanner"], kw) return ps -def scan(node, env, libpath = (), fs = SCons.Node.FS.default_fs): +def scan(node, env, libpath = ()): """ This scanner scans program files for static-library dependencies. It will search the LIBPATH environment variable diff --git a/src/engine/SCons/Scanner/ProgTests.py b/src/engine/SCons/Scanner/ProgTests.py index ec25f24..bac10b7 100644 --- a/src/engine/SCons/Scanner/ProgTests.py +++ b/src/engine/SCons/Scanner/ProgTests.py @@ -49,6 +49,7 @@ class DummyEnvironment: def __init__(self, **kw): self._dict = {'LIBSUFFIXES' : '.lib'} self._dict.update(kw) + self.fs = SCons.Node.FS.FS(test.workpath('')) def Dictionary(self, *args): if not args: @@ -83,6 +84,15 @@ class DummyEnvironment: path = [path] return map(self.subst, path) + def get_factory(self, factory): + return factory or self.fs.File + + def Dir(self, filename): + return self.fs.Dir(test.workpath(filename)) + + def File(self, filename): + return self.fs.File(test.workpath(filename)) + class DummyNode: def __init__(self, name): self.name = name @@ -95,9 +105,7 @@ def deps_match(deps, libs): deps=map(str, deps) deps.sort() libs.sort() - return map(os.path.normpath, deps) == \ - map(os.path.normpath, - map(test.workpath, libs)) + return map(os.path.normpath, deps) == map(os.path.normpath, libs) # define some tests: @@ -117,7 +125,7 @@ class ProgramScannerTestCase1(unittest.TestCase): deps = s(DummyNode('dummy'), env, path) assert deps_match(deps, ['l1.lib']), map(str, deps) - f1 = SCons.Node.FS.default_fs.File(test.workpath('f1')) + f1 = env.fs.File(test.workpath('f1')) env = DummyEnvironment(LIBPATH=[ test.workpath("") ], LIBS=[f1]) s = SCons.Scanner.Prog.ProgramScanner() @@ -125,7 +133,7 @@ class ProgramScannerTestCase1(unittest.TestCase): deps = s(DummyNode('dummy'), env, path) assert deps[0] is f1, deps - f2 = SCons.Node.FS.default_fs.File(test.workpath('f1')) + f2 = env.fs.File(test.workpath('f1')) env = DummyEnvironment(LIBPATH=[ test.workpath("") ], LIBS=f2) s = SCons.Scanner.Prog.ProgramScanner() diff --git a/src/engine/SCons/Scanner/ScannerTests.py b/src/engine/SCons/Scanner/ScannerTests.py index ef836bc..0d0ccec 100644 --- a/src/engine/SCons/Scanner/ScannerTests.py +++ b/src/engine/SCons/Scanner/ScannerTests.py @@ -30,10 +30,19 @@ import SCons.Sig import SCons.Scanner +class DummyFS: + def __init__(self, search_result=[]): + self.search_result = search_result + def File(self, name): + return DummyNode(name) + def Rsearchall(self, nodes, must_exist=0, clazz=None, cwd=dir): + return self.search_result + nodes + class DummyEnvironment(UserDict.UserDict): def __init__(self, dict=None, **kw): UserDict.UserDict.__init__(self, dict) self.data.update(kw) + self.fs = DummyFS() def subst(self, strSubst): if strSubst[0] == '$': return self.data[strSubst[1:]] @@ -48,6 +57,8 @@ class DummyEnvironment(UserDict.UserDict): return map(self.subst, path) def get_calculator(self): return SCons.Sig.default_calc + def get_factory(self, factory): + return factory or self.fs.File class DummyNode: def __init__(self, name): @@ -56,18 +67,15 @@ class DummyNode: return 1 def __str__(self): return self.name - + class FindPathDirsTestCase(unittest.TestCase): def test_FindPathDirs(self): """Test the FindPathDirs callable class""" - class FS: - def Rsearchall(self, nodes, must_exist=0, clazz=None, cwd=dir): - return ['xxx'] + nodes - env = DummyEnvironment(LIBPATH = [ 'foo' ]) + env.fs = DummyFS(['xxx']) - fpd = SCons.Scanner.FindPathDirs('LIBPATH', FS()) + fpd = SCons.Scanner.FindPathDirs('LIBPATH') result = fpd(env, dir) assert str(result) == "('xxx', 'foo')", result @@ -308,11 +316,12 @@ class SelectorTestCase(unittest.TestCase): s2 = SCons.Scanner.Base(s2func) selector = SCons.Scanner.Selector({'.x' : s1, '.y' : s2}) nx = self.skey_node('.x') - selector(nx, None, []) + env = DummyEnvironment() + selector(nx, env, []) assert called == ['s1func', nx], called del called[:] ny = self.skey_node('.y') - selector(ny, None, []) + selector(ny, env, []) assert called == ['s2func', ny], called def test_select(self): diff --git a/src/engine/SCons/Scanner/__init__.py b/src/engine/SCons/Scanner/__init__.py index 247eafb..504b6df 100644 --- a/src/engine/SCons/Scanner/__init__.py +++ b/src/engine/SCons/Scanner/__init__.py @@ -75,11 +75,10 @@ def Binder(path): class FindPathDirs: - """A class to bind a specific *PATH variable name and the fs object - to a function that will return all of the *path directories.""" - def __init__(self, variable, fs): + """A class to bind a specific *PATH variable name to a function that + will return all of the *path directories.""" + def __init__(self, variable): self.variable = variable - self.fs = fs def __call__(self, env, dir, target=None, source=None, argument=None): # The goal is that we've made caching this unnecessary # because the caching takes place at higher layers. @@ -89,10 +88,10 @@ class FindPathDirs: return () path = env.subst_path(path, target=target, source=source) - path_tuple = tuple(self.fs.Rsearchall(path, - must_exist = 0, #kwq! - clazz = SCons.Node.FS.Dir, - cwd = dir)) + path_tuple = tuple(env.fs.Rsearchall(path, + must_exist = 0, #kwq! + clazz = SCons.Node.FS.Dir, + cwd = dir)) return Binder(path_tuple) class Base: @@ -110,7 +109,7 @@ class Base: skeys = [], path_function = None, node_class = SCons.Node.FS.Entry, - node_factory = SCons.Node.FS.default_fs.File, + node_factory = None, scan_check = None, recursive = None): """ @@ -155,13 +154,12 @@ class Base: (the canonical example being only recursively scanning subdirectories within a directory). - The scanner function's first argument will be the a Node that - should be scanned for dependencies, the second argument will - be an Environment object, the third argument will be the tuple - of paths returned by the path_function, and the fourth - argument will be the value passed into 'argument', and the - returned list should contain the Nodes for all the direct - dependencies of the file. + The scanner function's first argument will be a Node that should + be scanned for dependencies, the second argument will be an + Environment object, the third argument will be the tuple of paths + returned by the path_function, and the fourth argument will be + the value passed into 'argument', and the returned list should + contain the Nodes for all the direct dependencies of the file. Examples: @@ -218,10 +216,11 @@ class Base: kw = {} if hasattr(node, 'dir'): kw['directory'] = node.dir + node_factory = env.get_factory(self.node_factory) nodes = [] for l in list: if self.node_class and not isinstance(l, self.node_class): - l = apply(self.node_factory, (l,), kw) + l = apply(node_factory, (l,), kw) nodes.append(l) return nodes @@ -315,11 +314,9 @@ class Classic(Current): include file in group 0. """ - def __init__(self, name, suffixes, path_variable, regex, - fs=SCons.Node.FS.default_fs, *args, **kw): + def __init__(self, name, suffixes, path_variable, regex, *args, **kw): self.cre = re.compile(regex, re.M) - self.fs = fs def _scan(node, env, path=(), self=self): node = node.rfile() @@ -328,7 +325,7 @@ class Classic(Current): return self.scan(node, path) kw['function'] = _scan - kw['path_function'] = FindPathDirs(path_variable, fs) + kw['path_function'] = FindPathDirs(path_variable) kw['recursive'] = 1 kw['skeys'] = suffixes kw['name'] = name diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index d018d15..fd2a914 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -241,7 +241,6 @@ class QuestionTask(SCons.Taskmaster.Task): # Global variables keep_going_on_error = 0 -count_stats = None print_dtree = 0 print_explanations = 0 print_includes = 0 @@ -251,7 +250,6 @@ print_stacktrace = 0 print_stree = 0 print_time = 0 print_tree = 0 -memory_stats = None ignore_errors = 0 sconscript_time = 0 command_time = 0 @@ -260,6 +258,62 @@ profiling = 0 repositories = [] num_jobs = 1 # this is modifed by SConscript.SetJobs() +# +class Stats: + def __init__(self): + self.stats = [] + self.labels = [] + self.append = self.do_nothing + self.print_stats = self.do_nothing + def enable(self, outfp): + self.outfp = outfp + self.append = self.do_append + self.print_stats = self.do_print + def do_nothing(self, *args, **kw): + pass + +class CountStats(Stats): + def do_append(self, label): + self.labels.append(label) + self.stats.append(SCons.Debug.fetchLoggedInstances()) + def do_print(self): + stats_table = {} + for s in self.stats: + for n in map(lambda t: t[0], s): + stats_table[n] = [0, 0, 0, 0] + i = 0 + for s in self.stats: + for n, c in s: + stats_table[n][i] = c + i = i + 1 + keys = stats_table.keys() + keys.sort() + self.outfp.write("Object counts:\n") + pre = [" "] + post = [" %s\n"] + l = len(self.stats) + fmt1 = string.join(pre + [' %7s']*l + post, '') + fmt2 = string.join(pre + [' %7d']*l + post, '') + self.labels.append(("", "Class")) + self.outfp.write(fmt1 % tuple(map(lambda x: x[0], self.labels))) + self.outfp.write(fmt1 % tuple(map(lambda x: x[1], self.labels))) + for k in keys: + r = stats_table[k] + self.outfp.write(fmt2 % (r[0], r[1], r[2], r[3], k)) + +count_stats = CountStats() + +class MemStats(Stats): + def do_append(self, label): + self.labels.append(label) + self.stats.append(SCons.Debug.memory()) + def do_print(self): + fmt = 'Memory %-32s %12d\n' + for label, stats in map(None, self.labels, self.stats): + self.outfp.write(fmt % (label, stats)) + +memory_stats = MemStats() + # utility functions def get_all_children(node): return node.all_children() @@ -406,15 +460,13 @@ def _SConstruct_exists(dirname=''): return None def _set_globals(options): - global repositories, keep_going_on_error, ignore_errors + global keep_going_on_error, ignore_errors global count_stats, print_dtree global print_explanations, print_includes, print_memoizer global print_objects, print_stacktrace, print_stree global print_time, print_tree - global memory_outf, memory_stats + global memory_stats - if options.repository: - repositories.extend(options.repository) keep_going_on_error = options.keep_going try: debug_values = options.debug @@ -424,7 +476,7 @@ def _set_globals(options): pass else: if "count" in debug_values: - count_stats = [] + count_stats.enable(sys.stdout) if "dtree" in debug_values: print_dtree = 1 if "explain" in debug_values: @@ -436,8 +488,7 @@ def _set_globals(options): if "memoizer" in debug_values: print_memoizer = 1 if "memory" in debug_values: - memory_stats = [] - memory_outf = sys.stdout + memory_stats.enable(sys.stdout) if "objects" in debug_values: print_objects = 1 if "presub" in debug_values: @@ -795,50 +846,28 @@ class SConscriptSettableOptions: def _main(args, parser): - targets = [] - fs = SCons.Node.FS.default_fs - - # Enable deprecated warnings by default. + # Here's where everything really happens. + + # First order of business: set up default warnings and and then + # handle the user's warning options, so we can warn about anything + # that happens appropriately. + default_warnings = [ SCons.Warnings.CorruptSConsignWarning, + SCons.Warnings.DeprecatedWarning, + SCons.Warnings.DuplicateEnvironmentWarning, + SCons.Warnings.MissingSConscriptWarning, + SCons.Warnings.NoParallelSupportWarning, + SCons.Warnings.MisleadingKeywordsWarning, ] + for warning in default_warnings: + SCons.Warnings.enableWarningClass(warning) SCons.Warnings._warningOut = _scons_internal_warning - SCons.Warnings.enableWarningClass(SCons.Warnings.CorruptSConsignWarning) - SCons.Warnings.enableWarningClass(SCons.Warnings.DeprecatedWarning) - SCons.Warnings.enableWarningClass(SCons.Warnings.DuplicateEnvironmentWarning) - SCons.Warnings.enableWarningClass(SCons.Warnings.MissingSConscriptWarning) - SCons.Warnings.enableWarningClass(SCons.Warnings.NoParallelSupportWarning) - # This is good for newbies, and hopefully most everyone else too. - SCons.Warnings.enableWarningClass(SCons.Warnings.MisleadingKeywordsWarning) - - global ssoptions - ssoptions = SConscriptSettableOptions(options) - - _set_globals(options) - SCons.Node.implicit_cache = options.implicit_cache - SCons.Node.implicit_deps_changed = options.implicit_deps_changed - SCons.Node.implicit_deps_unchanged = options.implicit_deps_unchanged if options.warn: _setup_warn(options.warn) - if options.noexec: - SCons.SConf.dryrun = 1 - SCons.Action.execute_actions = None - CleanTask.execute = CleanTask.show - if options.question: - SCons.SConf.dryrun = 1 - SCons.SConf.SetCacheMode(options.config) - SCons.SConf.SetProgressDisplay(progress_display) - if options.no_progress or options.silent: - progress_display.set_mode(0) - if options.silent: - display.set_mode(0) - if options.silent: - SCons.Action.print_actions = None - if options.cache_disable: - def disable(self): pass - fs.CacheDir = disable - if options.cache_force: - fs.cache_force = 1 - if options.cache_show: - fs.cache_show = 1 + # Next, we want to create the FS object that represents the outside + # world's file system, as that's central to a lot of initialization. + # To do this, however, we need to be in the directory from which we + # want to start everything, which means first handling any relevant + # options that might cause us to chdir somewhere (-C, -D, -U, -u). if options.directory: cdir = _create_path(options.directory) try: @@ -846,14 +875,11 @@ def _main(args, parser): except OSError: sys.stderr.write("Could not change directory to %s\n" % cdir) - xmit_args = [] - for a in args: - if '=' in a: - xmit_args.append(a) - else: - targets.append(a) - SCons.Script._Add_Arguments(xmit_args) - SCons.Script._Add_Targets(targets) + # The SConstruct file may be in a repository, so initialize those + # before we start the search up our path for one. + global repositories + if options.repository: + repositories.extend(options.repository) target_top = None if options.climb_up: @@ -869,8 +895,17 @@ def _main(args, parser): display("scons: Entering directory `%s'" % script_dir) os.chdir(script_dir) - fs.set_toplevel_dir(os.getcwd()) + # Now that we're in the top-level SConstruct directory, go ahead + # and initialize the FS object that represents the file system, + # and make it the build engine default. + fs = SCons.Node.FS.default_fs = SCons.Node.FS.FS() + + for rep in repositories: + fs.Repository(rep) + # Now that we have the FS object, the next order of business is to + # check for an SConstruct file (or other specified config file). + # If there isn't one, we can bail before doing any more work. scripts = [] if options.file: scripts.extend(options.file) @@ -879,15 +914,13 @@ def _main(args, parser): if sfile: scripts.append(sfile) - if options.help_msg: - if not scripts: + if not scripts: + if options.help_msg: # There's no SConstruct, but they specified -h. # Give them the options usage now, before we fail # trying to read a non-existent SConstruct file. parser.print_help() sys.exit(0) - - if not scripts: raise SCons.Errors.UserError, "No SConstruct file found." if scripts[0] == "-": @@ -896,6 +929,54 @@ def _main(args, parser): d = fs.File(scripts[0]).dir fs.set_SConstruct_dir(d) + # Now that we have the FS object and it's intialized, set up (most + # of) the rest of the options. + global ssoptions + ssoptions = SConscriptSettableOptions(options) + + _set_globals(options) + SCons.Node.implicit_cache = options.implicit_cache + SCons.Node.implicit_deps_changed = options.implicit_deps_changed + SCons.Node.implicit_deps_unchanged = options.implicit_deps_unchanged + if options.noexec: + SCons.SConf.dryrun = 1 + SCons.Action.execute_actions = None + CleanTask.execute = CleanTask.show + if options.question: + SCons.SConf.dryrun = 1 + SCons.SConf.SetCacheMode(options.config) + SCons.SConf.SetProgressDisplay(progress_display) + + if options.no_progress or options.silent: + progress_display.set_mode(0) + if options.silent: + display.set_mode(0) + if options.silent: + SCons.Action.print_actions = None + if options.cache_disable: + def disable(self): pass + fs.CacheDir = disable + if options.cache_force: + fs.cache_force = 1 + if options.cache_show: + fs.cache_show = 1 + + if options.include_dir: + sys.path = options.include_dir + sys.path + + # That should cover (most of) the options. Next, set up the variables + # that hold command-line arguments, so the SConscript files that we + # read and execute have access to them. + targets = [] + xmit_args = [] + for a in args: + if '=' in a: + xmit_args.append(a) + else: + targets.append(a) + SCons.Script._Add_Targets(targets) + SCons.Script._Add_Arguments(xmit_args) + class Unbuffered: def __init__(self, file): self.file = file @@ -907,15 +988,8 @@ def _main(args, parser): sys.stdout = Unbuffered(sys.stdout) - if options.include_dir: - sys.path = options.include_dir + sys.path - - global repositories - for rep in repositories: - fs.Repository(rep) - - if not memory_stats is None: memory_stats.append(SCons.Debug.memory()) - if not count_stats is None: count_stats.append(SCons.Debug.fetchLoggedInstances()) + memory_stats.append('before reading SConscript files:') + count_stats.append(('pre-', 'read')) progress_display("scons: Reading SConscript files ...") @@ -944,8 +1018,8 @@ def _main(args, parser): # file system nodes. SCons.Node.FS.save_strings(1) - if not memory_stats is None: memory_stats.append(SCons.Debug.memory()) - if not count_stats is None: count_stats.append(SCons.Debug.fetchLoggedInstances()) + memory_stats.append('after reading SConscript files:') + count_stats.append(('post-', 'read')) fs.chdir(fs.Top) @@ -1084,8 +1158,8 @@ def _main(args, parser): "\tignoring -j or num_jobs option.\n" SCons.Warnings.warn(SCons.Warnings.NoParallelSupportWarning, msg) - if not memory_stats is None: memory_stats.append(SCons.Debug.memory()) - if not count_stats is None: count_stats.append(SCons.Debug.fetchLoggedInstances()) + memory_stats.append('before building targets:') + count_stats.append(('pre-', 'build')) try: jobs.run() @@ -1097,37 +1171,11 @@ def _main(args, parser): if not options.noexec: SCons.SConsign.write() - if not memory_stats is None: - memory_stats.append(SCons.Debug.memory()) - when = [ - 'before reading SConscript files', - 'after reading SConscript files', - 'before building targets', - 'after building targets', - ] - for i in xrange(len(when)): - memory_outf.write('Memory %-32s %12d\n' % (when[i]+':', memory_stats[i])) - - if not count_stats is None: - count_stats.append(SCons.Debug.fetchLoggedInstances()) - stats_table = {} - for cs in count_stats: - for n in map(lambda t: t[0], cs): - stats_table[n] = [0, 0, 0, 0] - i = 0 - for cs in count_stats: - for n, c in cs: - stats_table[n][i] = c - i = i + 1 - keys = stats_table.keys() - keys.sort() - print "Object counts:" - fmt = " %7s %7s %7s %7s %s" - print fmt % ("pre-", "post-", "pre-", "post-", "") - print fmt % ("read", "read", "build", "build", "Class") - for k in keys: - r = stats_table[k] - print " %7d %7d %7d %7d %s" % (r[0], r[1], r[2], r[3], k) + memory_stats.append('after building targets:') + memory_stats.print_stats() + + count_stats.append(('post-', 'build')) + count_stats.print_stats() if print_objects: SCons.Debug.listLoggedInstances('*') @@ -1139,8 +1187,8 @@ def _main(args, parser): # Dump any development debug info that may have been enabled. # These are purely for internal debugging during development, so - # there's no need to control the with --debug= options, they're - # controlled by changing the source code.) + # there's no need to control them with --debug= options; they're + # controlled by changing the source code. SCons.Debug.dump_caller_counts() SCons.Taskmaster.dump_stats() diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py index 07dfd55..7ca9993 100644 --- a/src/engine/SCons/Script/SConscript.py +++ b/src/engine/SCons/Script/SConscript.py @@ -117,16 +117,16 @@ def compute_exports(exports): class Frame: """A frame on the SConstruct/SConscript call stack""" - def __init__(self, exports, sconscript): + def __init__(self, fs, exports, sconscript): self.globals = BuildDefaultGlobals() self.retval = None - self.prev_dir = SCons.Node.FS.default_fs.getcwd() + self.prev_dir = fs.getcwd() self.exports = compute_exports(exports) # exports from the calling SConscript # make sure the sconscript attr is a Node. if isinstance(sconscript, SCons.Node.Node): self.sconscript = sconscript else: - self.sconscript = SCons.Node.FS.default_fs.File(str(sconscript)) + self.sconscript = fs.File(str(sconscript)) # the SConstruct/SConscript call stack: call_stack = [] @@ -158,7 +158,7 @@ def _SConscript(fs, *files, **kw): # evaluate each SConscript file results = [] for fn in files: - call_stack.append(Frame(exports,fn)) + call_stack.append(Frame(fs, exports, fn)) old_sys_path = sys.path try: SCons.Script.sconscript_reading = 1 diff --git a/src/engine/SCons/Tool/Perforce.py b/src/engine/SCons/Tool/Perforce.py index 22c75e9..37115e9 100644 --- a/src/engine/SCons/Tool/Perforce.py +++ b/src/engine/SCons/Tool/Perforce.py @@ -75,7 +75,7 @@ def generate(env): # calling getcwd() for itself, which is odd. If no PWD variable # is present, p4 WILL call getcwd, but this seems to cause problems # with good ol' Win32's tilde-mangling for long file names. - environ['PWD'] = SCons.Node.FS.default_fs.Dir('#').get_abspath() + environ['PWD'] = env.Dir('#').get_abspath() for var in _import_env: v = os.environ.get(var) diff --git a/src/engine/SCons/Tool/jar.py b/src/engine/SCons/Tool/jar.py index a721d96..b069990 100644 --- a/src/engine/SCons/Tool/jar.py +++ b/src/engine/SCons/Tool/jar.py @@ -82,7 +82,7 @@ def jarChdir(target, source, env, for_signature): JarAction = SCons.Action.Action('$JARCOM', '$JARCOMSTR') JarBuilder = SCons.Builder.Builder(action = JarAction, - source_factory = SCons.Node.FS.default_fs.Entry, + source_factory = SCons.Node.FS.Entry, suffix = '$JARSUFFIX') def generate(env): diff --git a/src/engine/SCons/Tool/javac.py b/src/engine/SCons/Tool/javac.py index 8741c23..44a4bd0 100644 --- a/src/engine/SCons/Tool/javac.py +++ b/src/engine/SCons/Tool/javac.py @@ -99,8 +99,8 @@ JavaAction = SCons.Action.Action('$JAVACCOM', '$JAVACCOMSTR') JavaBuilder = SCons.Builder.Builder(action = JavaAction, emitter = emit_java_classes, - target_factory = SCons.Node.FS.default_fs.Dir, - source_factory = SCons.Node.FS.default_fs.Dir) + target_factory = SCons.Node.FS.Dir, + source_factory = SCons.Node.FS.Dir) def generate(env): """Add Builders and construction variables for javac to an Environment.""" diff --git a/src/engine/SCons/Tool/javah.py b/src/engine/SCons/Tool/javah.py index 4d5749a..26fcc53 100644 --- a/src/engine/SCons/Tool/javah.py +++ b/src/engine/SCons/Tool/javah.py @@ -59,7 +59,7 @@ def emit_java_headers(target, source, env): classdir = s.attributes.java_classdir except AttributeError: classdir = '.' - classdir = SCons.Node.FS.default_fs.Dir(classdir).rdir() + classdir = env.Dir(classdir).rdir() if str(classdir) == '.': c_ = None else: @@ -111,8 +111,8 @@ JavaHAction = SCons.Action.Action('$JAVAHCOM', '$JAVAHCOMSTR') JavaHBuilder = SCons.Builder.Builder(action = JavaHAction, emitter = emit_java_headers, src_suffix = '$JAVACLASSSUFFIX', - target_factory = SCons.Node.FS.default_fs.Entry, - source_factory = SCons.Node.FS.default_fs.File) + target_factory = SCons.Node.FS.Entry, + source_factory = SCons.Node.FS.File) def generate(env): """Add Builders and construction variables for javah to an Environment.""" diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index 04e09f5..e03eb8d 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -1049,8 +1049,8 @@ def projectEmitter(target, source, env): suff = env.subst('$MSVSPROJECTSUFFIX') target[0] = base + suff - dspfile = SCons.Node.FS.default_fs.File(target[0]).srcnode() - dswfile = SCons.Node.FS.default_fs.File(SCons.Util.splitext(str(dspfile))[0] + env.subst('$MSVSSOLUTIONSUFFIX')) + dspfile = env.File(target[0]).srcnode() + dswfile = env.File(SCons.Util.splitext(str(dspfile))[0] + env.subst('$MSVSSOLUTIONSUFFIX')) # XXX Need to find a way to abstract this; the build engine # shouldn't depend on anything in SCons.Script. @@ -1060,7 +1060,7 @@ def projectEmitter(target, source, env): source[0].attributes.sconstruct = stack[0].sconscript bdswpath = SCons.Util.splitext(str(target[0]))[0] + env.subst('$MSVSSOLUTIONSUFFIX') - bdswfile = SCons.Node.FS.default_fs.File(bdswpath) + bdswfile = env.File(bdswpath) # only make these side effects if they're # not the same file. diff --git a/src/engine/SCons/Tool/qt.py b/src/engine/SCons/Tool/qt.py index bc2d41b..04b6215 100644 --- a/src/engine/SCons/Tool/qt.py +++ b/src/engine/SCons/Tool/qt.py @@ -107,7 +107,6 @@ class _Automoc: debug = 0 # some shortcuts used in the scanner - FS = SCons.Node.FS.default_fs splitext = SCons.Util.splitext objBuilder = getattr(env, self.objBuilderName) @@ -147,9 +146,7 @@ class _Automoc: # try to find the header file in the corresponding source # directory hname = splitext(cpp.name)[0] + h_ext - h = find_file(hname, - (cpp.get_dir(),), - FS.File) + h = find_file(hname, (cpp.get_dir(),), env.File) if h: if debug: print "scons: qt: Scanning '%s' (header of '%s')" % (str(h), str(cpp)) diff --git a/src/engine/SCons/Tool/rmic.py b/src/engine/SCons/Tool/rmic.py index c5c4854..4b48e0b 100644 --- a/src/engine/SCons/Tool/rmic.py +++ b/src/engine/SCons/Tool/rmic.py @@ -58,7 +58,7 @@ def emit_rmic_classes(target, source, env): classdir = s.attributes.java_classdir except AttributeError: classdir = '.' - classdir = SCons.Node.FS.default_fs.Dir(classdir).rdir() + classdir = env.Dir(classdir).rdir() if str(classdir) == '.': c_ = None else: @@ -95,8 +95,8 @@ RMICAction = SCons.Action.Action('$RMICCOM', '$RMICCOMSTR') RMICBuilder = SCons.Builder.Builder(action = RMICAction, emitter = emit_rmic_classes, src_suffix = '$JAVACLASSSUFFIX', - target_factory = SCons.Node.FS.default_fs.Dir, - source_factory = SCons.Node.FS.default_fs.File) + target_factory = SCons.Node.FS.Dir, + source_factory = SCons.Node.FS.File) def generate(env): """Add Builders and construction variables for rmic to an Environment.""" diff --git a/src/engine/SCons/Tool/tar.py b/src/engine/SCons/Tool/tar.py index 079865e..58b7554 100644 --- a/src/engine/SCons/Tool/tar.py +++ b/src/engine/SCons/Tool/tar.py @@ -44,7 +44,7 @@ tars = ['tar', 'gtar'] TarAction = SCons.Action.Action('$TARCOM', '$TARCOMSTR') TarBuilder = SCons.Builder.Builder(action = TarAction, - source_factory = SCons.Node.FS.default_fs.Entry, + source_factory = SCons.Node.FS.Entry, source_scanner = SCons.Defaults.DirScanner, suffix = '$TARSUFFIX', multi = 1) diff --git a/src/engine/SCons/Tool/zip.py b/src/engine/SCons/Tool/zip.py index b67528b..fe9ce32 100644 --- a/src/engine/SCons/Tool/zip.py +++ b/src/engine/SCons/Tool/zip.py @@ -69,7 +69,7 @@ else: zipAction = SCons.Action.Action(zip, varlist=['ZIPCOMPRESSION']) ZipBuilder = SCons.Builder.Builder(action = SCons.Action.Action('$ZIPCOM', '$ZIPCOMSTR'), - source_factory = SCons.Node.FS.default_fs.Entry, + source_factory = SCons.Node.FS.Entry, source_scanner = SCons.Defaults.DirScanner, suffix = '$ZIPSUFFIX', multi = 1) -- cgit v0.12