summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2004-06-15 12:54:45 (GMT)
committerSteven Knight <knight@baldmt.com>2004-06-15 12:54:45 (GMT)
commitf0bf250b85abbe23faa7eeff0e53beb0613a2c6f (patch)
tree96cf9c87582bafacbe731704f4f10fbd8e34d331 /src
parenta0d7c6333aeb9b6f2848ea3c90662f91f7f8ac0e (diff)
downloadSCons-f0bf250b85abbe23faa7eeff0e53beb0613a2c6f.zip
SCons-f0bf250b85abbe23faa7eeff0e53beb0613a2c6f.tar.gz
SCons-f0bf250b85abbe23faa7eeff0e53beb0613a2c6f.tar.bz2
Add an option to not save the --debug=explain information.
Diffstat (limited to 'src')
-rw-r--r--src/CHANGES.txt5
-rw-r--r--src/engine/SCons/Node/FS.py29
-rw-r--r--src/engine/SCons/Node/FSTests.py50
-rw-r--r--src/engine/SCons/Node/NodeTests.py14
-rw-r--r--src/engine/SCons/Node/__init__.py32
-rw-r--r--src/engine/SCons/SConsign.py11
-rw-r--r--src/engine/SCons/SConsignTests.py9
-rw-r--r--src/engine/SCons/Script/__init__.py13
8 files changed, 133 insertions, 30 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 704d7b7..ee75857 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -94,6 +94,11 @@ RELEASE 0.96 - XXX
- Add a --debug=explain option that reports the reason(s) why SCons
thinks it must rebuild something.
+ - Add --save-explain-info and SetOption('save_explain_info') options
+ to control whether the --debug=explain information is saved in
+ the .sconsign file(s). Not saving this information can improve
+ performance and save memory usage.
+
- Add support for functions that return platform-independent Actions
to Chmod(), Copy(), Delete(), Mkdir(), Move() and Touch() files
and/or directories. Like any other Actions, the returned Action
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index 23cf8a7..2f115c9 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -1385,7 +1385,34 @@ class File(Base):
return 0
def store_info(self, obj):
- self.dir.sconsign().set_entry(self.name, obj)
+ # Merge our build information into the already-stored entry.
+ # This accomodates "chained builds" where a file that's a target
+ # in one build (SConstruct file) is a source in a different build.
+ # See test/chained-build.py for the use case.
+ entry = self.get_stored_info()
+ if not SCons.Node.Save_Explain_Info:
+ # If we're not saving explanation info, wipe out any that
+ # might be in the already-stored entry.
+ #
+ # XXX This is kind of bad that we're naming attributes that
+ # are really controlled in Node/__init__.py. It would be
+ # good to find a way to move this logic there in some way
+ # that still accounts for the fact that not all Node classes
+ # need or use this information.
+ attributes = [
+ 'bsources', 'bsourcesigs',
+ 'bdepends', 'bdependsigs',
+ 'bimplicit', 'bimplicitsigs',
+ 'bact', 'bactsig',
+ ]
+ for attr in attributes:
+ try:
+ delattr(entry, attr)
+ except AttributeError:
+ pass
+ for key, val in obj.__dict__.items():
+ entry.__dict__[key] = val
+ sconsign = self.dir.sconsign().set_entry(self.name, entry)
def get_stored_info(self):
try:
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py
index d9ffd83..d4137c1 100644
--- a/src/engine/SCons/Node/FSTests.py
+++ b/src/engine/SCons/Node/FSTests.py
@@ -1969,6 +1969,55 @@ class SaveStringsTestCase(unittest.TestCase):
expect = map(os.path.normpath, ['src/f', 'd1/f', 'd0/b', 'd1/b'])
assert s == expect, s
+class SaveExplainInfoTestCase(unittest.TestCase):
+ def runTest(self):
+ """Test how we store --debug=explain info."""
+ test=TestCmd(workdir='')
+ fs = SCons.Node.FS.FS(test.workpath('fs'))
+ f = fs.File('file')
+
+ class BInfo:
+ pass
+
+ bi = BInfo()
+ bi.bact = 'file bact'
+ bi.arg1 = 'file arg1'
+ f.store_info(bi)
+
+ i = f.get_stored_info()
+ assert i.bact == 'file bact', i.arg1
+ assert i.arg1 == 'file arg1', i.arg1
+ assert not hasattr(i, 'arg2'), i.bact
+ assert not hasattr(i, 'arg3'), i.bact
+
+ save_value = SCons.Node.Save_Explain_Info
+ try:
+ SCons.Node.Save_Explain_Info = 1
+
+ bi = BInfo()
+ bi.arg2 = 'file arg2'
+ f.store_info(bi)
+
+ i = f.get_stored_info()
+ assert i.bact == 'file bact', i.arg1
+ assert i.arg1 == 'file arg1', i.arg1
+ assert i.arg2 == 'file arg2', i.arg2
+ assert not hasattr(i, 'arg3'), i.bact
+
+ SCons.Node.Save_Explain_Info = 0
+
+ bi = BInfo()
+ bi.arg3 = 'file arg3'
+ f.store_info(bi)
+
+ i = f.get_stored_info()
+ assert not hasattr(i, 'bact'), i.bact
+ assert i.arg1 == 'file arg1', i.arg1
+ assert i.arg2 == 'file arg2', i.arg2
+ assert i.arg3 == 'file arg3', i.arg2
+ finally:
+ SCons.Node.Save_Explain_Info = save_value
+
if __name__ == "__main__":
@@ -1989,5 +2038,6 @@ if __name__ == "__main__":
suite.addTest(postprocessTestCase())
suite.addTest(SpecialAttrTestCase())
suite.addTest(SaveStringsTestCase())
+ suite.addTest(SaveExplainInfoTestCase())
if not unittest.TextTestRunner().run(suite).wasSuccessful():
sys.exit(1)
diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py
index 4c7d9c2..cd7aa18 100644
--- a/src/engine/SCons/Node/NodeTests.py
+++ b/src/engine/SCons/Node/NodeTests.py
@@ -396,6 +396,7 @@ class NodeTestCase(unittest.TestCase):
def collect(self, args):
return reduce(lambda x, y: x+y, args, self.val)
self.module = M(val)
+
node = SCons.Node.Node()
binfo = node.gen_binfo(Calculator(666))
assert isinstance(binfo, SCons.Node.BuildInfo), binfo
@@ -407,6 +408,19 @@ class NodeTestCase(unittest.TestCase):
assert hasattr(binfo, 'bimplicitsigs')
assert binfo.bsig == 666, binfo.bsig
+ SCons.Node.Save_Explain_Info = 0
+
+ node = SCons.Node.Node()
+ binfo = node.gen_binfo(Calculator(777))
+ assert isinstance(binfo, SCons.Node.BuildInfo), binfo
+ assert not hasattr(binfo, 'bsources')
+ assert not hasattr(binfo, 'bsourcesigs')
+ assert not hasattr(binfo, 'bdepends')
+ assert not hasattr(binfo, 'bdependsigs')
+ assert not hasattr(binfo, 'bimplicit')
+ assert not hasattr(binfo, 'bimplicitsigs')
+ assert binfo.bsig == 777, binfo.bsig
+
def test_explain(self):
"""Test explaining why a Node must be rebuilt
"""
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py
index ba4cbca..64226a6 100644
--- a/src/engine/SCons/Node/__init__.py
+++ b/src/engine/SCons/Node/__init__.py
@@ -76,6 +76,9 @@ implicit_deps_unchanged = 0
# controls whether the cached implicit deps are ignored:
implicit_deps_changed = 0
+# controls whether --debug=explain info is saved in Nodes:
+Save_Explain_Info = 1
+
# A variable that can be set to an interface-specific function be called
# to annotate a Node with information about its creation.
def do_nothing(node): pass
@@ -542,21 +545,26 @@ class Node:
dependsigs = map(calc_signature, depends)
implicitsigs = map(calc_signature, implicit)
- binfo.bsources = map(str, sources)
- binfo.bdepends = map(str, depends)
- binfo.bimplicit = map(str, implicit)
-
- binfo.bsourcesigs = sourcesigs
- binfo.bdependsigs = dependsigs
- binfo.bimplicitsigs = implicitsigs
-
sigs = sourcesigs + dependsigs + implicitsigs
- if self.has_builder():
+ has_builder = self.has_builder()
+ if has_builder:
executor = self.get_executor()
- binfo.bact = str(executor)
- binfo.bactsig = calc.module.signature(executor)
- sigs.append(binfo.bactsig)
+ bactsig = calc.module.signature(executor)
+ sigs.append(bactsig)
+
+ if Save_Explain_Info:
+ binfo.bsources = map(str, sources)
+ binfo.bdepends = map(str, depends)
+ binfo.bimplicit = map(str, implicit)
+
+ binfo.bsourcesigs = sourcesigs
+ binfo.bdependsigs = dependsigs
+ binfo.bimplicitsigs = implicitsigs
+
+ if has_builder:
+ binfo.bact = str(executor)
+ binfo.bactsig = calc.module.signature(executor)
binfo.bsig = calc.module.collect(filter(None, sigs))
diff --git a/src/engine/SCons/SConsign.py b/src/engine/SCons/SConsign.py
index c97f1b6..b7b06fe 100644
--- a/src/engine/SCons/SConsign.py
+++ b/src/engine/SCons/SConsign.py
@@ -68,8 +68,7 @@ class Base:
def get_entry(self, filename):
"""
- Create an entry for the filename and return it, or if one already exists,
- then return it.
+ Fetch the specified entry attribute.
"""
return self.entries[filename]
@@ -77,13 +76,7 @@ class Base:
"""
Set the entry.
"""
- try:
- entry = self.entries[filename]
- except KeyError:
- self.entries[filename] = obj
- else:
- for key, val in obj.__dict__.items():
- entry.__dict__[key] = val
+ self.entries[filename] = obj
self.dirty = 1
class DB(Base):
diff --git a/src/engine/SCons/SConsignTests.py b/src/engine/SCons/SConsignTests.py
index 79f4387..16ef816 100644
--- a/src/engine/SCons/SConsignTests.py
+++ b/src/engine/SCons/SConsignTests.py
@@ -47,8 +47,9 @@ class BaseTestCase(unittest.TestCase):
aaa = BuildInfo('aaa')
bbb = BuildInfo('bbb')
+ bbb.arg1 = 'bbb arg1'
ccc = BuildInfo('ccc')
- ccc.arg = 'ccc arg'
+ ccc.arg2 = 'ccc arg2'
f = SCons.SConsign.Base()
f.set_entry('aaa', aaa)
@@ -61,12 +62,14 @@ class BaseTestCase(unittest.TestCase):
e = f.get_entry('bbb')
assert e == bbb, e
assert e.name == 'bbb', e.name
- assert not hasattr(e, 'arg'), e
+ assert e.arg1 == 'bbb arg1', e.arg1
+ assert not hasattr(e, 'arg2'), e
f.set_entry('bbb', ccc)
e = f.get_entry('bbb')
assert e.name == 'ccc', e.name
- assert e.arg == 'ccc arg', e.arg
+ assert not hasattr(e, 'arg1'), e
+ assert e.arg2 == 'ccc arg2', e.arg1
ddd = BuildInfo('ddd')
eee = BuildInfo('eee')
diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py
index d4650d2..835409e 100644
--- a/src/engine/SCons/Script/__init__.py
+++ b/src/engine/SCons/Script/__init__.py
@@ -528,7 +528,6 @@ class OptParser(OptionParser):
def opt_debug(option, opt, value, parser, debug_options=debug_options):
if value in debug_options:
- #setattr(parser.values, 'debug', value)
parser.values.debug = value
else:
raise OptionValueError("Warning: %s is not a valid debug type" % value)
@@ -541,7 +540,6 @@ class OptParser(OptionParser):
def opt_duplicate(option, opt, value, parser):
if not value in SCons.Node.FS.Valid_Duplicates:
raise OptionValueError("`%s' is not a valid duplication style." % value)
- #setattr(parser.values, 'duplicate', value)
parser.values.duplicate = value
# Set the duplicate style right away so it can affect linking
# of SConscript files.
@@ -584,7 +582,6 @@ class OptParser(OptionParser):
def opt_j(option, opt, value, parser):
value = int(value)
- #setattr(parser.values, 'num_jobs', value)
parser.values.num_jobs = value
self.add_option('-j', '--jobs', action="callback", type="int",
callback=opt_j, metavar="N",
@@ -627,6 +624,10 @@ class OptParser(OptionParser):
self.add_option('-s', '--silent', '--quiet', action="store_true",
default=0, help="Don't print commands.")
+ self.add_option('--save-explain-info', type="int", action="store",
+ dest='save_explain_info', metavar='0|1',
+ help="(Don't) save --debug=explain information")
+
self.add_option('-u', '--up', '--search-up', action="store_const",
dest="climb_up", default=0, const=1,
help="Search up directory tree for SConstruct, "
@@ -734,7 +735,8 @@ class SConscriptSettableOptions:
'max_drift':SCons.Sig.default_max_drift,
'implicit_cache':0,
'clean':0,
- 'duplicate':'hard-soft-copy'}
+ 'duplicate':'hard-soft-copy',
+ 'save_explain_info':1}
def get(self, name):
if not self.settable.has_key(name):
@@ -770,7 +772,7 @@ class SConscriptSettableOptions:
# Set the duplicate stye right away so it can affect linking
# of SConscript files.
SCons.Node.FS.set_duplicate(value)
-
+
self.settable[name] = value
@@ -947,6 +949,7 @@ def _main(args, parser):
# that are SConscript settable:
SCons.Node.implicit_cache = ssoptions.get('implicit_cache')
SCons.Node.FS.set_duplicate(ssoptions.get('duplicate'))
+ SCons.Node.Save_Explain_Info = ssoptions.get('save_explain_info') or print_explanations
lookup_top = None
if targets: