From f837e2e6511cc8049e5a765c9af25afc9fd730fe Mon Sep 17 00:00:00 2001 From: David Rothenberger Date: Sat, 17 Aug 2013 12:12:56 -0700 Subject: Add a cyglink tool Add cyglink, a specialization of gnulink with the following properties: 1. Set SHLIBPREFIX to "cyg" and SHLIBSUFFIX = ".dll". 2. Remove any "lib" after "cyg", to accommodate build scripts that name libraries "libFoo". 3. Create DLL import libraries. --- src/engine/MANIFEST.in | 1 + src/engine/SCons/Tool/__init__.py | 8 ++++ src/engine/SCons/Tool/__init__.xml | 13 +++++- src/engine/SCons/Tool/cyglink.py | 96 ++++++++++++++++++++++++++++++++++++++ src/engine/SCons/Tool/link.py | 12 +++++ 5 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 src/engine/SCons/Tool/cyglink.py 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. +On Cygwin systems, the +&b-SharedLibrary; +builder method will always build an import +(.dll.a) library +in addition to the shared (.dll) library, +adding a .dll.a library with the same basename +if there is not already a .dll.a file explicitly +listed in the targets. + + + Any object files listed in the source must have been built for a shared library @@ -485,4 +496,4 @@ letters to designate alpha, beta, or release candidate patch levels. - \ No newline at end of file + diff --git a/src/engine/SCons/Tool/cyglink.py b/src/engine/SCons/Tool/cyglink.py new file mode 100644 index 0000000..23c1adf --- /dev/null +++ b/src/engine/SCons/Tool/cyglink.py @@ -0,0 +1,96 @@ +"""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') + dll_name = str(dll) + if dll_name[len(pre):len(pre)+3] == 'lib': + dll_name = pre + dll_name[len(pre)+3:] + dll = env.fs.File(dll_name) + + 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 -- cgit v0.12