From df81b3858c382f8c74d9645ba53cf66cf46c36d3 Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Sun, 6 Aug 2006 21:02:53 +0000 Subject: Merged revisions 1540-1545,1547-1581 via svnmerge from http://scons.tigris.org/svn/scons/branches/core ........ r1543 | stevenknight | 2006-07-25 20:37:19 -0400 (Tue, 25 Jul 2006) | 3 lines Initialized merge tracking via "svnmerge" with revisions "1-1502" from http://scons.tigris.org/svn/scons/branches/sigrefactor ........ r1558 | stevenknight | 2006-07-28 22:43:38 -0400 (Fri, 28 Jul 2006) | 2 lines Ignore *.pyc files in the QMTest subdirectory. ........ r1561 | stevenknight | 2006-07-29 07:16:14 -0400 (Sat, 29 Jul 2006) | 3 lines Fix the infrastructure that tests runtest.py itself when the wrapping runtest.py is run directly, not through Aegis. ........ r1580 | stevenknight | 2006-08-06 15:00:06 -0400 (Sun, 06 Aug 2006) | 1 line 0.96.D428 - Support cleaning and scanning target files generated by SWIG. (Arve Knudsen) ........ r1581 | stevenknight | 2006-08-06 15:40:20 -0400 (Sun, 06 Aug 2006) | 1 line 0.96.D429 - Use zipimport as a fallback when importing modules so SCons can use py2exe's all ........ --- QMTest/TestRuntest.py | 2 +- src/CHANGES.txt | 14 +++++++++ src/engine/SCons/Platform/__init__.py | 17 +++++++---- src/engine/SCons/Tool/__init__.py | 27 +++++++++++++++--- src/engine/SCons/Tool/swig.py | 54 +++++++++++++++++++++++++++++++++++ test/SWIG/SWIG.py | 50 ++++++++++++++++++++++++++++++++ 6 files changed, 154 insertions(+), 10 deletions(-) diff --git a/QMTest/TestRuntest.py b/QMTest/TestRuntest.py index 6fd423a9..a4bcd05d 100644 --- a/QMTest/TestRuntest.py +++ b/QMTest/TestRuntest.py @@ -99,7 +99,7 @@ class TestRuntest(TestCommon): 'QMTest', ] - dirs = [] + dirs = [orig_cwd] spe = os.environ.get('SCONS_SOURCE_PATH_EXECUTABLE', orig_cwd) for d in string.split(spe, os.pathsep): diff --git a/src/CHANGES.txt b/src/CHANGES.txt index b3eb4848..ccbc3af5 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -47,6 +47,16 @@ RELEASE 0.97 - XXX This will become the default behavior as we add more functionality to the QMTest side. + From Arve Knudsen: + + - Support cleaning and scanning SWIG-generated files. + + From Baptiste Lepilleur: + + - Try using zipimport if we can't import Tool or Platform modules + using the normal "imp" module. This allows SCons to be packaged + using py2exe's all-in-one-zip-file approach. + From Sanjoy Mahajan: - Change use of $SOURCES to $SOURCE in all TeX-related Tool modules. @@ -99,6 +109,10 @@ RELEASE 0.97 - XXX - Fix detection of Visual C++ Express Edition. + From Johan Zander: + + - Fix missing os.path.join() when constructing the $FRAMEWORKSDKDIR/bin. + RELEASE 0.96.92 - Mon, 10 Apr 2006 21:08:22 -0400 diff --git a/src/engine/SCons/Platform/__init__.py b/src/engine/SCons/Platform/__init__.py index b1a0a675..0a470595 100644 --- a/src/engine/SCons/Platform/__init__.py +++ b/src/engine/SCons/Platform/__init__.py @@ -98,12 +98,19 @@ def platform_module(name = platform_default()): try: file, path, desc = imp.find_module(name, sys.modules['SCons.Platform'].__path__) - mod = imp.load_module(full_name, file, path, desc) - setattr(SCons.Platform, name, mod) + try: + mod = imp.load_module(full_name, file, path, desc) + finally: + if file: + file.close() except ImportError: - raise SCons.Errors.UserError, "No platform named '%s'" % name - if file: - file.close() + try: + import zipimport + importer = zipimport.zipimporter( sys.modules['SCons.Platform'].__path__[0] ) + mod = importer.load_module(full_name) + except ImportError: + raise SCons.Errors.UserError, "No platform named '%s'" % name + setattr(SCons.Platform, name, mod) return sys.modules[full_name] def DefaultToolList(platform, env): diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 77da0c71..d36478d4 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -99,7 +99,17 @@ class Tool: if file: file.close() except ImportError, e: - pass + try: + import zipimport + except ImportError: + pass + else: + for aPath in self.toolpath: + try: + importer = zipimport.zipimporter(aPath) + return importer.load_module(self.name) + except ImportError, e: + pass finally: sys.path = oldpythonpath @@ -109,14 +119,23 @@ class Tool: except KeyError: try: smpath = sys.modules['SCons.Tool'].__path__ - file, path, desc = imp.find_module(self.name, smpath) try: + file, path, desc = imp.find_module(self.name, smpath) module = imp.load_module(full_name, file, path, desc) setattr(SCons.Tool, self.name, module) - return module - finally: if file: file.close() + return module + except ImportError, e: + try: + import zipimport + importer = zipimport.zipimporter( sys.modules['SCons.Tool'].__path__[0] ) + module = importer.load_module(full_name) + setattr(SCons.Tool, self.name, module) + return module + except ImportError, e: + m = "No tool named '%s': %s" % (self.name, e) + raise SCons.Errors.UserError, m except ImportError, e: m = "No tool named '%s': %s" % (self.name, e) raise SCons.Errors.UserError, m diff --git a/src/engine/SCons/Tool/swig.py b/src/engine/SCons/Tool/swig.py index 449e3aab..ed066a7c 100644 --- a/src/engine/SCons/Tool/swig.py +++ b/src/engine/SCons/Tool/swig.py @@ -37,6 +37,9 @@ import SCons.Action import SCons.Defaults import SCons.Tool import SCons.Util +from SCons.Scanner import Scanner +import os +import re SwigAction = SCons.Action.Action('$SWIGCOM', '$SWIGCOMSTR') @@ -46,6 +49,54 @@ def swigSuffixEmitter(env, source): else: return '$SWIGCFILESUFFIX' +_reSwig = re.compile(r"%include\s+(\S+)") + +def recurse(path, searchPath): + global _reSwig + f = open(path) + try: contents = f.read() + finally: f.close() + + found = [] + # Better code for when we drop Python 1.5.2. + #for m in _reSwig.finditer(contents): + # fname = m.group(1) + for fname in _reSwig.findall(contents): + for dpath in searchPath: + absPath = os.path.join(dpath, fname) + if os.path.isfile(absPath): + found.append(absPath) + break + + # Equivalent code for when we drop Python 1.5.2. + #for f in [f for f in found if os.path.splitext(f)[1] == ".i"]: + # found += recurse(f, searchPath) + for f in filter(lambda f: os.path.splitext(f)[1] == ".i", found): + found = found + recurse(f, searchPath) + return found + +def _scanSwig(node, env, path): + import sys + r = recurse(str(node), [os.path.abspath(os.path.dirname(str(node))), os.path.abspath(os.path.join("include", "swig"))]) + return r + +def _swigEmitter(target, source, env): + for src in source: + src = str(src) + mname = None + if "-python" in SCons.Util.CLVar(env.subst("$SWIGFLAGS")): + f = open(src) + try: + for l in f.readlines(): + m = re.match("%module (.+)", l) + if m: + mname = m.group(1) + finally: + f.close() + if mname is not None: + target.append(mname + ".py") + return (target, source) + def generate(env): """Add Builders and construction variables for swig to an Environment.""" c_file, cxx_file = SCons.Tool.createCFileBuilders(env) @@ -54,13 +105,16 @@ def generate(env): cxx_file.suffix['.i'] = swigSuffixEmitter c_file.add_action('.i', SwigAction) + c_file.add_emitter('.i', _swigEmitter) cxx_file.add_action('.i', SwigAction) + cxx_file.add_emitter('.i', _swigEmitter) env['SWIG'] = 'swig' env['SWIGFLAGS'] = SCons.Util.CLVar('') env['SWIGCFILESUFFIX'] = '_wrap$CFILESUFFIX' env['SWIGCXXFILESUFFIX'] = '_wrap$CXXFILESUFFIX' env['SWIGCOM'] = '$SWIG $SWIGFLAGS -o $TARGET $SOURCES' + env.Append(SCANNERS=Scanner(function=_scanSwig, skeys=[".i"])) def exists(env): return env.Detect(['swig']) diff --git a/test/SWIG/SWIG.py b/test/SWIG/SWIG.py index 753d0b92..65ecf2ba 100644 --- a/test/SWIG/SWIG.py +++ b/test/SWIG/SWIG.py @@ -218,6 +218,56 @@ This is bar.c! test.up_to_date(arguments = '.') + # Test that swig-generated modules are removed + # The %module directive specifies the module name + test.write("module.i", """\ +%module modulename +""") + test.write('SConstruct', """ +foo = Environment(SWIGFLAGS='-python', + CPPPATH='%(platform_sys_prefix)s/include/python%(version)s/', + SHCCFLAGS='', + LDMODULEPREFIX='%(ldmodule_prefix)s', + LDMODULESUFFIX='%(_dll)s', + FRAMEWORKSFLAGS='%(frameworks)s', + ) + +foo.LoadableModule(target = 'modulename', source = ['module.i']) +""" % locals()) + test.run() + test.must_exist(test.workpath("modulename.py")) + test.run(arguments = "-c") + test.must_not_exist(test.workpath("modulename.py")) + + # Test that implicit dependencies are caught + + test.write("dependency.i", """\ +%module dependency +""") + test.write("dependent.i", """\ +%module dependent + +%include dependency.i +""") + test.write('SConstruct', """ +foo = Environment(SWIGFLAGS='-python', + CPPPATH='%(platform_sys_prefix)s/include/python%(version)s/', + SHCCFLAGS='', + LDMODULEPREFIX='%(ldmodule_prefix)s', + LDMODULESUFFIX='%(_dll)s', + FRAMEWORKSFLAGS='%(frameworks)s', + ) +swig = foo.Dictionary('SWIG') +bar = foo.Copy(SWIG = r'%(python)s wrapper.py ' + swig) +foo.CFile(target = 'dependent', source = ['dependent.i']) +""" % locals()) + + test.run() + test.write("dependency.i", """%module dependency + +extern char *dependency_string(); +""") + test.not_up_to_date(arguments = "dependent_wrap.c") test.pass_test() -- cgit v1.2.1