From be720e0369b6b8a97ceab4a4f8f8930911bd1b75 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tarek=20Ziad=C3=A9?= <ziade.tarek@gmail.com>
Date: Sat, 9 May 2009 11:55:12 +0000
Subject: Merged revisions 72497 via svnmerge from
 svn+ssh://pythondev@svn.python.org/python/trunk

........
  r72497 | tarek.ziade | 2009-05-09 10:28:53 +0200 (Sat, 09 May 2009) | 1 line

  Fixed Issue 5900: distutils.command.build_ext - Ensure RUNPATH is added to extension modules with RPATH if GNU ld is used
........
---
 Lib/distutils/tests/test_build_ext.py     |  3 +-
 Lib/distutils/tests/test_unixccompiler.py | 93 +++++++++++++++++++++++++++++++
 Lib/distutils/unixccompiler.py            | 24 ++++++--
 Makefile.pre.in                           |  2 +
 configure                                 | 27 ++++++++-
 configure.in                              | 19 +++++++
 6 files changed, 160 insertions(+), 8 deletions(-)
 create mode 100644 Lib/distutils/tests/test_unixccompiler.py

diff --git a/Lib/distutils/tests/test_build_ext.py b/Lib/distutils/tests/test_build_ext.py
index 5ea67be..e4a0239 100644
--- a/Lib/distutils/tests/test_build_ext.py
+++ b/Lib/distutils/tests/test_build_ext.py
@@ -125,7 +125,7 @@ class BuildExtTestCase(TempdirManager,
         dist = Distribution({'name': 'xx'})
         cmd = build_ext(dist)
 
-        # making sure the suer option is there
+        # making sure the user option is there
         options = [name for name, short, lable in
                    cmd.user_options]
         self.assert_('user' in options)
@@ -145,6 +145,7 @@ class BuildExtTestCase(TempdirManager,
         # see if include_dirs and library_dirs
         # were set
         self.assert_(lib in cmd.library_dirs)
+        self.assert_(lib in cmd.rpath)
         self.assert_(incl in cmd.include_dirs)
 
     def test_optional_extension(self):
diff --git a/Lib/distutils/tests/test_unixccompiler.py b/Lib/distutils/tests/test_unixccompiler.py
new file mode 100644
index 0000000..94e9edf
--- /dev/null
+++ b/Lib/distutils/tests/test_unixccompiler.py
@@ -0,0 +1,93 @@
+"""Tests for distutils.unixccompiler."""
+import sys
+import unittest
+
+from distutils import sysconfig
+from distutils.unixccompiler import UnixCCompiler
+
+class UnixCCompilerTestCase(unittest.TestCase):
+
+    def setUp(self):
+        self._backup_platform = sys.platform
+        self._backup_get_config_var = sysconfig.get_config_var
+        class CompilerWrapper(UnixCCompiler):
+            def rpath_foo(self):
+                return self.runtime_library_dir_option('/foo')
+        self.cc = CompilerWrapper()
+
+    def tearDown(self):
+        sys.platform = self._backup_platform
+        sysconfig.get_config_var = self._backup_get_config_var
+
+    def test_runtime_libdir_option(self):
+
+        # not tested under windows
+        if sys.platform == 'win32':
+            return
+
+        # Issue#5900
+        #
+        # Ensure RUNPATH is added to extension modules with RPATH if
+        # GNU ld is used
+
+        # darwin
+        sys.platform = 'darwin'
+        self.assertEqual(self.cc.rpath_foo(), '-L/foo')
+
+        # hp-ux
+        sys.platform = 'hp-ux'
+        self.assertEqual(self.cc.rpath_foo(), '+s -L/foo')
+
+        # irix646
+        sys.platform = 'irix646'
+        self.assertEqual(self.cc.rpath_foo(), ['-rpath', '/foo'])
+
+        # osf1V5
+        sys.platform = 'osf1V5'
+        self.assertEqual(self.cc.rpath_foo(), ['-rpath', '/foo'])
+
+        # GCC GNULD
+        sys.platform = 'bar'
+        def gcv(v):
+            if v == 'CC':
+                return 'gcc'
+            elif v == 'GNULD':
+                return 'yes'
+        sysconfig.get_config_var = gcv
+        self.assertEqual(self.cc.rpath_foo(), '-Wl,--enable-new-dtags,-R/foo')
+
+        # GCC non-GNULD
+        sys.platform = 'bar'
+        def gcv(v):
+            if v == 'CC':
+                return 'gcc'
+            elif v == 'GNULD':
+                return 'no'
+        sysconfig.get_config_var = gcv
+        self.assertEqual(self.cc.rpath_foo(), '-Wl,-R/foo')
+
+        # non-GCC GNULD
+        sys.platform = 'bar'
+        def gcv(v):
+            if v == 'CC':
+                return 'cc'
+            elif v == 'GNULD':
+                return 'yes'
+        sysconfig.get_config_var = gcv
+        self.assertEqual(self.cc.rpath_foo(), '-R/foo')
+
+        # non-GCC non-GNULD
+        sys.platform = 'bar'
+        def gcv(v):
+            if v == 'CC':
+                return 'cc'
+            elif v == 'GNULD':
+                return 'no'
+        sysconfig.get_config_var = gcv
+        self.assertEqual(self.cc.rpath_foo(), '-R/foo')
+
+def test_suite():
+    return unittest.makeSuite(UnixCCompilerTestCase)
+
+if __name__ == "__main__":
+    unittest.main(defaultTest="test_suite")
diff --git a/Lib/distutils/unixccompiler.py b/Lib/distutils/unixccompiler.py
index d65ab32..c11544d 100644
--- a/Lib/distutils/unixccompiler.py
+++ b/Lib/distutils/unixccompiler.py
@@ -271,8 +271,9 @@ class UnixCCompiler(CCompiler):
         # Linkers on different platforms need different options to
         # specify that directories need to be added to the list of
         # directories searched for dependencies when a dynamic library
-        # is sought.  GCC has to be told to pass the -R option through
-        # to the linker, whereas other compilers just know this.
+        # is sought.  GCC on GNU systems (Linux, FreeBSD, ...) has to
+        # be told to pass the -R option through to the linker, whereas
+        # other compilers and gcc on other systems just know this.
         # Other compilers may need something slightly different.  At
         # this time, there's no way to determine this information from
         # the configuration data stored in the Python installation, so
@@ -285,10 +286,23 @@ class UnixCCompiler(CCompiler):
             return "+s -L" + dir
         elif sys.platform[:7] == "irix646" or sys.platform[:6] == "osf1V5":
             return ["-rpath", dir]
-        elif compiler[:3] == "gcc" or compiler[:3] == "g++":
-            return "-Wl,-R" + dir
         else:
-            return "-R" + dir
+            if compiler[:3] == "gcc" or compiler[:3] == "g++":
+                # gcc on non-GNU systems does not need -Wl, but can
+                # use it anyway.  Since distutils has always passed in
+                # -Wl whenever gcc was used in the past it is probably
+                # safest to keep doing so.
+                if sysconfig.get_config_var("GNULD") == "yes":
+                    # GNU ld needs an extra option to get a RUNPATH
+                    # instead of just an RPATH.
+                    return "-Wl,--enable-new-dtags,-R" + dir
+                else:
+                    return "-Wl,-R" + dir
+            else:
+                # No idea how --enable-new-dtags would be passed on to
+                # ld if this system was using GNU ld.  Don't know if a
+                # system like this even exists.
+                return "-R" + dir
 
     def library_option(self, lib):
         return "-l" + lib
diff --git a/Makefile.pre.in b/Makefile.pre.in
index d8b0abb..0a4b35e 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -36,6 +36,8 @@ AR=		@AR@
 RANLIB=		@RANLIB@
 SVNVERSION=	@SVNVERSION@
 
+GNULD=          @GNULD@
+
 # Shell used by make (some versions default to the login shell, which is bad)
 SHELL=		/bin/sh
 
diff --git a/configure b/configure
index 0c5c3e1..42d2945 100755
--- a/configure
+++ b/configure
@@ -693,6 +693,7 @@ LDLIBRARYDIR
 INSTSONAME
 RUNSHARED
 LINKCC
+GNULD
 RANLIB
 AR
 ARFLAGS
@@ -3949,6 +3950,27 @@ fi
 { echo "$as_me:$LINENO: result: $LINKCC" >&5
 echo "${ECHO_T}$LINKCC" >&6; }
 
+# GNULD is set to "yes" if the GNU linker is used.  If this goes wrong
+# make sure we default having it set to "no": this is used by
+# distutils.unixccompiler to know if it should add --enable-new-dtags
+# to linker command lines, and failing to detect GNU ld simply results
+# in the same bahaviour as before.
+
+{ echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; }
+ac_prog=ld
+if test "$GCC" = yes; then
+       ac_prog=`$CC -print-prog-name=ld`
+fi
+case `"$ac_prog" -V 2>&1 < /dev/null` in
+      *GNU*)
+          GNULD=yes;;
+      *)
+          GNULD=no;;
+esac
+{ echo "$as_me:$LINENO: result: $GNULD" >&5
+echo "${ECHO_T}$GNULD" >&6; }
+
 { echo "$as_me:$LINENO: checking for --enable-shared" >&5
 echo $ECHO_N "checking for --enable-shared... $ECHO_C" >&6; }
 # Check whether --enable-shared was given.
@@ -26096,6 +26118,7 @@ LDLIBRARYDIR!$LDLIBRARYDIR$ac_delim
 INSTSONAME!$INSTSONAME$ac_delim
 RUNSHARED!$RUNSHARED$ac_delim
 LINKCC!$LINKCC$ac_delim
+GNULD!$GNULD$ac_delim
 RANLIB!$RANLIB$ac_delim
 AR!$AR$ac_delim
 ARFLAGS!$ARFLAGS$ac_delim
@@ -26115,7 +26138,6 @@ BLDSHARED!$BLDSHARED$ac_delim
 CCSHARED!$CCSHARED$ac_delim
 LINKFORSHARED!$LINKFORSHARED$ac_delim
 CFLAGSFORSHARED!$CFLAGSFORSHARED$ac_delim
-SHLIBS!$SHLIBS$ac_delim
 _ACEOF
 
   if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
@@ -26157,6 +26179,7 @@ _ACEOF
 ac_delim='%!_!# '
 for ac_last_try in false false false false false :; do
   cat >conf$$subs.sed <<_ACEOF
+SHLIBS!$SHLIBS$ac_delim
 USE_SIGNAL_MODULE!$USE_SIGNAL_MODULE$ac_delim
 SIGNAL_OBJS!$SIGNAL_OBJS$ac_delim
 USE_THREAD_MODULE!$USE_THREAD_MODULE$ac_delim
@@ -26179,7 +26202,7 @@ SRCDIRS!$SRCDIRS$ac_delim
 LTLIBOBJS!$LTLIBOBJS$ac_delim
 _ACEOF
 
-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 20; then
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 21; then
     break
   elif $ac_last_try; then
     { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
diff --git a/configure.in b/configure.in
index 2591d8d..176e5cd 100644
--- a/configure.in
+++ b/configure.in
@@ -606,6 +606,25 @@ then
 fi
 AC_MSG_RESULT($LINKCC)
 
+# GNULD is set to "yes" if the GNU linker is used.  If this goes wrong
+# make sure we default having it set to "no": this is used by
+# distutils.unixccompiler to know if it should add --enable-new-dtags
+# to linker command lines, and failing to detect GNU ld simply results
+# in the same bahaviour as before.
+AC_SUBST(GNULD)
+AC_MSG_CHECKING(for GNU ld)
+ac_prog=ld
+if test "$GCC" = yes; then
+       ac_prog=`$CC -print-prog-name=ld`
+fi
+case `"$ac_prog" -V 2>&1 < /dev/null` in
+      *GNU*)
+          GNULD=yes;;
+      *)
+          GNULD=no;;
+esac
+AC_MSG_RESULT($GNULD)
+
 AC_MSG_CHECKING(for --enable-shared)
 AC_ARG_ENABLE(shared,
               AC_HELP_STRING(--enable-shared, disable/enable building shared python library))
-- 
cgit v0.12