diff options
author | Steven Knight <knight@baldmt.com> | 2004-04-10 07:35:32 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2004-04-10 07:35:32 (GMT) |
commit | 622d5777ae1e7db95933e3218a0619a764f20bd6 (patch) | |
tree | 27c321637161e64f419cc0b259c25205c2948417 /src | |
parent | f8c2e8cf9666d85adbd85d0bc0dbebaca76fde08 (diff) | |
download | SCons-622d5777ae1e7db95933e3218a0619a764f20bd6.zip SCons-622d5777ae1e7db95933e3218a0619a764f20bd6.tar.gz SCons-622d5777ae1e7db95933e3218a0619a764f20bd6.tar.bz2 |
Add support for extending the suffixes a scanner knows about.
Diffstat (limited to 'src')
-rw-r--r-- | src/CHANGES.txt | 9 | ||||
-rw-r--r-- | src/RELEASE.txt | 12 | ||||
-rw-r--r-- | src/engine/SCons/Defaults.py | 19 | ||||
-rw-r--r-- | src/engine/SCons/Environment.py | 28 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/C.py | 5 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/CTests.py | 84 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/D.py | 6 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/Fortran.py | 2 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/IDL.py | 2 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/ScannerTests.py | 24 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/__init__.py | 6 | ||||
-rw-r--r-- | src/engine/SCons/Tool/mingw.py | 4 | ||||
-rw-r--r-- | src/engine/SCons/Tool/msvc.py | 4 |
13 files changed, 138 insertions, 67 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt index a7323ea..d7922ce 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -67,6 +67,15 @@ RELEASE 0.96 - XXX - Enhance the Task.make_ready() method to create a list of the out-of-date Nodes for the task for use by the wrapping interface. + - Allow Scanners to pull the list of suffixes from the construction + environment when the "skeys" keyword argument is a string containing + a construction variable to be expanded. + + - Support new $CPPSUFFIXES, $DSUFFIXES $FORTRANSUFFIXES, and + $IDLSUFFIXES. construction variables that contain the default list + of suffixes to be scanned by a given type of scanner, allowing these + suffix lists to be easily added to or overridden. + From Gary Oberbrunner: - Add a --debug=presub option to print actions prior to substitution. diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 619c988..09a3d6f 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -27,6 +27,18 @@ RELEASE 0.96 - XXX Please note the following important changes since release 0.95: + - The internal Scanner.add_skey() method longer works for the default + scanners, which now use construction variables to hold their lists + of suffixes. If you had a custom Tool specification that was + reaching into the internals in this way to add a suffix to one of + the following scanner, you must now add the suffix to a construction + environment through which you plan to call the scanner, as follows: + + + CScan.add_skey('.x') => env.Append(CPPSUFFIXES = ['.x']) + DScan.add_skey('.x') => env.Append(DSUFFIXES = ['.x']) + FortranScan.add_skey('.x') => env.Append(FORTRANSUFFIXES = ['.x']) + - The behavior of the env.Append() and env.Prepend() methods has changed when appending a string value to a UserList, or vice versa. They now behave like normal Python addition of a string to diff --git a/src/engine/SCons/Defaults.py b/src/engine/SCons/Defaults.py index 4c7b0cc..94ab8d5 100644 --- a/src/engine/SCons/Defaults.py +++ b/src/engine/SCons/Defaults.py @@ -94,12 +94,25 @@ def SharedFlagChecker(source, target, env): SharedCheck = SCons.Action.Action(SharedFlagChecker, None) -# Scanners and actions for common language(s). +# Scanners and suffixes for common languages. CScan = SCons.Scanner.C.CScan() + +CSuffixes = [".c", ".C", ".cxx", ".cpp", ".c++", ".cc", + ".h", ".H", ".hxx", ".hpp", ".hh", + ".F", ".fpp", ".FPP", + ".S", ".spp", ".SPP"] + DScan = SCons.Scanner.D.DScan() +DSuffixes = ['.d'] + FortranScan = SCons.Scanner.Fortran.FortranScan() +FortranSuffixes = [".f", ".F", ".for", ".FOR"] + +IDLSuffixes = [".idl", ".IDL"] + +# Actions for common languages. CAction = SCons.Action.Action("$CCCOM") DAction = SCons.Action.Action("$DCOM") ShCAction = SCons.Action.Action("$SHCCCOM") @@ -253,6 +266,10 @@ class NullCmdGenerator: ConstructionEnvironment = { 'BUILDERS' : {}, 'SCANNERS' : [CScan, FortranScan, DScan], + 'CPPSUFFIXES': CSuffixes, + 'DSUFFIXES' : DSuffixes, + 'FORTRANSUFFIXES': FortranSuffixes, + 'IDLSUFFIXES': IDLSuffixes, 'PDFPREFIX' : '', 'PDFSUFFIX' : '.pdf', 'PSPREFIX' : '', diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 57056ad..2144a7f 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -384,14 +384,28 @@ class Base: def get_scanner(self, skey): """Find the appropriate scanner given a key (usually a file suffix). - Does a linear search. Could be sped up by creating a dictionary if - this proves too slow. """ - if self._dict['SCANNERS']: - for scanner in self._dict['SCANNERS']: - if skey in scanner.skeys: - return scanner - return None + try: + sm = self.scanner_map + except AttributeError: + try: + scanners = self._dict['SCANNERS'] + except KeyError: + return None + else: + self.scanner_map = sm = {} + # Reverse the scanner list so that, if multiple scanners + # claim they can scan the same suffix, earlier scanners + # in the list will overwrite later scanners, so that + # the result looks like a "first match" to the user. + scanners.reverse() + for scanner in scanners: + for k in scanner.get_skeys(self): + sm[k] = scanner + try: + return sm[skey] + except KeyError: + return None def subst(self, string, raw=0, target=None, source=None, dict=None, conv=None): """Recursively interpolates construction variables from the diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py index 4fcf327..a5c2331 100644 --- a/src/engine/SCons/Scanner/C.py +++ b/src/engine/SCons/Scanner/C.py @@ -36,10 +36,7 @@ def CScan(fs = SCons.Node.FS.default_fs): """Return a prototype Scanner instance for scanning source files that use the C pre-processor""" cs = SCons.Scanner.ClassicCPP("CScan", - [".c", ".C", ".cxx", ".cpp", ".c++", ".cc", - ".h", ".H", ".hxx", ".hpp", ".hh", - ".F", ".fpp", ".FPP", - ".S", ".spp", ".SPP"], + "$CPPSUFFIXES", "CPPPATH", '^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")', fs = fs) diff --git a/src/engine/SCons/Scanner/CTests.py b/src/engine/SCons/Scanner/CTests.py index abb72a4..f63060a 100644 --- a/src/engine/SCons/Scanner/CTests.py +++ b/src/engine/SCons/Scanner/CTests.py @@ -23,15 +23,18 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import TestCmd -import SCons.Scanner.C -import unittest -import sys import os import os.path +import sys +import TestCmd +import unittest +import UserDict + import SCons.Node.FS import SCons.Warnings +import SCons.Scanner.C + test = TestCmd.TestCmd(workdir = '') os.chdir(test.workpath('')) @@ -167,38 +170,29 @@ test.write("f5b.h", "\n") # define some helpers: -class DummyEnvironment: - def __init__(self, listCppPath): - self.path = listCppPath - +class DummyEnvironment(UserDict.UserDict): + def __init__(self, **kw): + UserDict.UserDict.__init__(self) + self.data.update(kw) + def Dictionary(self, *args): - if not args: - return { 'CPPPATH': self.path } - elif len(args) == 1 and args[0] == 'CPPPATH': - return self.path - else: - raise KeyError, "Dummy environment only has CPPPATH attribute." + return self.data + + def subst(self, strSubst): + if strSubst[0] == '$': + return self.data[strSubst[1:]] + return strSubst - def subst(self, arg): - return arg + def subst_list(self, strSubst): + if strSubst[0] == '$': + return [self.data[strSubst[1:]]] + return [[strSubst]] def subst_path(self, path): if type(path) != type([]): path = [path] return map(self.subst, path) - def has_key(self, key): - return self.Dictionary().has_key(key) - - def __getitem__(self,key): - return self.Dictionary()[key] - - def __setitem__(self,key,value): - self.Dictionary()[key] = value - - def __delitem__(self,key): - del self.Dictionary()[key] - if os.path.normcase('foo') == os.path.normcase('FOO'): my_normpath = os.path.normcase else: @@ -217,7 +211,7 @@ def make_node(filename, fs=SCons.Node.FS.default_fs): class CScannerTestCase1(unittest.TestCase): def runTest(self): - env = DummyEnvironment([]) + env = DummyEnvironment(CPPPATH=[]) s = SCons.Scanner.C.CScan() path = s.path(env) deps = s(make_node('f1.cpp'), env, path) @@ -226,7 +220,7 @@ class CScannerTestCase1(unittest.TestCase): class CScannerTestCase2(unittest.TestCase): def runTest(self): - env = DummyEnvironment([test.workpath("d1")]) + env = DummyEnvironment(CPPPATH=[test.workpath("d1")]) s = SCons.Scanner.C.CScan() path = s.path(env) deps = s(make_node('f1.cpp'), env, path) @@ -235,7 +229,7 @@ class CScannerTestCase2(unittest.TestCase): class CScannerTestCase3(unittest.TestCase): def runTest(self): - env = DummyEnvironment([test.workpath("d1")]) + env = DummyEnvironment(CPPPATH=[test.workpath("d1")]) s = SCons.Scanner.C.CScan() path = s.path(env) deps = s(make_node('f2.cpp'), env, path) @@ -244,7 +238,7 @@ class CScannerTestCase3(unittest.TestCase): class CScannerTestCase4(unittest.TestCase): def runTest(self): - env = DummyEnvironment([test.workpath("d1"), test.workpath("d1/d2")]) + env = DummyEnvironment(CPPPATH=[test.workpath("d1"), test.workpath("d1/d2")]) s = SCons.Scanner.C.CScan() path = s.path(env) deps = s(make_node('f2.cpp'), env, path) @@ -253,7 +247,7 @@ class CScannerTestCase4(unittest.TestCase): class CScannerTestCase5(unittest.TestCase): def runTest(self): - env = DummyEnvironment([]) + env = DummyEnvironment(CPPPATH=[]) s = SCons.Scanner.C.CScan() path = s.path(env) @@ -276,8 +270,8 @@ class CScannerTestCase5(unittest.TestCase): class CScannerTestCase6(unittest.TestCase): def runTest(self): - env1 = DummyEnvironment([test.workpath("d1")]) - env2 = DummyEnvironment([test.workpath("d1/d2")]) + env1 = DummyEnvironment(CPPPATH=[test.workpath("d1")]) + env2 = DummyEnvironment(CPPPATH=[test.workpath("d1/d2")]) s = SCons.Scanner.C.CScan() path1 = s.path(env1) path2 = s.path(env2) @@ -291,7 +285,7 @@ class CScannerTestCase6(unittest.TestCase): class CScannerTestCase8(unittest.TestCase): def runTest(self): fs = SCons.Node.FS.FS(test.workpath('')) - env = DummyEnvironment(["include"]) + env = DummyEnvironment(CPPPATH=["include"]) s = SCons.Scanner.C.CScan(fs = fs) path = s.path(env) deps1 = s(fs.File('fa.cpp'), env, path) @@ -317,7 +311,7 @@ class CScannerTestCase9(unittest.TestCase): SCons.Warnings._warningOut = to test.write('fa.h','\n') fs = SCons.Node.FS.FS(test.workpath('')) - env = DummyEnvironment([]) + env = DummyEnvironment(CPPPATH=[]) s = SCons.Scanner.C.CScan(fs=fs) path = s.path(env) deps = s(fs.File('fa.cpp'), env, path) @@ -332,7 +326,7 @@ class CScannerTestCase10(unittest.TestCase): def runTest(self): fs = SCons.Node.FS.FS(test.workpath('')) fs.chdir(fs.Dir('include')) - env = DummyEnvironment([]) + env = DummyEnvironment(CPPPATH=[]) s = SCons.Scanner.C.CScan(fs=fs) path = s.path(env) test.write('include/fa.cpp', test.read('fa.cpp')) @@ -351,7 +345,7 @@ class CScannerTestCase11(unittest.TestCase): # This was a bug at one time. f1=fs.File('include2/jjj.h') f1.builder=1 - env = DummyEnvironment(['include', 'include2']) + env = DummyEnvironment(CPPPATH=['include', 'include2']) s = SCons.Scanner.C.CScan(fs=fs) path = s.path(env) deps = s(fs.File('src/fff.c'), env, path) @@ -365,7 +359,7 @@ class CScannerTestCase12(unittest.TestCase): fs.BuildDir('build1', 'src', 1) fs.BuildDir('build2', 'src', 0) fs.Repository(test.workpath('repository')) - env = DummyEnvironment([]) + env = DummyEnvironment(CPPPATH=[]) s = SCons.Scanner.C.CScan(fs = fs) path = s.path(env) deps1 = s(fs.File('build1/aaa.c'), env, path) @@ -383,7 +377,7 @@ class CScannerTestCase13(unittest.TestCase): class SubstEnvironment(DummyEnvironment): def subst(self, arg, test=test): return test.workpath("d1") - env = SubstEnvironment(["blah"]) + env = SubstEnvironment(CPPPATH=["blah"]) s = SCons.Scanner.C.CScan() path = s.path(env) deps = s(make_node('f1.cpp'), env, path) @@ -392,7 +386,7 @@ class CScannerTestCase13(unittest.TestCase): class CScannerTestCase14(unittest.TestCase): def runTest(self): - env = DummyEnvironment([]) + env = DummyEnvironment(CPPPATH=[]) s = SCons.Scanner.C.CScan() path = s.path(env) deps = s(make_node('f5.c'), env, path) @@ -401,14 +395,14 @@ class CScannerTestCase14(unittest.TestCase): class CScannerTestCase15(unittest.TestCase): def runTest(self): - env = DummyEnvironment([]) - s = SCons.Scanner.C.CScan() suffixes = [".c", ".C", ".cxx", ".cpp", ".c++", ".cc", ".h", ".H", ".hxx", ".hpp", ".hh", ".F", ".fpp", ".FPP", ".S", ".spp", ".SPP"] + env = DummyEnvironment(CPPSUFFIXES = suffixes) + s = SCons.Scanner.C.CScan() for suffix in suffixes: - assert suffix in s.skeys, "%s not in skeys" % suffix + assert suffix in s.get_skeys(env), "%s not in skeys" % suffix diff --git a/src/engine/SCons/Scanner/D.py b/src/engine/SCons/Scanner/D.py index 28f3c29..27ba165 100644 --- a/src/engine/SCons/Scanner/D.py +++ b/src/engine/SCons/Scanner/D.py @@ -32,12 +32,14 @@ Coded by Andy Friesen __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +import string + import SCons.Scanner def DScan(fs = SCons.Node.FS.default_fs): """Return a prototype Scanner instance for scanning D source files""" ds = DScanner(name = "DScan", - suffixes = ['.d'], + suffixes = '$DSUFFIXES', path_variable = 'DPATH', regex = 'import\s+([^\;]*)\;', fs = fs) @@ -46,7 +48,7 @@ def DScan(fs = SCons.Node.FS.default_fs): class DScanner(SCons.Scanner.Classic): def find_include(self, include, source_dir, path): # translate dots (package separators) to slashes - inc = include.replace('.', '/') + inc = string.replace(include, '.', '/') i = SCons.Node.FS.find_file(inc + '.d', (source_dir,) + path, diff --git a/src/engine/SCons/Scanner/Fortran.py b/src/engine/SCons/Scanner/Fortran.py index 473375c..c29eec5 100644 --- a/src/engine/SCons/Scanner/Fortran.py +++ b/src/engine/SCons/Scanner/Fortran.py @@ -42,7 +42,7 @@ def FortranScan(fs = SCons.Node.FS.default_fs): """Return a prototype Scanner instance for scanning source files for Fortran INCLUDE statements""" scanner = SCons.Scanner.Classic("FortranScan", - [".f", ".F", ".for", ".FOR"], + "$FORTRANSUFFIXES", "F77PATH", "(?i)INCLUDE[ \t]+'([\\w./\\\\]+)'", fs = fs) diff --git a/src/engine/SCons/Scanner/IDL.py b/src/engine/SCons/Scanner/IDL.py index f8769a3..8c4f68d 100644 --- a/src/engine/SCons/Scanner/IDL.py +++ b/src/engine/SCons/Scanner/IDL.py @@ -36,7 +36,7 @@ import SCons.Scanner def IDLScan(fs = SCons.Node.FS.default_fs): """Return a prototype Scanner instance for scanning IDL source files""" cs = SCons.Scanner.ClassicCPP("IDLScan", - [".idl", ".IDL"], + "$IDLSUFFIXES", "CPPPATH", '^[ \t]*(?:#[ \t]*include|[ \t]*import)[ \t]+(<|")([^>"]+)(>|")', fs = fs) diff --git a/src/engine/SCons/Scanner/ScannerTests.py b/src/engine/SCons/Scanner/ScannerTests.py index 1051580..91a0f8c 100644 --- a/src/engine/SCons/Scanner/ScannerTests.py +++ b/src/engine/SCons/Scanner/ScannerTests.py @@ -34,7 +34,13 @@ class DummyEnvironment(UserDict.UserDict): UserDict.UserDict.__init__(self, dict) self.data.update(kw) def subst(self, strSubst): + if strSubst[0] == '$': + return self.data[strSubst[1:]] return strSubst + def subst_list(self, strSubst): + if strSubst[0] == '$': + return [self.data[strSubst[1:]]] + return [[strSubst]] def subst_path(self, path): if type(path) != type([]): path = [path] @@ -165,6 +171,24 @@ class ScannerTestCase(unittest.TestCase): self.failUnless(s.recursive == 1, "did not set recursive flag to 1") + def test_get_skeys(self): + """Test the Scanner.Base get_skeys() method""" + s = SCons.Scanner.Base(function = self.func) + sk = s.get_skeys() + self.failUnless(sk == [], + "did not initialize to expected []") + + s = SCons.Scanner.Base(function = self.func, skeys = ['.1', '.2']) + sk = s.get_skeys() + self.failUnless(sk == ['.1', '.2'], + "sk was %s, not ['.1', '.2']") + + s = SCons.Scanner.Base(function = self.func, skeys = '$LIST') + env = DummyEnvironment(LIST = ['.3', '.4']) + sk = s.get_skeys(env) + self.failUnless(sk == ['.3', '.4'], + "sk was %s, not ['.3', '.4']") + class CurrentTestCase(unittest.TestCase): def test_class(self): """Test the Scanner.Current class""" diff --git a/src/engine/SCons/Scanner/__init__.py b/src/engine/SCons/Scanner/__init__.py index c59480e..102849d 100644 --- a/src/engine/SCons/Scanner/__init__.py +++ b/src/engine/SCons/Scanner/__init__.py @@ -185,6 +185,12 @@ class Base: """Add a skey to the list of skeys""" self.skeys.append(skey) + def get_skeys(self, env=None): + if SCons.Util.is_String(self.skeys): + return env.subst_list(self.skeys)[0] + return self.skeys + + class Current(Base): """ A class for scanning files that are source files (have no builder) diff --git a/src/engine/SCons/Tool/mingw.py b/src/engine/SCons/Tool/mingw.py index fa46652..1369a8b 100644 --- a/src/engine/SCons/Tool/mingw.py +++ b/src/engine/SCons/Tool/mingw.py @@ -137,9 +137,7 @@ def generate(env): env['RCINCPREFIX'] = '--include-dir ' env['RCINCSUFFIX'] = '' env['RCCOM'] = '$RC $RCINCFLAGS $RCFLAGS -i $SOURCE -o $TARGET' - CScan = env.get_scanner('.c') - if CScan: - CScan.add_skey('.rc') + env.Append(CPPSUFFIXES = ['.rc']) env['BUILDERS']['RES'] = res_builder # Some setting from the platform also have to be overridden: diff --git a/src/engine/SCons/Tool/msvc.py b/src/engine/SCons/Tool/msvc.py index 19fbf1d..1caa4db 100644 --- a/src/engine/SCons/Tool/msvc.py +++ b/src/engine/SCons/Tool/msvc.py @@ -448,9 +448,7 @@ def generate(env): env['RC'] = 'rc' env['RCFLAGS'] = SCons.Util.CLVar('') env['RCCOM'] = '$RC $_CPPDEFFLAGS $_CPPINCFLAGS $RCFLAGS /fo$TARGET $SOURCES' - CScan = env.get_scanner('.c') - if CScan: - CScan.add_skey('.rc') + env.Append(CPPSUFFIXES = ['.rc']) env['BUILDERS']['RES'] = res_builder try: |