diff options
-rw-r--r-- | QMTest/TestCommon.py | 2 | ||||
-rw-r--r-- | bin/SConsDoc.py | 2 | ||||
-rwxr-xr-x | bootstrap.py | 33 | ||||
-rw-r--r-- | src/CHANGES.txt | 14 | ||||
-rw-r--r-- | src/engine/MANIFEST.in | 1 | ||||
-rw-r--r-- | src/engine/SCons/Tool/__init__.py | 8 | ||||
-rw-r--r-- | src/engine/SCons/Tool/__init__.xml | 13 | ||||
-rw-r--r-- | src/engine/SCons/Tool/cyglink.py | 94 | ||||
-rw-r--r-- | src/engine/SCons/Tool/link.py | 12 | ||||
-rw-r--r-- | test/LINK/VersionedLib.py | 12 | ||||
-rw-r--r-- | test/Libs/SharedLibrary.py | 9 | ||||
-rw-r--r-- | test/Libs/SharedLibraryIxes.py | 20 |
12 files changed, 184 insertions, 36 deletions
diff --git a/QMTest/TestCommon.py b/QMTest/TestCommon.py index 6eeda5e..4e90e16 100644 --- a/QMTest/TestCommon.py +++ b/QMTest/TestCommon.py @@ -163,7 +163,7 @@ elif sys.platform == 'cygwin': shobj_prefix = '' lib_prefix = 'lib' lib_suffix = '.a' - dll_prefix = '' + dll_prefix = 'cyg' dll_suffix = '.dll' elif sys.platform.find('irix') != -1: exe_suffix = '' diff --git a/bin/SConsDoc.py b/bin/SConsDoc.py index c9d1e6e..dc9d161 100644 --- a/bin/SConsDoc.py +++ b/bin/SConsDoc.py @@ -331,7 +331,7 @@ if not has_libxml2: # Use lxml xmlschema = etree.XMLSchema(xmlschema_context) try: - doc = etree.parse(fpath) + doc = etree.parse(fpath) except Exception, e: print "ERROR: %s fails to parse:"%fpath print e diff --git a/bootstrap.py b/bootstrap.py index 78a85b5..f3bc105 100755 --- a/bootstrap.py +++ b/bootstrap.py @@ -80,9 +80,7 @@ def parseManifestLines(basedir, lines): comment lines, starting with a '#'. """ sources = [] - oldwd = os.path.abspath(os.getcwd()) basewd = os.path.abspath(basedir) - os.chdir(basedir) for l in lines: if l.startswith('#'): # Skip comments @@ -90,33 +88,18 @@ def parseManifestLines(basedir, lines): l = l.rstrip('\n') if l.endswith('**'): # Glob all files recursively - globwd, tail = os.path.split(l) - if globwd: - os.chdir(globwd) - for path, dirs, files in os.walk('.'): + globwd = os.path.dirname(os.path.join(basewd, l)) + for path, dirs, files in os.walk(globwd): for f in files: - if globwd: - fpath = os.path.join(globwd, path, f) - else: - fpath = os.path.join(path, f) - sources.append(os.path.normpath(fpath)) - if globwd: - os.chdir(basewd) + fpath = os.path.join(globwd, path, f) + sources.append(os.path.relpath(fpath, basewd)) elif '*' in l: # Glob file pattern - globwd, tail = os.path.split(l) - if globwd: - os.chdir(globwd) - files = glob.glob(tail) - for f in files: - fpath = os.path.join(globwd, f) - sources.append(os.path.normpath(fpath)) - os.chdir(basewd) - else: - sources.extend(glob.glob(tail)) + files = glob.glob(os.path.join(basewd, l)) + for f in files: + sources.append(os.path.relpath(f, basewd)) else: sources.append(l) - os.chdir(oldwd) return sources @@ -201,7 +184,7 @@ def main(): MANIFEST_in = find(os.path.join(src_engine, 'MANIFEST.in')) files = [ scons_py ] + [os.path.join(src_engine, x) - for x in parseManifestLines(src_engine, open(MANIFEST_in).readlines())] + for x in parseManifestLines(os.path.join(script_dir, src_engine), open(MANIFEST_in).readlines())] for file in files: src = find(file) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 3494cfd..0b5368b 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,9 +6,21 @@ RELEASE 2.3.1.alpha.yyyymmdd - NEW DATE WILL BE INSERTED HERE + From David Rothenberger: + - Added cyglink linker that uses Cygwin naming conventions for + shared libraries and automatically generates import libraries. + + From Dirk Baechle: + - Update bootstrap.py so it can be used from any dir, to run + SCons from a source (non-installed) dir. + From Gary Oberbrunner: - Test harness: fail_test() can now print a message to help debugging. + From Anatoly Techtonik: + - require rpmbuild when building SCons package. + - print full stack on certain errors, for debugging. + From William Deegan: - VS2012 & VS2010 Resolve initialization issues by adding path to reg.exe in shell used to run batch files. @@ -182,7 +194,7 @@ RELEASE 2.1.0 - Mon, 09 Sep 2011 20:54:57 -0700 - Fix Delete to be able to delete broken symlinks and dir symlinks. - From Robert Lehr: + From Imran Fanaswala and Robert Lehr: - Handle .output file generated by bison/yacc properly. Cleaning it when necessary. diff --git a/src/engine/MANIFEST.in b/src/engine/MANIFEST.in index 5e7627f..0afda50 100644 --- a/src/engine/MANIFEST.in +++ b/src/engine/MANIFEST.in @@ -62,6 +62,7 @@ SCons/Tool/bcc32.py SCons/Tool/BitKeeper.py SCons/Tool/c++.py SCons/Tool/cc.py +SCons/Tool/cyglink.py SCons/Tool/cvf.py SCons/Tool/CVS.py SCons/Tool/default.py diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index d76b721..b80d6e4 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -741,6 +741,14 @@ def tool_list(platform, env): assemblers = ['as'] fortran_compilers = ['gfortran', 'f95', 'f90', 'g77'] ars = ['ar'] + elif str(platform) == 'cygwin': + "prefer GNU tools on Cygwin, except for a platform-specific linker" + linkers = ['cyglink', 'mslink', 'ilink'] + c_compilers = ['gcc', 'msvc', 'intelc', 'icc', 'cc'] + cxx_compilers = ['g++', 'msvc', 'intelc', 'icc', 'c++'] + assemblers = ['gas', 'nasm', 'masm'] + fortran_compilers = ['gfortran', 'g77', 'ifort', 'ifl', 'f95', 'f90', 'f77'] + ars = ['ar', 'mslib'] else: "prefer GNU tools on all other platforms" linkers = ['gnulink', 'mslink', 'ilink'] diff --git a/src/engine/SCons/Tool/__init__.xml b/src/engine/SCons/Tool/__init__.xml index de4f59b..0918b46 100644 --- a/src/engine/SCons/Tool/__init__.xml +++ b/src/engine/SCons/Tool/__init__.xml @@ -168,6 +168,17 @@ listed in the targets. </para> <para> +On Cygwin systems, the +&b-SharedLibrary; +builder method will always build an import +(<filename>.dll.a</filename>) library +in addition to the shared (<filename>.dll</filename>) library, +adding a <filename>.dll.a</filename> library with the same basename +if there is not already a <filename>.dll.a</filename> file explicitly +listed in the targets. +</para> + +<para> Any object files listed in the <literal>source</literal> must have been built for a shared library @@ -485,4 +496,4 @@ letters to designate alpha, beta, or release candidate patch levels. </summary> </cvar> -</sconsdoc>
\ No newline at end of file +</sconsdoc> diff --git a/src/engine/SCons/Tool/cyglink.py b/src/engine/SCons/Tool/cyglink.py new file mode 100644 index 0000000..87716cf --- /dev/null +++ b/src/engine/SCons/Tool/cyglink.py @@ -0,0 +1,94 @@ +"""SCons.Tool.cyglink + +Customization of gnulink for Cygwin (http://www.cygwin.com/) + +There normally shouldn't be any need to import this module directly. +It will usually be imported through the generic SCons.Tool.Tool() +selection method. + +""" + +import SCons.Action +import SCons.Util + +import gnulink + +def shlib_generator(target, source, env, for_signature): + cmd = SCons.Util.CLVar(['$SHLINK']) + + dll = env.FindIxes(target, 'SHLIBPREFIX', 'SHLIBSUFFIX') + if dll: cmd.extend(['-o', dll]) + + cmd.extend(['$SHLINKFLAGS', '$__RPATH']) + + implib = env.FindIxes(target, 'IMPLIBPREFIX', 'IMPLIBSUFFIX') + if implib: + cmd.extend([ + '-Wl,--out-implib='+implib.get_string(for_signature), + '-Wl,--export-all-symbols', + '-Wl,--enable-auto-import', + '-Wl,--whole-archive', '$SOURCES', + '-Wl,--no-whole-archive', '$_LIBDIRFLAGS', '$_LIBFLAGS' + ]) + else: + cmd.extend(['$SOURCES', '$_LIBDIRFLAGS', '$_LIBFLAGS']) + + return [cmd] + +def shlib_emitter(target, source, env): + dll = env.FindIxes(target, 'SHLIBPREFIX', 'SHLIBSUFFIX') + no_import_lib = env.get('no_import_lib', 0) + + if not dll or len(target) > 1: + raise SCons.Errors.UserError("A shared library should have exactly one target with the suffix: %s" % env.subst("$SHLIBSUFFIX")) + + # Remove any "lib" after the prefix + pre = env.subst('$SHLIBPREFIX') + if dll.name[len(pre):len(pre)+3] == 'lib': + dll.name = pre + dll.name[len(pre)+3:] + + orig_target = target + target = [env.fs.File(dll)] + target[0].attributes.shared = 1 + + # Append an import lib target + if not no_import_lib: + # Create list of target libraries as strings + target_strings = env.ReplaceIxes(orig_target[0], + 'SHLIBPREFIX', 'SHLIBSUFFIX', + 'IMPLIBPREFIX', 'IMPLIBSUFFIX') + + implib_target = env.fs.File(target_strings) + implib_target.attributes.shared = 1 + target.append(implib_target) + + return (target, source) + + +shlib_action = SCons.Action.Action(shlib_generator, generator=1) + +def generate(env): + """Add Builders and construction variables for cyglink to an Environment.""" + gnulink.generate(env) + + env['LINKFLAGS'] = SCons.Util.CLVar('-Wl,-no-undefined') + + env['SHLINKCOM'] = shlib_action + env['LDMODULECOM'] = shlib_action + env.Append(SHLIBEMITTER = [shlib_emitter]) + + env['SHLIBPREFIX'] = 'cyg' + env['SHLIBSUFFIX'] = '.dll' + + env['IMPLIBPREFIX'] = 'lib' + env['IMPLIBSUFFIX'] = '.dll.a' + +def exists(env): + return gnulink.exists(env) + + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/link.py b/src/engine/SCons/Tool/link.py index 2ba419e..3f20fe0 100644 --- a/src/engine/SCons/Tool/link.py +++ b/src/engine/SCons/Tool/link.py @@ -127,6 +127,18 @@ def shlib_emitter_names(target, source, env): print "shlib_emitter_names: side effect: ", name # add version_name to list of names to be a Side effect version_names.append(version_name) + elif platform == 'cygwin': + shlib_suffix = env.subst('$SHLIBSUFFIX') + name = target[0].name + # generate library name with the version number + suffix_re = re.escape(shlib_suffix) + version_name = re.sub(suffix_re, '-' + re.sub('\.', '-', version) + shlib_suffix, name) + if Verbose: + print "shlib_emitter_names: target is ", version_name + print "shlib_emitter_names: side effect: ", name + # add version_name to list of names to be a Side effect + version_names.append(version_name) + except KeyError: version = None return version_names diff --git a/test/LINK/VersionedLib.py b/test/LINK/VersionedLib.py index d3f1141..a2345d6 100644 --- a/test/LINK/VersionedLib.py +++ b/test/LINK/VersionedLib.py @@ -98,6 +98,18 @@ elif platform == 'darwin': 'libtest.dylib',
'libtest.2.5.4.dylib',
]
+elif platform == 'cygwin':
+ # All (?) the files we expect will get created in the current directory
+ files = [
+ 'cygtest-2-5-4.dll',
+ 'libtest-2-5-4.dll.a',
+ 'test.os',
+ ]
+ # All (?) the files we expect will get created in the 'installtest' directory
+ instfiles = [
+ 'cygtest-2-5-4.dll',
+ 'libtest-2-5-4.dll.a',
+ ]
elif platform == 'win32':
# All (?) the files we expect will get created in the current directory
files = [
diff --git a/test/Libs/SharedLibrary.py b/test/Libs/SharedLibrary.py index 18d1f24..b7d1374 100644 --- a/test/Libs/SharedLibrary.py +++ b/test/Libs/SharedLibrary.py @@ -44,7 +44,7 @@ else: SharedLibrary(target = 'foo2', source = Split('f2a.c f2b.c f2c.c'), WINDOWS_INSERT_DEF = 1) -env.SharedLibrary(target = 'foo3', source = ['f3a.c', 'f3b.c', 'f3c.c']) +env.SharedLibrary(target = 'foo3', source = ['f3a.c', 'f3b.c', 'f3c.c'], no_import_lib = 1) env2.Program(target = 'prog', source = 'prog.c') """) @@ -207,6 +207,13 @@ if sys.platform.find('irix') != -1: test.run(program = test.workpath('prog'), stdout = "f1.c\nf2a.c\nf2b.c\nf2c.c\nf3a.c\nf3b.c\nf3c.c\nprog.c\n") +if sys.platform == 'cygwin': + # Cygwin: Make sure the DLLs are prefixed correctly. + test.must_exist('cygfoo1.dll', 'cygfoo2.dll', 'cygfoo3.dll') + test.must_exist('libfoo1.dll.a', 'libfoo2.dll.a') + test.must_not_exist('foo3.dll.a') + + if sys.platform == 'win32' or sys.platform.find('irix') != -1: test.run(arguments = '-f SConstructFoo') else: diff --git a/test/Libs/SharedLibraryIxes.py b/test/Libs/SharedLibraryIxes.py index 4804f5f..6924769 100644 --- a/test/Libs/SharedLibraryIxes.py +++ b/test/Libs/SharedLibraryIxes.py @@ -30,12 +30,14 @@ libraries that have non-standard library prefixes and suffixes. """ import re +import sys import TestSCons test = TestSCons.TestSCons() test.write('SConstruct', """ import sys +isCygwin = sys.platform == 'cygwin' isWindows = sys.platform == 'win32' isMingw = False if isWindows: @@ -107,9 +109,9 @@ def nameInLib(source, lib, libname): return (source, libname) libmethods = [nodeInSrc, pathInSrc, nodeInLib, pathInLib] -# We skip the nameInLib test for MinGW...it would fail, due to +# We skip the nameInLib test for MinGW and Cygwin...they would fail, due to # the Tool's internal naming conventions -if not isMingw: +if not isMingw and not isCygwin: libmethods.extend([nameInLib]) def buildAndlinkAgainst(builder, target, source, method, lib, libname, **kw): @@ -122,11 +124,11 @@ def buildAndlinkAgainst(builder, target, source, method, lib, libname, **kw): if str(l)[-4:] == '.lib': lib = [l] break - # If we use MinGW and create a SharedLibrary, we get two targets: a DLL, + # If we use MinGW or Cygwin and create a SharedLibrary, we get two targets: a DLL, # and the import lib created by the "--out-implib" parameter. We always # want to link against the second one, in order to prevent naming issues # for the linker command line... - if isMingw and len(lib) > 1: + if (isMingw or isCygwin) and len(lib) > 1: lib = lib[1:] # Apply the naming method to be tested and call the specified Builder. @@ -276,8 +278,14 @@ tests = re.findall(r'Prog: (\d+), (\S+), (\S+), (\S+)', test.stdout()) expected = "goo.c\nfoo.c\nprog.c\n" for t in tests: - test.must_exist(t[1]) - test.must_exist(t[2]) + if sys.platform != 'cygwin': + test.must_exist(t[1]) + test.must_exist(t[2]) + else: + # Cygwin turns libFoo.xxx into cygFoo.xxx + for f in t[1:2]: + test.must_exist(re.sub('^lib', 'cyg', f)) + test.must_exist(t[3]) test.run(program = test.workpath(t[3]), stdout=expected) |