summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGary Oberbrunner <garyo@oberbrunner.com>2013-08-25 13:51:55 (GMT)
committerGary Oberbrunner <garyo@oberbrunner.com>2013-08-25 13:51:55 (GMT)
commitd9ee0920aa8f861e326ffb8278661de58dacbac8 (patch)
treebe1b724d5da507ac34721397b08f94d3e1d4151a
parent96119bccc3252d27798353a07fe4b52eaff17efb (diff)
parent6d7f7a2a743436e65432c6b2ed1037c7c4ad2477 (diff)
downloadSCons-d9ee0920aa8f861e326ffb8278661de58dacbac8.zip
SCons-d9ee0920aa8f861e326ffb8278661de58dacbac8.tar.gz
SCons-d9ee0920aa8f861e326ffb8278661de58dacbac8.tar.bz2
Merge pull request #84, cyglink tool from David Rothenberger.
Also updated src/CHANGES.txt.
-rw-r--r--QMTest/TestCommon.py2
-rw-r--r--src/CHANGES.txt12
-rw-r--r--src/engine/MANIFEST.in1
-rw-r--r--src/engine/SCons/Tool/__init__.py8
-rw-r--r--src/engine/SCons/Tool/__init__.xml13
-rw-r--r--src/engine/SCons/Tool/cyglink.py94
-rw-r--r--src/engine/SCons/Tool/link.py12
-rw-r--r--test/LINK/VersionedLib.py12
-rw-r--r--test/Libs/SharedLibrary.py9
-rw-r--r--test/Libs/SharedLibraryIxes.py20
10 files changed, 174 insertions, 9 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/src/CHANGES.txt b/src/CHANGES.txt
index 68740bd..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.
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 89aabb5..af1282c 100644
--- a/src/engine/SCons/Tool/__init__.py
+++ b/src/engine/SCons/Tool/__init__.py
@@ -733,6 +733,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 18bfd3e..9c3dc85 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 0d45789..3c92252 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)