summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2001-12-13 04:42:05 (GMT)
committerSteven Knight <knight@baldmt.com>2001-12-13 04:42:05 (GMT)
commitc81b4be9b7a06dc41cc1f425887d4600fa47f0bc (patch)
treea800b193675c98825b6af007b88b1fb51c41c3e4 /src/engine/SCons
parentb9f370f232001d693f10279a3bcff8a0e66eb303 (diff)
downloadSCons-c81b4be9b7a06dc41cc1f425887d4600fa47f0bc.zip
SCons-c81b4be9b7a06dc41cc1f425887d4600fa47f0bc.tar.gz
SCons-c81b4be9b7a06dc41cc1f425887d4600fa47f0bc.tar.bz2
Bug fixes for Scanner handling of subdirectories and Environment copying, courtesy Charles Crain.
Diffstat (limited to 'src/engine/SCons')
-rw-r--r--src/engine/SCons/Builder.py2
-rw-r--r--src/engine/SCons/BuilderTests.py8
-rw-r--r--src/engine/SCons/Environment.py35
-rw-r--r--src/engine/SCons/EnvironmentTests.py15
-rw-r--r--src/engine/SCons/Node/FS.py11
-rw-r--r--src/engine/SCons/Node/FSTests.py11
-rw-r--r--src/engine/SCons/Node/NodeTests.py12
-rw-r--r--src/engine/SCons/Node/__init__.py8
-rw-r--r--src/engine/SCons/Scanner/C.py5
-rw-r--r--src/engine/SCons/Scanner/CTests.py25
10 files changed, 93 insertions, 39 deletions
diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py
index a578405..c7551af 100644
--- a/src/engine/SCons/Builder.py
+++ b/src/engine/SCons/Builder.py
@@ -236,7 +236,7 @@ class MultiStepBuilder(BuilderBase):
final_sources = []
src_suffix = env.subst(self.src_suffix)
for snode in slist:
- path, ext = os.path.splitext(snode.path)
+ path, ext = os.path.splitext(snode.abspath)
if not src_suffix or ext != src_suffix:
tgt = self.src_builder(env, target = [ path ],
source=snode)
diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py
index d563bb6..575cb77 100644
--- a/src/engine/SCons/BuilderTests.py
+++ b/src/engine/SCons/BuilderTests.py
@@ -400,7 +400,7 @@ class BuilderTestCase(unittest.TestCase):
scn = TestScanner()
builder=SCons.Builder.Builder(scanner=scn)
tgt = builder(env, target='foo', source='bar')
- assert tgt.scanner == scn, tgt.scanner
+ assert scn in tgt.scanners, tgt.scanners
assert instanced
instanced = None
@@ -411,7 +411,7 @@ class BuilderTestCase(unittest.TestCase):
src_builder = builder1,
scanner = scn)
tgt = builder2(env, target='baz', source='test.bar test2.foo test3.txt')
- assert tgt.scanner == scn, tgt.scanner
+ assert scn in tgt.scanners, tgt.scanners
assert instanced
def test_src_scanner(slf):
@@ -425,8 +425,8 @@ class BuilderTestCase(unittest.TestCase):
env_scanner = TestScanner()
builder = SCons.Builder.Builder(action='action')
tgt = builder(env, target='foo', source='bar')
- assert not tgt.scanner == env_scanner
- assert tgt.sources[0].scanner == env_scanner
+ assert not tgt.scanners == [ env_scanner ]
+ assert tgt.sources[0].scanners == [ env_scanner ]
if __name__ == "__main__":
suite = unittest.makeSuite(BuilderTestCase, 'test_')
diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py
index b93a3dd..69455e7 100644
--- a/src/engine/SCons/Environment.py
+++ b/src/engine/SCons/Environment.py
@@ -37,6 +37,7 @@ import re
import types
import SCons.Util
import SCons.Builder
+import SCons.Defaults
from SCons.Errors import UserError
from UserList import UserList
@@ -49,19 +50,18 @@ def Install():
def InstallAs():
pass # XXX
-
-
-def _deepcopy_atomic(x, memo):
- return x
-copy._deepcopy_dispatch[types.ModuleType] = _deepcopy_atomic
-copy._deepcopy_dispatch[types.ClassType] = _deepcopy_atomic
-copy._deepcopy_dispatch[types.FunctionType] = _deepcopy_atomic
-copy._deepcopy_dispatch[types.MethodType] = _deepcopy_atomic
-copy._deepcopy_dispatch[types.TracebackType] = _deepcopy_atomic
-copy._deepcopy_dispatch[types.FrameType] = _deepcopy_atomic
-copy._deepcopy_dispatch[types.FileType] = _deepcopy_atomic
-
-
+def our_deepcopy(x):
+ """deepcopy lists and dictionaries, and just copy the reference
+ for everything else."""
+ if type(x) is type({}):
+ copy = {}
+ for key in x.keys():
+ copy[key] = our_deepcopy(x[key])
+ elif type(x) is type([]):
+ copy = map(our_deepcopy, x)
+ else:
+ copy = x
+ return copy
class Environment:
"""Base class for construction Environments. These are
@@ -75,12 +75,12 @@ class Environment:
def __init__(self, **kw):
import SCons.Defaults
- self._dict = copy.deepcopy(SCons.Defaults.ConstructionEnvironment)
+ self._dict = our_deepcopy(SCons.Defaults.ConstructionEnvironment)
if kw.has_key('BUILDERS') and type(kw['BUILDERS']) != type([]):
kw['BUILDERS'] = [kw['BUILDERS']]
if kw.has_key('SCANNERS') and type(kw['SCANNERS']) != type([]):
kw['SCANNERS'] = [kw['SCANNERS']]
- self._dict.update(copy.deepcopy(kw))
+ self._dict.update(our_deepcopy(kw))
class BuilderWrapper:
"""Wrapper class that allows an environment to
@@ -124,7 +124,8 @@ class Environment:
(like a function). There are no references to any mutable
objects in the original Environment.
"""
- clone = copy.deepcopy(self)
+ clone = copy.copy(self)
+ clone._dict = our_deepcopy(self._dict)
apply(clone.Update, (), kw)
return clone
@@ -135,7 +136,7 @@ class Environment:
"""Update an existing construction Environment with new
construction variables and/or values.
"""
- self._dict.update(copy.deepcopy(kw))
+ self._dict.update(our_deepcopy(kw))
def Depends(self, target, dependency):
"""Explicity specify that 'target's depend on 'dependency'."""
diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py
index af9ccb7..3ba8ad4 100644
--- a/src/engine/SCons/EnvironmentTests.py
+++ b/src/engine/SCons/EnvironmentTests.py
@@ -159,6 +159,21 @@ class EnvironmentTestCase(unittest.TestCase):
assert env3.Dictionary('ZZZ') == 'z3'
assert env1 == env1copy
+ # Ensure that lists and dictionaries are
+ # deep copied, but not instances.
+ class TestA:
+ pass
+ env1 = Environment(XXX=TestA(), YYY = [ 1, 2, 3 ],
+ ZZZ = { 1:2, 3:4 })
+ env2=env1.Copy()
+ env2.Dictionary('YYY').append(4)
+ env2.Dictionary('ZZZ')[5] = 6
+ assert env1.Dictionary('XXX') is env2.Dictionary('XXX')
+ assert 4 in env2.Dictionary('YYY')
+ assert not 4 in env1.Dictionary('YYY')
+ assert env2.Dictionary('ZZZ').has_key(5)
+ assert not env1.Dictionary('ZZZ').has_key(5)
+
def test_Dictionary(self):
"""Test retrieval of known construction variables
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index cd12f6d..648e1f9 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -466,11 +466,12 @@ class File(Entry):
return self.dir.sconsign().get(self.name)
def scan(self):
- if not self.scanned.has_key(self.scanner) and self.env:
- if self.scanner:
- self.add_implicit(self.scanner.scan(self.path, self.env),
- self.scanner)
- self.scanned[self.scanner] = 1
+ if self.env:
+ for scn in self.scanners:
+ if not self.scanned.has_key(scn):
+ self.add_implicit(scn.scan(self.path, self.env),
+ scn)
+ self.scanned[scn] = 1
def __createDir(self):
# ensure that the directories for this node are
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py
index aecbfb4..523f96b 100644
--- a/src/engine/SCons/Node/FSTests.py
+++ b/src/engine/SCons/Node/FSTests.py
@@ -301,15 +301,16 @@ class FSTestCase(unittest.TestCase):
match(e13.path, "subdir/subdir/e13")
# Test scanning
- f1.scanner = Scanner()
+ scn = Scanner()
+ f1.scanners = [ scn ]
f1.scan()
- assert f1.implicit[f1.scanner][0].path_ == os.path.join("d1", "f1")
- del f1.implicit[f1.scanner]
+ assert f1.implicit[scn][0].path_ == os.path.join("d1", "f1")
+ del f1.implicit[scn]
f1.scan()
assert len(f1.implicit) == 0, f1.implicit
- del f1.scanned[f1.scanner]
+ del f1.scanned[scn]
f1.scan()
- assert f1.implicit[f1.scanner][0].path_ == os.path.join("d1", "f1")
+ assert f1.implicit[scn][0].path_ == os.path.join("d1", "f1")
# Test building a file whose directory is not there yet...
f1 = fs.File(test.workpath("foo/bar/baz/ack"))
diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py
index 9dec623..673ab25 100644
--- a/src/engine/SCons/Node/NodeTests.py
+++ b/src/engine/SCons/Node/NodeTests.py
@@ -259,6 +259,18 @@ class NodeTestCase(unittest.TestCase):
assert node.implicit[3] == [two, three]
assert node.implicit[4] == [three, four, one]
+ def test_scan(self):
+ """Test Scanner functionality"""
+ class DummyScanner:
+ pass
+ ds=DummyScanner()
+ node = SCons.Node.Node()
+ assert node.scanners == [], node.scanners
+ node.scanner_set(ds)
+ assert node.scanners == [ ds ], node.scanners
+ node.scan()
+ assert node.scanned[ds] == 1, node.scanned
+
def test_children(self):
"""Test fetching the "children" of a Node.
"""
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py
index 17bf539..ddcddfb 100644
--- a/src/engine/SCons/Node/__init__.py
+++ b/src/engine/SCons/Node/__init__.py
@@ -60,7 +60,7 @@ class Node:
self.implicit = {} # implicit (scanned) dependencies
self.parents = []
self.builder = None
- self.scanner = None
+ self.scanners = []
self.scanned = {}
self.env = None
self.state = None
@@ -103,10 +103,12 @@ class Node:
return Adapter(self)
def scanner_set(self, scanner):
- self.scanner = scanner
+ if not scanner in self.scanners:
+ self.scanners.append(scanner)
def scan(self):
- self.scanned[self.scanner] = 1
+ for scn in self.scanners:
+ self.scanned[scn] = 1
def env_set(self, env, safe=0):
if safe and self.env:
diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py
index 589aef6..8ad7e00 100644
--- a/src/engine/SCons/Scanner/C.py
+++ b/src/engine/SCons/Scanner/C.py
@@ -106,10 +106,9 @@ def scan(filename, env, args = [SCons.Node.FS.default_fs, ()]):
dir = os.path.dirname(filename)
if dir:
- source_dir = (fs.Dir(dir),)
+ source_dir = (fs.Dir(dir, fs.Top),)
else:
- source_dir = ()
-
+ source_dir = ( fs.Top, )
return (SCons.Util.find_files(angle_includes, cpppath + source_dir,
fs.File)
+ SCons.Util.find_files(quote_includes, source_dir + cpppath,
diff --git a/src/engine/SCons/Scanner/CTests.py b/src/engine/SCons/Scanner/CTests.py
index ca4abf0..bc30fa4 100644
--- a/src/engine/SCons/Scanner/CTests.py
+++ b/src/engine/SCons/Scanner/CTests.py
@@ -206,7 +206,7 @@ class CScannerTestCase7(unittest.TestCase):
dict = {}
dict[s1] = 777
assert dict[s2] == 777
-
+
class CScannerTestCase8(unittest.TestCase):
def runTest(self):
fs = SCons.Node.FS.FS(test.workpath(''))
@@ -220,6 +220,27 @@ class CScannerTestCase8(unittest.TestCase):
deps_match(self, deps1, headers1)
deps_match(self, deps2, headers2)
+class CScannerTestCase9(unittest.TestCase):
+ def runTest(self):
+ fs = SCons.Node.FS.FS(test.workpath(''))
+ s = SCons.Scanner.C.CScan(fs=fs)
+ env = DummyEnvironment([])
+ test.write('fa.h','\n')
+ deps = s.instance(env).scan('fa.cpp', None)
+ deps_match(self, deps, [ 'fa.h' ])
+ test.unlink('fa.h')
+
+class CScannerTestCase10(unittest.TestCase):
+ def runTest(self):
+ fs = SCons.Node.FS.FS(test.workpath(''))
+ fs.chdir(fs.Dir('include'))
+ s = SCons.Scanner.C.CScan(fs=fs)
+ env = DummyEnvironment([])
+ test.write('include/fa.cpp', test.read('fa.cpp'))
+ deps = s.instance(env).scan('include/fa.cpp', None)
+ deps_match(self, deps, [ 'include/fa.h', 'include/fb.h' ])
+ test.unlink('include/fa.cpp')
+
def suite():
suite = unittest.TestSuite()
suite.addTest(CScannerTestCase1())
@@ -230,6 +251,8 @@ def suite():
suite.addTest(CScannerTestCase6())
suite.addTest(CScannerTestCase7())
suite.addTest(CScannerTestCase8())
+ suite.addTest(CScannerTestCase9())
+ suite.addTest(CScannerTestCase10())
return suite
if __name__ == "__main__":