.RE
.fi
..
-.TH SCONS 1 "June 2003"
+.TH SCONS 1 "September 2003"
.SH NAME
scons \- a software construction tool
.SH SYNOPSIS
Return(["foo", "bar"])
.EE
+.TP
+.RI SConsignFile([ file ])
+This tells
+.B scons
+to store all file signatures
+in the specified
+.IR file .
+If the
+.I file
+is omitted,
+.B .sconsign.dbm
+is used by default.
+If
+.I file
+is not an absolute path name,
+the file is placed in the same directory as the top-level
+.B SConstruct
+file.
+Examples:
+
+.ES
+# Stores signatures in ".sconsign.dbm"
+# in the top-level SConstruct directory.
+SConsignFile()
+
+# Stores signatures in the file "etc/scons-signatures"
+# relative to the top-level SConstruct directory.
+SConsignFile("etc/scons-signatures")
+
+# Stores signatures in the specified absolute file name.
+SConsignFile("/home/me/SCons/signatures")
+.EE
+
.TP
.RI SetOption( name ", " value )
This function provides a way to set a select subset of the scons command
.RE
.fi
..
-.TH SCONSIGN 1 "July 2003"
+.TH SCONSIGN 1 "September 2003"
.SH NAME
sconsign \- print SCons .sconsign file information
.SH SYNOPSIS
If the entry has no implicit dependencies,
the lines are simply omitted.
+By default,
+.B sconsign
+assumes that any
+.I file
+arguments that end with a
+.B .dbm
+suffix contains
+signature entries for
+more than one directory
+(that is,
+was specified by the
+.B SConsignFile ()
+function).
+Any
+.I file
+argument that does not end in
+.B .dbm
+is assumed to be a traditional
+.B .sconsign
+file containing the signature entries
+for a single directory.
+An explicit format
+may be specified using the
+.B -f
+or
+.B --file=
+options.
+
.SH OPTIONS
Various options control what information is printed
and the format:
-.TP
--b
-Ignored for compatibility with non-GNU versions of
-.BR make.
-
.TP
-b, --bsig
Prints the build signature (bsig) information
for all entries or the specified entries.
.TP
--e entry, --entry=entry
-Prints information about only the specified entry.
+-d DIRECTORY, --dir=DIRECTORY
+When the signatures are being
+read from a
+.B .dbm
+file, or the
+.B -f dbm
+or
+.B --format=dbm
+options are used,
+prints information about
+only the signatures
+for entries in the specified
+.IR DIRECTORY .
+
+.TP
+-e ENTRY, --entry=ENTRY
+Prints information about only the specified
+.IR ENTRY .
Multiple -e options may be used,
in which case information about each
-entry is printed in the order in which the
+.I ENTRY
+is printed in the order in which the
options are specified on the command line.
+.TP
+-f FORMAT, --format=FORMAT
+The file(s) to be printed
+are in the specified
+.IR FORMAT .
+Legal values are
+.B dbm
+(the DBM format used
+when the
+.BR SConsignFile ()
+function is used)
+or
+.B sconsign
+(the default format
+used for an individual
+.B .sconsign
+file in each directory).
+
.TP
-h, --help
Prints a help message and exits.
- Add support for CCVERSION and CXXVERSION variables for a number
of C and C++ compilers.
+ From Stephen Kennedy:
+
+ - Add support for a configurable global .sconsign.dbm file which
+ can be used to avoid cluttering each directory with an individual
+ .sconsign file.
+
From Steven Knight:
- The -Q option suppressed too many messages; fix it so that it only
creating it first if necessary."""
if not self._sconsign:
import SCons.Sig
- self._sconsign = SCons.Sig.SConsignFile(self)
+ self._sconsign = SCons.Sig.SConsignForDirectory(self)
return self._sconsign
def srcnode(self):
import SCons.Platform
import SCons.SConf
import SCons.Script
-import SCons.Tool
import SCons.Util
import SCons.Options
import SCons
def GetOption(name):
return SCons.Script.ssoptions.get(name)
+def SConsignFile(name=".sconsign.dbm"):
+ import SCons.Sig
+ if not os.path.isabs(name):
+ sd = str(SCons.Node.FS.default_fs.SConstruct_dir)
+ name = os.path.join(sd, name)
+ SCons.Sig.SConsignFile(name)
+
def BuildDefaultGlobals():
"""
Create a dictionary containing all the default globals for
globals['Return'] = Return
globals['SConscript'] = SConscript
globals['SConscriptChdir'] = SConscriptChdir
+ globals['SConsignFile'] = SConsignFile
globals['Scanner'] = SCons.Scanner.Base
globals['SetBuildSignatureType'] = SetBuildSignatureType
globals['SetCommandHandler'] = SCons.Action.SetCommandHandler
assert f.get('foo') == (3, 1, 2)
assert f.get_implicit('foo') == ['bar']
- f = SCons.Sig._SConsign(None, DummyModule())
+ f = SCons.Sig._SConsign(DummyModule())
f.set_bsig('foo', 1)
assert f.get('foo') == (None, 1, None)
f.set_csig('foo', 2)
assert f.get('foo') == (3, 1, 2)
assert f.get_implicit('foo') == ['bar']
-class SConsignFileTestCase(unittest.TestCase):
+class SConsignDBTestCase(unittest.TestCase):
+
+ def runTest(self):
+ class DummyNode:
+ def __init__(self, path):
+ self.path = path
+ save_SConsign_db = SCons.Sig.SConsign_db
+ SCons.Sig.SConsign_db = {}
+ try:
+ d1 = SCons.Sig.SConsignDB(DummyNode('dir1'))
+ d1.set_timestamp('foo', 1)
+ d1.set_bsig('foo', 2)
+ d1.set_csig('foo', 3)
+ d1.set_timestamp('bar', 4)
+ d1.set_bsig('bar', 5)
+ d1.set_csig('bar', 6)
+ assert d1.get('foo') == (1, 2, 3)
+ assert d1.get('bar') == (4, 5, 6)
+
+ d2 = SCons.Sig.SConsignDB(DummyNode('dir1'))
+ d2.set_timestamp('foo', 7)
+ d2.set_bsig('foo', 8)
+ d2.set_csig('foo', 9)
+ d2.set_timestamp('bar', 10)
+ d2.set_bsig('bar', 11)
+ d2.set_csig('bar', 12)
+ assert d2.get('foo') == (7, 8, 9)
+ assert d2.get('bar') == (10, 11, 12)
+ finally:
+ SCons.Sig.SConsign_db = save_SConsign_db
+
+class SConsignDirFileTestCase(unittest.TestCase):
def runTest(self):
class DummyModule:
class DummyNode:
path = 'not_a_valid_path'
- f = SCons.Sig.SConsignFile(DummyNode(), DummyModule())
+ f = SCons.Sig.SConsignDirFile(DummyNode(), DummyModule())
f.set_bsig('foo', 1)
assert f.get('foo') == (None, 1, None)
f.set_csig('foo', 2)
suite.addTest(CalcTestCase())
suite.addTest(SConsignEntryTestCase())
suite.addTest(_SConsignTestCase())
- suite.addTest(SConsignFileTestCase())
+ suite.addTest(SConsignDBTestCase())
+ suite.addTest(SConsignDirFileTestCase())
return suite
if __name__ == "__main__":
#XXX Get rid of the global array so this becomes re-entrant.
sig_files = []
+SConsign_db = None
+
# 1 means use build signature for derived source files
# 0 means use content signature for derived source files
build_signature = 1
implicit = None
class _SConsign:
-
- def __init__(self, fp=None, module=None):
+ """
+ This is the controlling class for the signatures for the collection of
+ entries associated with a specific directory. The actual directory
+ association will be maintained by a subclass that is specific to
+ the underlying storage method. This class provides a common set of
+ methods for fetching and storing the individual bits of information
+ that make up signature entry.
+ """
+ def __init__(self, module=None):
"""
- fp - file pointer to read entries from
module - the signature module being used
"""
self.entries = {}
self.dirty = 0
- if fp:
- try:
- self.entries = cPickle.load(fp)
- if type(self.entries) is not type({}):
- self.entries = {}
- raise TypeError
- except:
- SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning,
- "Ignoring corrupt .sconsign file: %s"%self.sconsign)
- global sig_files
- sig_files.append(self)
-
# A null .sconsign entry. We define this here so that it will
# be easy to keep this in sync if/whenever we change the type of
# information returned by the get() method, below.
entry.implicit = implicit
self.set_entry(filename, entry)
-class SConsignFile(_SConsign):
+class SConsignDB(_SConsign):
"""
- Encapsulates reading and writing a .sconsign file.
+ A _SConsign subclass that reads and writes signature information
+ from a global .sconsign.dbm file.
"""
+ def __init__(self, dir, module=None):
+ _SConsign.__init__(self, module)
+
+ self.dir = dir
+
+ try:
+ global SConsign_db
+ rawentries = SConsign_db[self.dir.path]
+ except KeyError:
+ pass
+ else:
+ try:
+ self.entries = cPickle.loads(rawentries)
+ if type(self.entries) is not type({}):
+ self.entries = {}
+ raise TypeError
+ except:
+ SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning,
+ "Ignoring corrupt sconsign entry : %s"%self.dir.path)
+
+ global sig_files
+ sig_files.append(self)
+
+ def write(self):
+ if self.dirty:
+ global SConsign_db
+ SConsign_db[self.dir.path] = cPickle.dumps(self.entries, 1)
+ SConsign_db.sync()
+class SConsignDir(_SConsign):
+ def __init__(self, fp=None, module=None):
+ """
+ fp - file pointer to read entries from
+ module - the signature module being used
+ """
+ _SConsign.__init__(self, module)
+
+ if fp:
+ self.entries = cPickle.load(fp)
+ if type(self.entries) is not type({}):
+ self.entries = {}
+ raise TypeError
+
+class SConsignDirFile(SConsignDir):
+ """
+ Encapsulates reading and writing a per-directory .sconsign file.
+ """
def __init__(self, dir, module=None):
"""
dir - the directory for the file
except:
fp = None
- _SConsign.__init__(self, fp, module)
+ try:
+ SConsignDir.__init__(self, fp, module)
+ except:
+ SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning,
+ "Ignoring corrupt .sconsign file: %s"%self.sconsign)
+
+ global sig_files
+ sig_files.append(self)
def write(self):
"""
except:
pass
+SConsignForDirectory = SConsignDirFile
+
+def SConsignFile(name):
+ """
+ Arrange for all signatures to be stored in a global .sconsign.dbm
+ file.
+ """
+ global SConsign_db
+ if SConsign_db is None:
+ import anydbm
+ SConsign_db = anydbm.open(name, "c")
+
+ global SConsignForDirectory
+ SConsignForDirectory = SConsignDB
+
class Calculator:
"""
Encapsulates signature calculations and .sconsign file generating
# END STANDARD SCons SCRIPT HEADER
##############################################################################
+PF_bsig = 0x1
+PF_csig = 0x2
+PF_timestamp = 0x4
+PF_implicit = 0x8
+PF_all = PF_bsig | PF_csig | PF_timestamp | PF_implicit
+
+Do_Func = None
+Print_Directories = []
+Print_Entries = []
+Print_Flags = 0
+Verbose = 0
+Readable = 0
+
+def field(name, pf, val):
+ if Print_Flags & pf:
+ if Verbose:
+ sep = "\n " + name + ": "
+ else:
+ sep = " "
+ return sep + str(val)
+ else:
+ return ""
+
+def printfield(name, entry):
+ if Readable and entry.timestamp:
+ ts = "'" + time.ctime(entry.timestamp) + "'"
+ else:
+ ts = entry.timestamp
+ timestamp = field("timestamp", PF_timestamp, ts)
+ bsig = field("bsig", PF_bsig, entry.bsig)
+ csig = field("csig", PF_csig, entry.csig)
+ print name + ":" + timestamp + bsig + csig
+ if Print_Flags & PF_implicit and entry.implicit:
+ if Verbose:
+ print " implicit:"
+ for i in entry.implicit:
+ print " %s" % i
+
+def printentries(entries):
+ if Print_Entries:
+ for name in Print_Entries:
+ try:
+ entry = entries[name]
+ except KeyError:
+ sys.stderr.write("sconsign: no entry `%s' in `%s'\n" % (name, args[0]))
+ else:
+ printfield(name, entry)
+ else:
+ for name, e in entries.items():
+ printfield(name, e)
+
+import SCons.Sig
+
+def Do_SConsignDB(name):
+ import anydbm
+ import cPickle
+ try:
+ open(name, 'rb')
+ except (IOError, OSError), e:
+ sys.stderr.write("sconsign: %s\n" % (e))
+ return
+ try:
+ db = anydbm.open(name, "r")
+ except anydbm.error, e:
+ sys.stderr.write("sconsign: ignoring invalid .sconsign.dbm file `%s': %s\n" % (name, e))
+ return
+ if Print_Directories:
+ for dir in Print_Directories:
+ try:
+ val = db[dir]
+ except KeyError:
+ sys.stderr.write("sconsign: no dir `%s' in `%s'\n" % (dir, args[0]))
+ else:
+ entries = cPickle.loads(val)
+ print '=== ' + dir + ':'
+ printentries(entries)
+ else:
+ keys = db.keys()
+ keys.sort()
+ for dir in keys:
+ entries = cPickle.loads(db[dir])
+ print '=== ' + dir + ':'
+ printentries(entries)
+
+def Do_SConsignDir(name):
+ try:
+ fp = open(name, 'rb')
+ except (IOError, OSError), e:
+ sys.stderr.write("sconsign: %s\n" % (e))
+ return
+ try:
+ sconsign = SCons.Sig.SConsignDir(fp)
+ except:
+ sys.stderr.write("sconsign: ignoring invalid .sconsign file `%s'\n" % name)
+ return
+ printentries(sconsign.entries)
+
+Function_Map = {'dbm' : Do_SConsignDB,
+ 'sconsign' : Do_SConsignDir}
+
+##############################################################################
+
import getopt
helpstr = """\
Options:
-b, --bsig Print build signature information.
-c, --csig Print content signature information.
- -e, --entry ENTRY Print only info about ENTRY.
+ -d DIR, --dir=DIR Print only info about DIR.
+ -e ENTRY, --entry=ENTRY Print only info about ENTRY.
+ -f FORMAT, --format=FORMAT FILE is in the specified FORMAT.
-h, --help Print this message and exit.
-i, --implicit Print implicit dependency information.
-r, --readable Print timestamps in human-readable form.
-v, --verbose Verbose, describe each field.
"""
-opts, args = getopt.getopt(sys.argv[1:], "bce:hirtv",
- ['bsig', 'csig', 'entry=', 'help', 'implicit',
+opts, args = getopt.getopt(sys.argv[1:], "bcd:e:f:hirtv",
+ ['bsig', 'csig', 'dir=', 'entry=',
+ 'format=', 'help', 'implicit',
'readable', 'timestamp', 'verbose'])
-pf_bsig = 0x1
-pf_csig = 0x2
-pf_timestamp = 0x4
-pf_implicit = 0x8
-pf_all = pf_bsig | pf_csig | pf_timestamp | pf_implicit
-
-entries = []
-printflags = 0
-verbose = 0
-readable = 0
-
for o, a in opts:
if o in ('-b', '--bsig'):
- printflags = printflags | pf_bsig
+ Print_Flags = Print_Flags | PF_bsig
elif o in ('-c', '--csig'):
- printflags = printflags | pf_csig
+ Print_Flags = Print_Flags | PF_csig
+ elif o in ('-d', '--dir'):
+ Print_Directories.append(a)
elif o in ('-e', '--entry'):
- entries.append(a)
+ Print_Entries.append(a)
+ elif o in ('-f', '--format'):
+ try:
+ Do_Func = Function_Map[a]
+ except KeyError:
+ sys.stderr.write("sconsign: illegal file format `%s'\n" % a)
+ print helpstr
+ sys.exit(2)
elif o in ('-h', '--help'):
print helpstr
sys.exit(0)
elif o in ('-i', '--implicit'):
- printflags = printflags | pf_implicit
+ Print_Flags = Print_Flags | PF_implicit
elif o in ('-r', '--readable'):
- readable = 1
+ Readable = 1
elif o in ('-t', '--timestamp'):
- printflags = printflags | pf_timestamp
+ Print_Flags = Print_Flags | PF_timestamp
elif o in ('-v', '--verbose'):
- verbose = 1
+ Verbose = 1
-if printflags == 0:
- printflags = pf_all
-
-def field(name, pf, val):
- if printflags & pf:
- if verbose:
- sep = "\n " + name + ": "
- else:
- sep = " "
- return sep + str(val)
- else:
- return ""
-
-def printfield(name, entry):
- if readable and entry.timestamp:
- ts = "'" + time.ctime(entry.timestamp) + "'"
- else:
- ts = entry.timestamp
- timestamp = field("timestamp", pf_timestamp, ts)
- bsig = field("bsig", pf_bsig, entry.bsig)
- csig = field("csig", pf_csig, entry.csig)
- print name + ":" + timestamp + bsig + csig
- if printflags & pf_implicit and entry.implicit:
- if verbose:
- print " implicit:"
- for i in entry.implicit:
- print " %s" % i
-
-import SCons.Sig
-
-def do_sconsign(fp):
- sconsign = SCons.Sig._SConsign(fp)
- if entries:
- for name in entries:
- try:
- entry = sconsign.entries[name]
- except KeyError:
- sys.stderr.write("sconsign: no entry `%s' in `%s'\n" % (name, args[0]))
- else:
- printfield(name, entry)
- else:
- for name, e in sconsign.entries.items():
- printfield(name, e)
-
+if Print_Flags == 0:
+ Print_Flags = PF_all
for a in args:
- do_sconsign(open(a, 'rb'))
+ if Do_Func:
+ Do_Func(a)
+ elif a[-4:] == '.dbm':
+ Do_SConsignDB(a)
+ else:
+ Do_SConsignDir(a)
+
+sys.exit(0)
--- /dev/null
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import TestSCons
+import os.path
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+test.subdir('work1', ['work1', 'subdir'])
+test.subdir('work2', ['work2', 'subdir'])
+
+test.write('build.py', r"""
+import sys
+contents = open(sys.argv[2], 'rb').read()
+file = open(sys.argv[1], 'wb')
+file.write(contents)
+file.close()
+""")
+
+#
+test.write(['work1', 'SConstruct'], """
+SConsignFile()
+B = Builder(action = "%s ../build.py $TARGETS $SOURCES")
+env = Environment(BUILDERS = { 'B' : B })
+env.B(target = 'f1.out', source = 'f1.in')
+env.B(target = 'f2.out', source = 'f2.in')
+env.B(target = 'subdir/f3.out', source = 'subdir/f3.in')
+env.B(target = 'subdir/f4.out', source = 'subdir/f4.in')
+""" % python)
+
+test.write(['work1', 'f1.in'], "work1/f1.in\n")
+test.write(['work1', 'f2.in'], "work1/f2.in\n")
+test.write(['work1', 'subdir', 'f3.in'], "work1/subdir/f3.in\n")
+test.write(['work1', 'subdir', 'f4.in'], "work1/subdir/f4.in\n")
+
+test.run(chdir = 'work1')
+
+test.fail_test(not os.path.exists(test.workpath('work1', '.sconsign.dbm')))
+test.fail_test(os.path.exists(test.workpath('work1', '.sconsign')))
+test.fail_test(os.path.exists(test.workpath('work1', 'subdir', '.sconsign')))
+
+test.fail_test(test.read(['work1', 'f1.out']) != "work1/f1.in\n")
+test.fail_test(test.read(['work1', 'f2.out']) != "work1/f2.in\n")
+test.fail_test(test.read(['work1', 'subdir', 'f3.out']) != "work1/subdir/f3.in\n")
+test.fail_test(test.read(['work1', 'subdir', 'f4.out']) != "work1/subdir/f4.in\n")
+
+test.up_to_date(chdir = 'work1', arguments = '.')
+
+test.fail_test(not os.path.exists(test.workpath('work1', '.sconsign.dbm')))
+test.fail_test(os.path.exists(test.workpath('work1', '.sconsign')))
+test.fail_test(os.path.exists(test.workpath('work1', 'subdir', '.sconsign')))
+
+#
+test.write(['work2', 'SConstruct'], """
+SConsignFile('my_sconsign')
+B = Builder(action = "%s ../build.py $TARGETS $SOURCES")
+env = Environment(BUILDERS = { 'B' : B })
+env.B(target = 'f5.out', source = 'f5.in')
+env.B(target = 'f6.out', source = 'f6.in')
+env.B(target = 'subdir/f7.out', source = 'subdir/f7.in')
+env.B(target = 'subdir/f8.out', source = 'subdir/f8.in')
+""" % python)
+
+test.write(['work2', 'f5.in'], "work2/f5.in\n")
+test.write(['work2', 'f6.in'], "work2/f6.in\n")
+test.write(['work2', 'subdir', 'f7.in'], "work2/subdir/f7.in\n")
+test.write(['work2', 'subdir', 'f8.in'], "work2/subdir/f8.in\n")
+
+test.run(chdir = 'work2')
+
+test.fail_test(not os.path.exists(test.workpath('work2', 'my_sconsign')))
+test.fail_test(os.path.exists(test.workpath('work2', '.sconsign.dbm')))
+test.fail_test(os.path.exists(test.workpath('work2', '.sconsign')))
+test.fail_test(os.path.exists(test.workpath('work2', 'subdir', '.sconsign')))
+
+test.fail_test(test.read(['work2', 'f5.out']) != "work2/f5.in\n")
+test.fail_test(test.read(['work2', 'f6.out']) != "work2/f6.in\n")
+test.fail_test(test.read(['work2', 'subdir', 'f7.out']) != "work2/subdir/f7.in\n")
+test.fail_test(test.read(['work2', 'subdir', 'f8.out']) != "work2/subdir/f8.in\n")
+
+test.up_to_date(chdir = 'work2', arguments = '.')
+
+test.fail_test(not os.path.exists(test.workpath('work2', 'my_sconsign')))
+test.fail_test(os.path.exists(test.workpath('work2', '.sconsign.dbm')))
+test.fail_test(os.path.exists(test.workpath('work2', '.sconsign')))
+test.fail_test(os.path.exists(test.workpath('work2', 'subdir', '.sconsign')))
+
+test.pass_test()
import os.path
import string
+import time
import TestCmd
import TestSCons
test = TestSCons.TestSCons(match = TestCmd.match_re)
-test.subdir('sub1', 'sub2')
-test.write('SConstruct', """
+
+
+test.subdir('work1', ['work1', 'sub1'], ['work1', 'sub2'],
+ 'work2', ['work2', 'sub1'], ['work2', 'sub2'])
+
+test.write(['work1', 'SConstruct'], """
env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj')
env1.Program('sub1/hello.c')
env2 = env1.Copy(CPPPATH = ['sub2'])
env2.Program('sub2/hello.c')
""")
-test.write(['sub1', 'hello.c'], r"""\
+test.write(['work1', 'sub1', 'hello.c'], r"""\
int
main(int argc, char *argv[])
{
}
""")
-test.write(['sub2', 'hello.c'], r"""\
+test.write(['work1', 'sub2', 'hello.c'], r"""\
#include <inc1.h>
#include <inc2.h>
int
}
""")
-test.write(['sub2', 'inc1.h'], r"""\
+test.write(['work1', 'sub2', 'inc1.h'], r"""\
#define STRING1 "inc1.h"
""")
-test.write(['sub2', 'inc2.h'], r"""\
+test.write(['work1', 'sub2', 'inc2.h'], r"""\
#define STRING2 "inc2.h"
""")
-test.run(arguments = '--implicit-cache .')
+test.run(chdir = 'work1', arguments = '--implicit-cache .')
test.run(interpreter = TestSCons.python,
program = sconsign,
- arguments = "sub1/.sconsign",
+ arguments = "work1/sub1/.sconsign",
stdout = """\
hello.exe: None \S+ None
hello.obj: None \S+ None
test.run(interpreter = TestSCons.python,
program = sconsign,
- arguments = "-v sub1/.sconsign",
+ arguments = "-v work1/sub1/.sconsign",
stdout = """\
hello.exe:
timestamp: None
test.run(interpreter = TestSCons.python,
program = sconsign,
- arguments = "-b -v sub1/.sconsign",
+ arguments = "-b -v work1/sub1/.sconsign",
stdout = """\
hello.exe:
bsig: \S+
test.run(interpreter = TestSCons.python,
program = sconsign,
- arguments = "-c -v sub1/.sconsign",
+ arguments = "-c -v work1/sub1/.sconsign",
stdout = """\
hello.exe:
csig: None
test.run(interpreter = TestSCons.python,
program = sconsign,
- arguments = "-e hello.obj sub1/.sconsign",
+ arguments = "-e hello.obj work1/sub1/.sconsign",
stdout = """\
hello.obj: None \S+ None
""")
test.run(interpreter = TestSCons.python,
program = sconsign,
- arguments = "-e hello.obj -e hello.exe -e hello.obj sub1/.sconsign",
+ arguments = "-e hello.obj -e hello.exe -e hello.obj work1/sub1/.sconsign",
stdout = """\
hello.obj: None \S+ None
hello.exe: None \S+ None
test.run(interpreter = TestSCons.python,
program = sconsign,
- arguments = "sub2/.sconsign",
+ arguments = "work1/sub2/.sconsign",
stdout = """\
hello.exe: None \S+ None
hello.obj: None \S+ None
test.run(interpreter = TestSCons.python,
program = sconsign,
- arguments = "-i -v sub2/.sconsign",
+ arguments = "-i -v work1/sub2/.sconsign",
stdout = """\
hello.exe:
hello.obj:
test.run(interpreter = TestSCons.python,
program = sconsign,
- arguments = "-e hello.obj sub2/.sconsign sub1/.sconsign",
+ arguments = "-e hello.obj work1/sub2/.sconsign work1/sub1/.sconsign",
stdout = """\
hello.obj: None \S+ None
%s
""" % (string.replace(os.path.join('sub2', 'inc1.h'), '\\', '\\\\'),
string.replace(os.path.join('sub2', 'inc2.h'), '\\', '\\\\')))
-test.run(arguments = '--clean .')
+test.run(chdir = 'work1', arguments = '--clean .')
-test.write('SConstruct', """
+test.write(['work1', 'SConstruct'], """
SourceSignatures('timestamp')
TargetSignatures('content')
env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj')
env2.Program('sub2/hello.c')
""")
-import time
time.sleep(1)
-test.run(arguments = '. --max-drift=1')
+test.run(chdir = 'work1', arguments = '. --max-drift=1')
test.run(interpreter = TestSCons.python,
program = sconsign,
- arguments = "sub1/.sconsign")
+ arguments = "work1/sub1/.sconsign")
test.fail_test(not sort_match(test, test.stdout(), """\
hello.exe: None \S+ None
test.run(interpreter = TestSCons.python,
program = sconsign,
- arguments = "-r sub1/.sconsign")
+ arguments = "-r work1/sub1/.sconsign")
test.fail_test(not sort_match(test, test.stdout(), """\
hello.exe: None \S+ None
hello.obj: None \S+ None
"""))
+
+##############################################################################
+
+test.write(['work2', 'SConstruct'], """
+SConsignFile()
+env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj')
+env1.Program('sub1/hello.c')
+env2 = env1.Copy(CPPPATH = ['sub2'])
+env2.Program('sub2/hello.c')
+""")
+
+test.write(['work2', 'sub1', 'hello.c'], r"""\
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("sub1/hello.c\n");
+ exit (0);
+}
+""")
+
+test.write(['work2', 'sub2', 'hello.c'], r"""\
+#include <inc1.h>
+#include <inc2.h>
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("sub2/goodbye.c\n");
+ exit (0);
+}
+""")
+
+test.write(['work2', 'sub2', 'inc1.h'], r"""\
+#define STRING1 "inc1.h"
+""")
+
+test.write(['work2', 'sub2', 'inc2.h'], r"""\
+#define STRING2 "inc2.h"
+""")
+
+test.run(chdir = 'work2', arguments = '--implicit-cache .')
+
+test.run(interpreter = TestSCons.python,
+ program = sconsign,
+ arguments = "work2/.sconsign.dbm",
+ stdout = """\
+=== sub1:
+hello.exe: None \S+ None
+hello.obj: None \S+ None
+=== sub2:
+hello.exe: None \S+ None
+hello.obj: None \S+ None
+ %s
+ %s
+""" % (string.replace(os.path.join('sub2', 'inc1.h'), '\\', '\\\\'),
+ string.replace(os.path.join('sub2', 'inc2.h'), '\\', '\\\\')))
+
+test.run(interpreter = TestSCons.python,
+ program = sconsign,
+ arguments = "-v work2/.sconsign.dbm",
+ stdout = """\
+=== sub1:
+hello.exe:
+ timestamp: None
+ bsig: \S+
+ csig: None
+hello.obj:
+ timestamp: None
+ bsig: \S+
+ csig: None
+=== sub2:
+hello.exe:
+ timestamp: None
+ bsig: \S+
+ csig: None
+hello.obj:
+ timestamp: None
+ bsig: \S+
+ csig: None
+ implicit:
+ %s
+ %s
+""" % (string.replace(os.path.join('sub2', 'inc1.h'), '\\', '\\\\'),
+ string.replace(os.path.join('sub2', 'inc2.h'), '\\', '\\\\')))
+
+test.run(interpreter = TestSCons.python,
+ program = sconsign,
+ arguments = "-b -v work2/.sconsign.dbm",
+ stdout = """\
+=== sub1:
+hello.exe:
+ bsig: \S+
+hello.obj:
+ bsig: \S+
+=== sub2:
+hello.exe:
+ bsig: \S+
+hello.obj:
+ bsig: \S+
+""")
+
+test.run(interpreter = TestSCons.python,
+ program = sconsign,
+ arguments = "-c -v work2/.sconsign.dbm",
+ stdout = """\
+=== sub1:
+hello.exe:
+ csig: None
+hello.obj:
+ csig: None
+=== sub2:
+hello.exe:
+ csig: None
+hello.obj:
+ csig: None
+""")
+
+test.run(interpreter = TestSCons.python,
+ program = sconsign,
+ arguments = "-e hello.obj work2/.sconsign.dbm",
+ stdout = """\
+=== sub1:
+hello.obj: None \S+ None
+=== sub2:
+hello.obj: None \S+ None
+ %s
+ %s
+""" % (string.replace(os.path.join('sub2', 'inc1.h'), '\\', '\\\\'),
+ string.replace(os.path.join('sub2', 'inc2.h'), '\\', '\\\\')))
+
+test.run(interpreter = TestSCons.python,
+ program = sconsign,
+ arguments = "-e hello.obj -e hello.exe -e hello.obj work2/.sconsign.dbm",
+ stdout = """\
+=== sub1:
+hello.obj: None \S+ None
+hello.exe: None \S+ None
+hello.obj: None \S+ None
+=== sub2:
+hello.obj: None \S+ None
+ %s
+ %s
+hello.exe: None \S+ None
+hello.obj: None \S+ None
+ %s
+ %s
+""" % (string.replace(os.path.join('sub2', 'inc1.h'), '\\', '\\\\'),
+ string.replace(os.path.join('sub2', 'inc2.h'), '\\', '\\\\'),
+ string.replace(os.path.join('sub2', 'inc1.h'), '\\', '\\\\'),
+ string.replace(os.path.join('sub2', 'inc2.h'), '\\', '\\\\')))
+
+test.run(interpreter = TestSCons.python,
+ program = sconsign,
+ arguments = "-i -v work2/.sconsign.dbm",
+ stdout = """\
+=== sub1:
+hello.exe:
+hello.obj:
+=== sub2:
+hello.exe:
+hello.obj:
+ implicit:
+ %s
+ %s
+""" % (string.replace(os.path.join('sub2', 'inc1.h'), '\\', '\\\\'),
+ string.replace(os.path.join('sub2', 'inc2.h'), '\\', '\\\\')))
+
+test.run(chdir = 'work2', arguments = '--clean .')
+
+test.write(['work2','SConstruct'], """
+SConsignFile('my_sconsign')
+SourceSignatures('timestamp')
+TargetSignatures('content')
+env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj')
+env1.Program('sub1/hello.c')
+env2 = env1.Copy(CPPPATH = ['sub2'])
+env2.Program('sub2/hello.c')
+""")
+
+time.sleep(1)
+
+test.run(chdir = 'work2', arguments = '. --max-drift=1')
+
+test.run(interpreter = TestSCons.python,
+ program = sconsign,
+ arguments = "-d sub1 -f dbm work2/my_sconsign")
+
+test.fail_test(not sort_match(test, test.stdout(), """\
+=== sub1:
+hello.exe: None \S+ None
+hello.obj: None \S+ None
+hello.c: \d+ None \d+
+"""))
+
+test.run(interpreter = TestSCons.python,
+ program = sconsign,
+ arguments = "-r -d sub1 -f dbm work2/my_sconsign")
+
+test.fail_test(not sort_match(test, test.stdout(), """\
+=== sub1:
+hello.exe: None \S+ None
+hello.obj: None \S+ None
+hello.c: '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' None \d+
+"""))
+
+##############################################################################
+
+test.write('bad_sconsign', "bad_sconsign\n")
+
+test.run(interpreter = TestSCons.python,
+ program = sconsign,
+ arguments = "-f dbm no_sconsign",
+ stderr = "sconsign: \[Errno 2\] No such file or directory: 'no_sconsign'\n")
+
+test.run(interpreter = TestSCons.python,
+ program = sconsign,
+ arguments = "-f dbm bad_sconsign",
+ stderr = "sconsign: ignoring invalid .sconsign.dbm file `bad_sconsign': db type could not be determined\n")
+
+test.run(interpreter = TestSCons.python,
+ program = sconsign,
+ arguments = "-f sconsign no_sconsign",
+ stderr = "sconsign: \[Errno 2\] No such file or directory: 'no_sconsign'\n")
+
+test.run(interpreter = TestSCons.python,
+ program = sconsign,
+ arguments = "-f sconsign bad_sconsign",
+ stderr = "sconsign: ignoring invalid .sconsign file `bad_sconsign'\n")
+
+
test.pass_test()