From a7405b2115ba873ade35ebf16ade8736548b9a99 Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Fri, 18 Jul 2003 17:52:21 +0000 Subject: Add a script to print .sconsign file contents. --- HOWTO/new-script.txt | 73 +++++++++++++ SConstruct | 14 ++- debian/rules | 6 ++ doc/SConscript | 40 ++++--- doc/man/sconsign.1 | 131 +++++++++++++++++++++++ gentoo/scons.ebuild.in | 1 + rpm/scons.spec.in | 2 + src/CHANGES.txt | 13 +++ src/engine/SCons/SConfTests.py | 8 +- src/engine/SCons/Sig/SigTests.py | 36 +++++++ src/engine/SCons/Sig/__init__.py | 41 ++++--- src/engine/SCons/Tool/g++.py | 11 +- src/engine/SCons/Tool/gcc.py | 4 +- src/engine/SCons/Tool/gnulink.py | 32 +++++- src/script/MANIFEST.in | 1 + src/script/scons.py | 17 ++- src/script/sconsign.py | 223 +++++++++++++++++++++++++++++++++++++++ src/setup.py | 2 +- test/LINK.py | 2 +- test/LINKFLAGS.py | 2 +- test/sconsign-script.py | 170 +++++++++++++++++++++++++++++ 21 files changed, 772 insertions(+), 57 deletions(-) create mode 100644 HOWTO/new-script.txt create mode 100644 doc/man/sconsign.1 create mode 100644 src/script/sconsign.py create mode 100644 test/sconsign-script.py diff --git a/HOWTO/new-script.txt b/HOWTO/new-script.txt new file mode 100644 index 0000000..8bb5222 --- /dev/null +++ b/HOWTO/new-script.txt @@ -0,0 +1,73 @@ +Steps for adding a new script/utility to the SCons packages. Assume +that you're creating a new man page, too. In the template steps +below, "newscript" is the name of the new script/utility being added. + + New files: + + doc/man/newscript.1 + + New man page; use an existing one as a template. + + src/script/newscript.py + + The new script itself. + + test/*.py + + Appropriate tests for the new script. + + Modified files: + + SConstruct + + In the "scons_script" package description: + + Add "newscript" : "newscript.py" to the "filemap" + dictionary. + + In the "scons" package description: + + Add "newscript.1" to the "files" list. + + Add "newscript.1" : "../doc/man/newscript.1" to the + "filemap" dictionary. + + Add "newscript" to the scripts[] list + + debian/rules + + Add: + + rm -f debian/scons/usr/bin/newscript + cp build/scripts/newscript debian/scons/user/bin/newscript + sed '1s|.*|#!/usr/bin/python2.1|' build/scripts/newscript > debian/scons/user/bin/newscript + chmod +x debian/scons/user/bin/newscript + + rm -f debian/scons/usr/share/man/man1/newscript.1 + cp newscript.1 debian/scons/user/share/man/man1/ + + doc/SConscript + + Add "newscript" to man_page_list[] + + gentoo/scons.ebuild.in + + Add "doman newscript.1" + + rpm/scons.spec.in + + Add "gzip -c newscript.1" > $RPM_BUILD_ROOT/usr/man/man1/newscript.1.gz + + Add "%doc /usr/man/man1/newscript.1.gz" + + src/CHANGES.txt + + Document the addition of the new script. + + src/script/MANIFEST.in + + Add a line: "newscript" + + src/setup.py + + Add "script/newscript" to the 'scripts' list. diff --git a/SConstruct b/SConstruct index 59d8963..0c05859 100644 --- a/SConstruct +++ b/SConstruct @@ -395,6 +395,7 @@ scons_script = { 'filemap' : { 'LICENSE.txt' : '../LICENSE.txt', 'scons' : 'scons.py', + 'sconsign' : 'sconsign.py', } } @@ -419,6 +420,7 @@ scons = { 'RELEASE.txt', 'os_spawnv_fix.diff', 'scons.1', + 'sconsign.1', 'script/scons.bat', 'setup.cfg', 'setup.py', @@ -426,6 +428,7 @@ scons = { 'filemap' : { 'scons.1' : '../doc/man/scons.1', + 'sconsign.1' : '../doc/man/sconsign.1', }, 'subpkgs' : [ python_scons, scons_script ], @@ -436,6 +439,8 @@ scons = { }, } +scripts = ['scons', 'sconsign'] + src_deps = [] src_files = [] @@ -806,12 +811,15 @@ for p in [ scons ]: "rm -rf %s" % local, "$PYTHON $SETUP_PY install --install-script=%s --install-lib=%s --no-compile" % \ (cwd_local, cwd_local_slv), - "mv %s/scons %s/scons.py" % (local, local), ] - rf = filter(lambda x: x != "scons", raw_files) + for script in scripts: + commands.append("mv %s/%s %s/%s.py" % (local, script, local, script)) + + rf = filter(lambda x: not x in scripts, raw_files) rf = map(lambda x, slv=s_l_v: os.path.join(slv, x), rf) - rf.append("scons.py") + for script in scripts: + rf.append("%s.py" % script) local_targets = map(lambda x, s=local: os.path.join(s, x), rf) env.Command(local_targets, build_src_files, commands) diff --git a/debian/rules b/debian/rules index 200536f..e9e6421 100644 --- a/debian/rules +++ b/debian/rules @@ -57,16 +57,22 @@ install: build mkdir -p debian/scons/usr/bin/ rm -f debian/scons/usr/bin/scons + rm -f debian/scons/usr/bin/sconsign ifeq ($(PYTHON),python) cp build/scripts/scons debian/scons/usr/bin/scons + cp build/scripts/sconsign debian/scons/usr/bin/sconsign else sed '1s|.*|#!/usr/bin/python2.1|' build/scripts/scons > debian/scons/usr/bin/scons + sed '1s|.*|#!/usr/bin/python2.1|' build/scripts/sconsign > debian/scons/usr/bin/sconsign endif chmod +x debian/scons/usr/bin/scons + chmod +x debian/scons/usr/bin/sconsign mkdir -p debian/scons/usr/share/man/man1/ rm -f debian/scons/usr/share/man/man1/scons.1 + rm -f debian/scons/usr/share/man/man1/sconsign.1 cp scons.1 debian/scons/usr/share/man/man1/ + cp sconsign.1 debian/scons/usr/share/man/man1/ mkdir -p debian/scons/usr/share/doc/scons rm -f debian/scons/usr/share/doc/scons/changelog diff --git a/doc/SConscript b/doc/SConscript index d5fe171..25ad6bf 100644 --- a/doc/SConscript +++ b/doc/SConscript @@ -254,6 +254,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. if docs[doc].get('text') and jade and lynx: env.Command(text, html, "lynx -dump ${SOURCE.abspath} > $TARGET") + Local(text) env.Ignore(text, "version.sgml") @@ -263,29 +264,35 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. # # Man page(s), in good ol' troff format. # -scons_1 = os.path.join('man', 'scons.1') +man_page_list = ['scons', 'sconsign'] -if groff: - ps = os.path.join('PS', 'scons-man.ps') - text = os.path.join('TEXT', 'scons-man.txt') +for man in man_page_list: + man_1 = os.path.join('man', '%s.1' % man) - env.Command(ps, scons_1, "groff -man -Tps $SOURCES > $TARGET") + if groff: + ps = os.path.join('PS', '%s-man.ps' % man) + text = os.path.join('TEXT', '%s-man.txt' % man) - env.Command(text, scons_1, "groff -man -Tascii $SOURCES > $TARGET") + env.Command(ps, man_1, "groff -man -Tps $SOURCES > $TARGET") + Local(ps) - tar_deps.extend([ps, text]) - tar_list = string.join([tar_list, ps, text], " ") + env.Command(text, man_1, "groff -man -Tascii $SOURCES > $TARGET") + Local(text) -if man2html: - html = os.path.join('HTML' , 'scons-man.html') + tar_deps.extend([ps, text]) + tar_list = string.join([tar_list, ps, text], " ") - cmds = [ "man2html $SOURCES > $TARGET" ] - if tidy: - cmds.append("tidy -m -q $TARGET || true") - env.Command(html, scons_1, cmds) + if man2html: + html = os.path.join('HTML' , '%s-man.html' % man) - tar_deps.append(html) - tar_list = tar_list + " " + html + cmds = [ "man2html $SOURCES > $TARGET" ] + if tidy: + cmds.append("tidy -m -q $TARGET || true") + env.Command(html, man_1, cmds) + Local(html) + + tar_deps.append(html) + tar_list = tar_list + " " + html # # Now actually create the tar file of the documentation, @@ -294,3 +301,4 @@ if man2html: if tar_deps: env.Command(doc_tar_gz, tar_deps, "tar cf${TAR_HFLAG} - -C build/doc %s | gzip > $TARGET" % tar_list) + Local(doc_tar_gz) diff --git a/doc/man/sconsign.1 b/doc/man/sconsign.1 new file mode 100644 index 0000000..cb0e38e --- /dev/null +++ b/doc/man/sconsign.1 @@ -0,0 +1,131 @@ +.\" Copyright (c) 2001, 2002, 2003 Steven Knight +.\" +.\" 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. +.\" +.\" doc/man/scons.1 0.90.D006 2003/07/02 09:02:19 knight +.\" +.\" ES - Example Start - indents and turns off line fill +.de ES +.RS +.nf +.. +.\" EE - Example End - ends indent and turns line fill back on +.de EE +.RE +.fi +.. +.TH SCONSIGN 1 "July 2003" +.SH NAME +sconsign \- print SCons .sconsign file information +.SH SYNOPSIS +.B sconsign +[ +.IR options ... +] +.IR file +[ ... ] +.SH DESCRIPTION + +The +.B sconsign +command +displays the contents of one or more +.B .sconsign +files specified by the user. + +By default, +.B sconsign +dumps the entire contents of the +specified file(s). +Each entry is printed in the following format: + + file: timestamp bsig csig + implicit_dependency_1 + implicit_dependency_2 + +If the entry has no timestamp, bsig, or csig, a dash +(\fR\-\fP) is printed instead. +If the entry has no implicit dependencies, +the lines are simply omitted. + +.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 +-c, --csig +Prints the content signature (csig) information +for all entries or the specified entries. + +.TP +-e entry, --entry=entry +Prints information about only the specified entry. +Multiple -e options may be used, +in which case information about each +entry is printed in the order in which the +options are specified on the command line. + +.TP +-h, --help +Prints a help message and exits. + +.TP +-i, --implicit +Prints the list of cached implicit dependencies +for all entries or the the specified entries. + +.TP +-t, --timestamp +Prints the timestamp information +for all entries or the specified entries. + +.TP +-v, --verbose +Prints labels identifying each field being printed. + +.SH ENVIRONMENT + +.IP SCONS_LIB_DIR +Specifies the directory that contains the SCons Python module directory +(e.g. /home/aroach/scons-src-0.01/src/engine). +on the command line. + +.SH "SEE ALSO" +.BR scons , +.B scons +User Manual, +.B scons +Design Document, +.B scons +source code. + +.SH AUTHORS +Steven Knight diff --git a/gentoo/scons.ebuild.in b/gentoo/scons.ebuild.in index 36f83db..91e38a8 100644 --- a/gentoo/scons.ebuild.in +++ b/gentoo/scons.ebuild.in @@ -22,4 +22,5 @@ src_install () { python setup.py install --root=${D} dodoc *.txt PKG-INFO MANIFEST doman scons.1 + doman sconsign.1 } diff --git a/rpm/scons.spec.in b/rpm/scons.spec.in index de34305..a276af7 100644 --- a/rpm/scons.spec.in +++ b/rpm/scons.spec.in @@ -43,6 +43,7 @@ python setup.py build python setup.py install --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES mkdir -p $RPM_BUILD_ROOT/usr/man/man1 gzip -c scons.1 > $RPM_BUILD_ROOT/usr/man/man1/scons.1.gz +gzip -c sconsign.1 > $RPM_BUILD_ROOT/usr/man/man1/sconsign.1.gz %clean rm -rf $RPM_BUILD_ROOT @@ -51,3 +52,4 @@ rm -rf $RPM_BUILD_ROOT %defattr(-,root,root) __RPM_FILES__ %doc /usr/man/man1/scons.1.gz +%doc /usr/man/man1/sconsign.1.gz diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 8426798..a066689 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -26,6 +26,8 @@ RELEASE 0.XX - XXX from CVS with a specified module name. This avoids zero-length files when there is a checkout error. + - Add an "sconsign" script to print the contents of .sconsign files. + From Gary Oberbrunner: - Report the target being built in error messages when building @@ -36,6 +38,17 @@ RELEASE 0.XX - XXX - Provide helpful error messages when the arguments to env.Install() are incorrect. + From Christoph Wiedemann + + - Have the g++ Tool actually use g++ in preference to c++. + + - Have the gcc Tool actually use gcc in preference to cc. + + - Add a gnutools.py test of the GNU tool chain. + + - Be smarter about linking: use $CC by default and $CXX only if we're + linking with any C++ objects. + RELEASE 0.90 - Wed, 25 Jun 2003 14:24:52 -0500 diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py index 65c84b9..3240aa4 100644 --- a/src/engine/SCons/SConfTests.py +++ b/src/engine/SCons/SConfTests.py @@ -76,17 +76,11 @@ class SConfTestCase(unittest.TestCase): # - cygwin on win32 (using cmd.exe, not bash) # - posix # - msvc on win32 (hopefully) - if self.scons_env.subst('$CXX') == 'c++': - # better use g++ (which is normally no symbolic link - # --> the c++ call fails on cygwin - self.scons_env['CXX'] = 'g++' - if self.scons_env.subst('$LINK') == 'c++': - self.scons_env['LINK'] = 'g++' if (not self.scons_env.Detect( self.scons_env.subst('$CXX') ) or not self.scons_env.Detect( self.scons_env.subst('$CC') ) or not self.scons_env.Detect( self.scons_env.subst('$LINK') )): raise Exception, "This test needs an installed compiler!" - if self.scons_env['LINK'] == 'g++': + if self.scons_env['CXX'] == 'g++': global existing_lib existing_lib = 'm' diff --git a/src/engine/SCons/Sig/SigTests.py b/src/engine/SCons/Sig/SigTests.py index 3010396..af2ebab 100644 --- a/src/engine/SCons/Sig/SigTests.py +++ b/src/engine/SCons/Sig/SigTests.py @@ -400,6 +400,41 @@ class SConsignEntryTestCase(unittest.TestCase): assert e.bsig == None assert e.implicit == None +class _SConsignTestCase(unittest.TestCase): + + def runTest(self): + class DummyModule: + def to_string(self, sig): + return str(sig) + + def from_string(self, sig): + return int(sig) + + class DummyNode: + path = 'not_a_valid_path' + + f = SCons.Sig._SConsign() + f.set_bsig('foo', 1) + assert f.get('foo') == (None, 1, None) + f.set_csig('foo', 2) + assert f.get('foo') == (None, 1, 2) + f.set_timestamp('foo', 3) + assert f.get('foo') == (3, 1, 2) + f.set_implicit('foo', ['bar']) + assert f.get('foo') == (3, 1, 2) + assert f.get_implicit('foo') == ['bar'] + + f = SCons.Sig._SConsign(None, DummyModule()) + f.set_bsig('foo', 1) + assert f.get('foo') == (None, 1, None) + f.set_csig('foo', 2) + assert f.get('foo') == (None, 1, 2) + f.set_timestamp('foo', 3) + assert f.get('foo') == (3, 1, 2) + f.set_implicit('foo', ['bar']) + assert f.get('foo') == (3, 1, 2) + assert f.get_implicit('foo') == ['bar'] + class SConsignFileTestCase(unittest.TestCase): def runTest(self): @@ -431,6 +466,7 @@ def suite(): suite.addTest(TimeStampTestCase()) suite.addTest(CalcTestCase()) suite.addTest(SConsignEntryTestCase()) + suite.addTest(_SConsignTestCase()) suite.addTest(SConsignFileTestCase()) return suite diff --git a/src/engine/SCons/Sig/__init__.py b/src/engine/SCons/Sig/__init__.py index 65fe807..36145cb 100644 --- a/src/engine/SCons/Sig/__init__.py +++ b/src/engine/SCons/Sig/__init__.py @@ -76,34 +76,24 @@ class SConsignEntry: csig = None implicit = None -class SConsignFile: - """ - Encapsulates reading and writing a .sconsign file. - """ +class _SConsign: - def __init__(self, dir, module=None): + def __init__(self, fp=None, module=None): """ - dir - the directory for the file + fp - file pointer to read entries from module - the signature module being used """ - self.dir = dir - if module is None: self.module = default_calc.module else: self.module = module - self.sconsign = os.path.join(dir.path, '.sconsign') self.entries = {} self.dirty = 0 - try: - file = open(self.sconsign, 'rb') - except: - pass - else: + if fp: try: - self.entries = cPickle.load(file) + self.entries = cPickle.load(fp) if type(self.entries) is not type({}): self.entries = {} raise TypeError @@ -190,6 +180,27 @@ class SConsignFile: entry.implicit = implicit self.set_entry(filename, entry) +class SConsignFile(_SConsign): + """ + Encapsulates reading and writing a .sconsign file. + """ + + def __init__(self, dir, module=None): + """ + dir - the directory for the file + module - the signature module being used + """ + + self.dir = dir + self.sconsign = os.path.join(dir.path, '.sconsign') + + try: + fp = open(self.sconsign, 'rb') + except: + fp = None + + _SConsign.__init__(self, fp, module) + def write(self): """ Write the .sconsign file to disk. diff --git a/src/engine/SCons/Tool/g++.py b/src/engine/SCons/Tool/g++.py index 6beca1c..6497fe2 100644 --- a/src/engine/SCons/Tool/g++.py +++ b/src/engine/SCons/Tool/g++.py @@ -35,25 +35,22 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os.path +import cc import SCons.Defaults import SCons.Tool import SCons.Util -compilers = ['c++', 'g++'] - -CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++'] -if os.path.normcase('.c') != os.path.normcase('.C'): - CXXSuffixes.append('.C') +compilers = ['g++', 'c++'] def generate(env): """Add Builders and construction variables for g++ to an Environment.""" static_obj, shared_obj = SCons.Tool.createObjBuilders(env) - for suffix in CXXSuffixes: + for suffix in cc.CXXSuffixes: static_obj.add_action(suffix, SCons.Defaults.CXXAction) shared_obj.add_action(suffix, SCons.Defaults.ShCXXAction) - env['CXX'] = env.Detect(compilers) or 'c++' + env['CXX'] = env.Detect(compilers) or 'g++' env['CXXFLAGS'] = '$CCFLAGS' env['CXXCOM'] = '$CXX $CXXFLAGS $CPPFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES' env['SHCXX'] = '$CXX' diff --git a/src/engine/SCons/Tool/gcc.py b/src/engine/SCons/Tool/gcc.py index bf81ba8..a9f8ee1 100644 --- a/src/engine/SCons/Tool/gcc.py +++ b/src/engine/SCons/Tool/gcc.py @@ -35,13 +35,13 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import cc -compilers = ['cc', 'gcc'] +compilers = ['gcc', 'cc'] def generate(env): """Add Builders and construction variables for gcc to an Environment.""" cc.generate(env) - env['CC'] = env.Detect(compilers) or 'cc' + env['CC'] = env.Detect(compilers) or 'gcc' if env['PLATFORM'] == 'cygwin': env['SHCCFLAGS'] = '$CCFLAGS' else: diff --git a/src/engine/SCons/Tool/gnulink.py b/src/engine/SCons/Tool/gnulink.py index 1928b58..4c14383 100644 --- a/src/engine/SCons/Tool/gnulink.py +++ b/src/engine/SCons/Tool/gnulink.py @@ -33,13 +33,41 @@ selection method. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +import cc import link +import os.path +import SCons.Action +import SCons.Builder +import SCons.Errors +import SCons.Util -linkers = ['c++', 'cc', 'g++', 'gcc'] +linkers = ['g++', 'gcc', 'c++', 'cc'] +def cxxSource(sources): + for s in sources: + if os.path.splitext(str(s))[1] in cc.CXXSuffixes: + return 1 + if cxxSource(s.sources): + return 1 + return 0 + +def smart_link(source, target, env, for_signature): + cppSource = 0 + if source is None: + # may occur, when env.subst('$LINK') is called + return '$CXX' + if not SCons.Util.is_List(source): + source = [source] + + if cxxSource(source): + return '$CXX' + else: + return '$CC' + def generate(env): """Add Builders and construction variables for gnulink to an Environment.""" link.generate(env) - + env['LINK'] = smart_link + def exists(env): return env.Detect(linkers) diff --git a/src/script/MANIFEST.in b/src/script/MANIFEST.in index ebff829..9783f23 100644 --- a/src/script/MANIFEST.in +++ b/src/script/MANIFEST.in @@ -1 +1,2 @@ scons +sconsign diff --git a/src/script/scons.py b/src/script/scons.py index f128d1d..501f071 100644 --- a/src/script/scons.py +++ b/src/script/scons.py @@ -36,9 +36,18 @@ __date__ = "__DATE__" __developer__ = "__DEVELOPER__" -import sys -import os.path import os +import os.path +import sys + +############################################################################## +# BEGIN STANDARD SCons SCRIPT HEADER +# +# This is the cut-and-paste logic so that a self-contained script can +# interoperate correctly with different SCons versions and installation +# locations for the engine. If you modify anything in this section, you +# should also change other scripts that use this same header. +############################################################################## # Strip the script directory from sys.path() so on case-insensitive # (WIN32) systems Python doesn't think that the "scons" script is the @@ -120,5 +129,9 @@ libs.extend(map(lambda x: os.path.join(x, 'scons'), prefs)) sys.path = libs + sys.path +############################################################################## +# END STANDARD SCons SCRIPT HEADER +############################################################################## + import SCons.Script SCons.Script.main() diff --git a/src/script/sconsign.py b/src/script/sconsign.py new file mode 100644 index 0000000..7b5daf8 --- /dev/null +++ b/src/script/sconsign.py @@ -0,0 +1,223 @@ +#! /usr/bin/env python +# +# SCons - a Software Constructor +# +# Copyright (c) 2001, 2002, 2003 Steven Knight +# +# 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__ = "__REVISION__" + +__version__ = "__VERSION__" + +__build__ = "__BUILD__" + +__buildsys__ = "__BUILDSYS__" + +__date__ = "__DATE__" + +__developer__ = "__DEVELOPER__" + +import os +import os.path +import sys + +############################################################################## +# BEGIN STANDARD SCons SCRIPT HEADER +# +# This is the cut-and-paste logic so that a self-contained script can +# interoperate correctly with different SCons versions and installation +# locations for the engine. If you modify anything in this section, you +# should also change other scripts that use this same header. +############################################################################## + +# Strip the script directory from sys.path() so on case-insensitive +# (WIN32) systems Python doesn't think that the "scons" script is the +# "SCons" package. Replace it with our own library directories +# (version-specific first, in case they installed by hand there, +# followed by generic) so we pick up the right version of the build +# engine modules if they're in either directory. + +script_dir = sys.path[0] + +if script_dir in sys.path: + sys.path.remove(script_dir) + +libs = [] + +if os.environ.has_key("SCONS_LIB_DIR"): + libs.append(os.environ["SCONS_LIB_DIR"]) + +local = 'scons-local-' + __version__ +if script_dir: + local = os.path.join(script_dir, local) +libs.append(local) + +scons_version = 'scons-%s' % __version__ + +prefs = [] + +if sys.platform == 'win32': + # sys.prefix is (likely) C:\Python*; + # check only C:\Python*. + prefs.append(sys.prefix) +else: + # On other (POSIX) platforms, things are more complicated due to + # the variety of path names and library locations. Try to be smart + # about it. + if script_dir == 'bin': + # script_dir is `pwd`/bin; + # check `pwd`/lib/scons*. + prefs.append(os.getcwd()) + else: + if script_dir == '.' or script_dir == '': + script_dir = os.getcwd() + head, tail = os.path.split(script_dir) + if tail == "bin": + # script_dir is /foo/bin; + # check /foo/lib/scons*. + prefs.append(head) + + head, tail = os.path.split(sys.prefix) + if tail == "usr": + # sys.prefix is /foo/usr; + # check /foo/usr/lib/scons* first, + # then /foo/usr/local/lib/scons*. + prefs.append(sys.prefix) + prefs.append(os.path.join(sys.prefix, "local")) + elif tail == "local": + h, t = os.path.split(head) + if t == "usr": + # sys.prefix is /foo/usr/local; + # check /foo/usr/local/lib/scons* first, + # then /foo/usr/lib/scons*. + prefs.append(sys.prefix) + prefs.append(head) + else: + # sys.prefix is /foo/local; + # check only /foo/local/lib/scons*. + prefs.append(sys.prefix) + else: + # sys.prefix is /foo (ends in neither /usr or /local); + # check only /foo/lib/scons*. + prefs.append(sys.prefix) + + prefs = map(lambda x: os.path.join(x, 'lib'), prefs) + +# Look first for 'scons-__version__' in all of our preference libs, +# then for 'scons'. +libs.extend(map(lambda x: os.path.join(x, scons_version), prefs)) +libs.extend(map(lambda x: os.path.join(x, 'scons'), prefs)) + +sys.path = libs + sys.path + +############################################################################## +# END STANDARD SCons SCRIPT HEADER +############################################################################## + +import getopt + +helpstr = """\ +Usage: sconsign [OPTIONS] FILE [...] +Options: + -b, --bsig Print build signature information. + -c, --csig Print content signature information. + -e, --entry ENTRY Print only info about ENTRY. + -h, --help Print this message and exit. + -i, --implicit Print implicit dependency information. + -t, --timestamp Print timestamp information. + -v, --verbose Verbose, describe each field. +""" + +opts, args = getopt.getopt(sys.argv[1:], "bce:hitv", + ['bsig', 'csig', 'entry=', 'help', 'implicit', + '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 + +for o, a in opts: + if o in ('-b', '--bsig'): + printflags = printflags | pf_bsig + elif o in ('-c', '--csig'): + printflags = printflags | pf_csig + elif o in ('-e', '--entry'): + entries.append(a) + elif o in ('-h', o == '--help'): + print helpstr + sys.exit(0) + elif o in ('-i', '--implicit'): + printflags = printflags | pf_implicit + elif o in ('-t', '--timestamp'): + printflags = printflags | pf_timestamp + elif o in ('-v', '--verbose'): + 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 + (val or '-') + else: + return "" + +def printfield(name, entry): + timestamp = field("timestamp", pf_timestamp, entry.timestamp) + 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) + + +for a in args: + do_sconsign(open(a, 'rb')) diff --git a/src/setup.py b/src/setup.py index bb6f0ab..a4cb17f 100644 --- a/src/setup.py +++ b/src/setup.py @@ -195,7 +195,7 @@ arguments = { "SCons.Sig", "SCons.Tool"], 'package_dir' : {'' : 'engine'}, - 'scripts' : ["script/scons"], + 'scripts' : ['script/scons', 'script/sconsign'], 'cmdclass' : {'install' : install, 'install_lib' : install_lib, 'install_scripts' : install_scripts} diff --git a/test/LINK.py b/test/LINK.py index e3c21bc..5333290 100644 --- a/test/LINK.py +++ b/test/LINK.py @@ -44,7 +44,7 @@ os.system(string.join(sys.argv[1:], " ")) test.write('SConstruct', """ foo = Environment() -link = foo.Dictionary('LINK') +link = foo.subst("$LINK") bar = Environment(LINK = r'%s wrapper.py ' + link) foo.Program(target = 'foo', source = 'foo.c') bar.Program(target = 'bar', source = 'bar.c') diff --git a/test/LINKFLAGS.py b/test/LINKFLAGS.py index 58efcf3..047ddc7 100644 --- a/test/LINKFLAGS.py +++ b/test/LINKFLAGS.py @@ -44,7 +44,7 @@ os.system(string.join(sys.argv[1:], " ")) test.write('SConstruct', """ foo = Environment() -link = foo.Dictionary('LINK') +link = foo.subst("$LINK") bar = Environment(LINK = '', LINKFLAGS = r'%s wrapper.py ' + link) foo.Program(target = 'foo', source = 'foo.c') bar.Program(target = 'bar', source = 'bar.c') diff --git a/test/sconsign-script.py b/test/sconsign-script.py new file mode 100644 index 0000000..006f414 --- /dev/null +++ b/test/sconsign-script.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python +# +# Copyright (c) 2001, 2002, 2003 Steven Knight +# +# 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__ = "/home/scons/scons/branch.0/baseline/test/sconsign.py 0.90.D001 2003/06/25 15:32:24 knight" + +import os.path +import string + +import TestCmd +import TestSCons + +test = TestSCons.TestSCons(match = TestCmd.match_re) + +test.subdir('sub1', 'sub2') + +test.write('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"""\ +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf("sub1/hello.c\n"); + exit (0); +} +""") + +test.write(['sub2', 'hello.c'], r"""\ +#include +#include +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf("sub2/goodbye.c\n"); + exit (0); +} +""") + +test.write(['sub2', 'inc1.h'], r"""\ +#define STRING1 "inc1.h" +""") + +test.write(['sub2', 'inc2.h'], r"""\ +#define STRING2 "inc2.h" +""") + +test.run(arguments = '--implicit-cache .') + +test.run(interpreter = TestSCons.python, + program = "sconsign", + arguments = "sub1/.sconsign", + stdout = """\ +hello.exe: - \S+ - +hello.obj: - \S+ - +""") + +test.run(interpreter = TestSCons.python, + program = "sconsign", + arguments = "-v sub1/.sconsign", + stdout = """\ +hello.exe: + timestamp: - + bsig: \S+ + csig: - +hello.obj: + timestamp: - + bsig: \S+ + csig: - +""") + +test.run(interpreter = TestSCons.python, + program = "sconsign", + arguments = "-b -v sub1/.sconsign", + stdout = """\ +hello.exe: + bsig: \S+ +hello.obj: + bsig: \S+ +""") + +test.run(interpreter = TestSCons.python, + program = "sconsign", + arguments = "-c -v sub1/.sconsign", + stdout = """\ +hello.exe: + csig: - +hello.obj: + csig: - +""") + +test.run(interpreter = TestSCons.python, + program = "sconsign", + arguments = "-e hello.obj sub1/.sconsign", + stdout = """\ +hello.obj: - \S+ - +""") + +test.run(interpreter = TestSCons.python, + program = "sconsign", + arguments = "-e hello.obj -e hello.exe -e hello.obj sub1/.sconsign", + stdout = """\ +hello.obj: - \S+ - +hello.exe: - \S+ - +hello.obj: - \S+ - +""") + +test.run(interpreter = TestSCons.python, + program = "sconsign", + arguments = "sub2/.sconsign", + stdout = """\ +hello.exe: - \S+ - +hello.obj: - \S+ - + %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 = "-i -v sub2/.sconsign", + stdout = """\ +hello.exe: +hello.obj: + implicit: + %s + %s +""" % (string.replace(os.path.join('sub2', 'inc1.h'), '\\', '\\\\'), + string.replace(os.path.join('sub2', 'inc2.h'), '\\', '\\\\'))) + +test.pass_test() + +test.run(interpreter = TestSCons.python, + program = "sconsign", + arguments = "-e hello.obj sub2/.sconsign sub1/.sconsign", + stdout = """\ +hello.obj: - \S+ - + %s + %s +hello.obj: - \S+ - +""" % (string.replace(os.path.join('sub2', 'inc1.h'), '\\', '\\\\'), + string.replace(os.path.join('sub2', 'inc2.h'), '\\', '\\\\'))) + +test.pass_test() -- cgit v0.12