Complete CPPPATH work.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Thu, 22 Nov 2001 14:10:14 +0000 (14:10 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Thu, 22 Nov 2001 14:10:14 +0000 (14:10 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@122 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/engine/SCons/Scanner/C.py
src/engine/SCons/Scanner/CTests.py
src/engine/SCons/Scanner/Prog.py
src/engine/SCons/Scanner/ScannerTests.py
src/engine/SCons/Scanner/__init__.py
test/CPPPATH.py

index e2842e15fd00cfb8ec0ba8e62ac1806bb63fe63f..90cb141f98d35fa37665875fe71f0f79a703a8f1 100644 (file)
@@ -40,8 +40,9 @@ quote_re = re.compile('^[ \t]*#[ \t]*include[ \t]+"([\\w./\\\\]+)"', re.M)
 
 def CScan():
     "Return a Scanner instance for scanning C/C++ source files"
-    s = SCons.Scanner.Scanner(scan, SCons.Node.FS.default_fs.File,
-                              [".c", ".C", ".cxx", ".cpp", ".c++"])
+    s = SCons.Scanner.Recursive(scan, SCons.Node.FS.default_fs.File,
+                                [".c", ".C", ".cxx", ".cpp", ".c++",
+                                 ".h", ".H", ".hxx", ".hpp"])
     s.name = "CScan"
     return s
 
index e6bd29e9f5aca5ac3daa567add1b6ac46e2b0830..02a423b9a45174ae0a17bb283dd53119e75cd2ee 100644 (file)
@@ -79,13 +79,22 @@ int main()
 
 test.subdir('d1', ['d1', 'd2'])
 
-headers = ['f1.h','f2.h', 'f3.h', 'never.h',
-           'd1/f1.h', 'd1/f2.h', 'd1/f3.h',
-           'd1/d2/f1.h', 'd1/d2/f2.h', 'd1/d2/f3.h', 'd1/d2/f4.h']
+headers = ['f1.h','f2.h', 'f3.h', 'fi.h', 'fj.h', 'never.h',
+           'd1/f1.h', 'd1/f2.h', 'd1/f3.h', 'd1/fi.h', 'd1/fj.h',
+           'd1/d2/f1.h', 'd1/d2/f2.h', 'd1/d2/f3.h',
+           'd1/d2/f4.h', 'd1/d2/fi.h', 'd1/d2/fj.h']
 
 for h in headers:
     test.write(h, " ")
 
+test.write('f2.h',"""
+#include "fi.h"
+""")
+
+test.write('f3.h',"""
+#include <fj.h>
+""")
+
 # define some helpers:
 
 class DummyEnvironment:
@@ -115,7 +124,8 @@ class CScannerTestCase1(unittest.TestCase):
         env = DummyEnvironment([])
         s = SCons.Scanner.C.CScan()
         deps = s.scan(test.workpath('f1.cpp'), env)
-        self.failUnless(deps_match(deps, ['f1.h', 'f2.h']), map(str, deps))
+       headers = ['f1.h', 'f2.h', 'fi.h']
+        self.failUnless(deps_match(deps, headers), map(str, deps))
 
 class CScannerTestCase2(unittest.TestCase):
     def runTest(self):
@@ -146,7 +156,8 @@ class CScannerTestCase5(unittest.TestCase):
         env = DummyEnvironment([])
         s = SCons.Scanner.C.CScan()
         deps = s.scan(test.workpath('f3.cpp'), env)
-        headers =  ['f1.h', 'f2.h', 'f3.h', 'd1/f1.h', 'd1/f2.h', 'd1/f3.h']
+        headers =  ['f1.h', 'f2.h', 'f3.h', 'fi.h', 'fj.h',
+                    'd1/f1.h', 'd1/f2.h', 'd1/f3.h']
         self.failUnless(deps_match(deps, headers), map(str, deps))
 
 def suite():
index f9d352c94ebe43d5bd61794c615e749d6660c9b9..62dee973a7c1a7dbc214ca2e0f2589e94ba3bbe8 100644 (file)
@@ -30,7 +30,7 @@ import SCons.Util
 def ProgScan():
     """Return a Scanner instance for scanning executable files
     for static-lib dependencies"""
-    s = SCons.Scanner.Scanner(scan, SCons.Node.FS.default_fs.File)
+    s = SCons.Scanner.Base(scan, SCons.Node.FS.default_fs.File)
     s.name = "ProgScan"
     return s
 
index 757f239c69700d114b31e5e8324e141ca36eb8be..5d434a631b21f12d01844fdf7e7562a3f322854e 100644 (file)
@@ -59,7 +59,7 @@ class DummyEnvironment:
 class ScannerPositionalTestCase(ScannerTestBase, unittest.TestCase):
     "Test the Scanner class using the position argument"
     def runTest(self):
-        s = SCons.Scanner.Scanner(self.func)
+        s = SCons.Scanner.Base(self.func)
         env = DummyEnvironment()
         env.VARIABLE = "var1"
         self.test(s, env, 'f1.cpp', ['f1.h', 'f1.hpp'])
@@ -67,7 +67,7 @@ class ScannerPositionalTestCase(ScannerTestBase, unittest.TestCase):
 class ScannerKeywordTestCase(ScannerTestBase, unittest.TestCase):
     "Test the Scanner class using the keyword argument"
     def runTest(self):
-        s = SCons.Scanner.Scanner(function = self.func)
+        s = SCons.Scanner.Base(function = self.func)
         env = DummyEnvironment()
         env.VARIABLE = "var2"
         self.test(s, env, 'f2.cpp', ['f2.h', 'f2.hpp'])
@@ -76,7 +76,7 @@ class ScannerPositionalArgumentTestCase(ScannerTestBase, unittest.TestCase):
     "Test the Scanner class using the position argument and optional argument"
     def runTest(self):
         arg = "this is the argument"
-        s = SCons.Scanner.Scanner(self.func, arg)
+        s = SCons.Scanner.Base(self.func, arg)
         env = DummyEnvironment()
         env.VARIABLE = "var3"
         self.test(s, env, 'f3.cpp', ['f3.h', 'f3.hpp'], arg)
@@ -85,7 +85,7 @@ class ScannerKeywordArgumentTestCase(ScannerTestBase, unittest.TestCase):
     "Test the Scanner class using the keyword argument and optional argument"
     def runTest(self):
         arg = "this is another argument"
-        s = SCons.Scanner.Scanner(function = self.func, argument = arg)
+        s = SCons.Scanner.Base(function = self.func, argument = arg)
         env = DummyEnvironment()
         env.VARIABLE = "var4"
         self.test(s, env, 'f4.cpp', ['f4.h', 'f4.hpp'], arg)
index 28fab7ad7ccbaddf947d8a37a1a199daae4c2861..3c53396c576f402bbe5951b7501960fa9584abba 100644 (file)
@@ -42,7 +42,11 @@ class _Null:
 # used as an actual argument value.
 _null = _Null
 
-class Scanner:
+class Base:
+    """
+    The base class for dependency scanners.  This implements
+    straightforward, single-pass scanning of a single file.
+    """
 
     def __init__(self, function, argument=_null, skeys=[]):
         """
@@ -86,10 +90,10 @@ class Scanner:
 
     def scan(self, filename, env):
         """
-        This method does the actually scanning. 'filename' is the filename
+        This method scans a single object. 'filename' is the filename
         that will be passed to the scanner function, and 'env' is the
         environment that will be passed to the scanner function. A list of
-        dependencies will be returned (i.e. a list of 'Node's).
+        direct dependency nodes for the specified filename will be returned.
         """
 
         if not self.argument is _null:
@@ -108,3 +112,36 @@ class Scanner:
         if len(slist) == 1:
             slist = slist[0]
         return slist
+
+class Recursive(Base):
+    """
+    The class for recursive dependency scanning.  This will
+    re-scan any new files returned by each call to the
+    underlying scanning function, and return the aggregate
+    list of all dependencies.
+    """
+
+    def scan(self, filename, env):
+        """
+        This method does the actual scanning. 'filename' is the filename
+        that will be passed to the scanner function, and 'env' is the
+        environment that will be passed to the scanner function. An
+        aggregate list of dependency nodes for the specified filename
+        and any of its scanned dependencies will be returned.
+        """
+
+        files = [filename]
+        seen = [filename]
+        deps = []
+        while files:
+            f = files.pop(0)
+            if not self.argument is _null:
+                d = self.function(f, env, self.argument)
+            else:
+                d = self.function(f, env)
+            d = filter(lambda x, seen=seen: str(x) not in seen, d)
+            deps.extend(d)
+            s = map(str, d)
+           seen.extend(s)
+            files.extend(s)
+        return deps
index 32c00b6477b8163db01a811b10fd7426cbc6a992..345603bf56b3f448262bc0f92e7332204ed1d65b 100644 (file)
@@ -29,12 +29,13 @@ import TestSCons
 test = TestSCons.TestSCons()
 
 test.write('foo.c',
-"""#include "include/foo.h"
+"""#include "foo.h"
 #include <stdio.h>
 
 int main(void)
 {
-    printf(TEST_STRING);
+    printf(FOO_STRING);
+    printf(BAR_STRING);
     return 0;
 }
 """)
@@ -43,29 +44,52 @@ test.subdir('include')
 
 test.write('include/foo.h',
 """
-#define TEST_STRING "Bad news\n"
+#define        FOO_STRING "foo.h 1\n"
+#include "bar.h"
+""")
+
+test.write('include/bar.h',
+"""
+#define BAR_STRING "bar.h 1\n"
 """)
 
 test.write('SConstruct', """
-env = Environment()
+env = Environment(CPPPATH = ['include'])
 env.Program(target='prog', source='foo.c')
-#env.Depends(target='foo.c', dependency='include/foo.h')
 """)
 
 test.run(arguments = 'prog')
 
 test.run(program = test.workpath('prog'),
-         stdout = "Bad news\n")
+         stdout = "foo.h 1\nbar.h 1\n")
+
+test.up_to_date(arguments = 'prog')
 
 test.unlink('include/foo.h')
 test.write('include/foo.h',
 """
-#define TEST_STRING "Good news\n"
+#define        FOO_STRING "foo.h 2\n"
+#include "bar.h"
 """)
 
 test.run(arguments = 'prog')
 
 test.run(program = test.workpath('prog'),
-         stdout = "Good news\n")
+         stdout = "foo.h 2\nbar.h 1\n")
+
+test.up_to_date(arguments = 'prog')
+
+test.unlink('include/bar.h')
+test.write('include/bar.h',
+"""
+#define BAR_STRING "bar.h 2\n"
+""")
+
+test.run(arguments = 'prog')
+
+test.run(program = test.workpath('prog'),
+         stdout = "foo.h 2\nbar.h 2\n")
+
+test.up_to_date(arguments = 'prog')
 
 test.pass_test()