diff --git a/Lib/distutils/tests/test_build_ext.py b/Lib/distutils/tests/test_build_ext.py index 5ea67bedb76..e4a02391af0 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 00000000000..94e9edfc094 --- /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 d65ab321b61..c11544d8283 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 d8b0abb73fe..0a4b35ec284 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 0c5c3e18bc9..42d294585db 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 2591d8dffbd..176e5cd4e6b 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))