configure: Coerce gcc to use $LD instead of system default
authorBen Gamari <bgamari.foss@gmail.com>
Thu, 29 Jun 2017 23:38:51 +0000 (19:38 -0400)
committerBen Gamari <ben@smart-cactus.org>
Thu, 29 Jun 2017 23:38:52 +0000 (19:38 -0400)
The configure script will now try to coerce gcc to use the linker
pointed to by $LD instead of the system default (typically bfd ld).
Moreover, we now check for `ld.gold` and `ld.lld` before trying `ld`.

The previous behavior can be reverted to by using the new
--disable-ld-override flag.

On my machine gold seems to trigger an apparent infelicity in
constructor behavior, causing T5435_asm to fail. I've opened #13883 to
record this issue and have accepted the questionable constructor
ordering for the time being.

Test Plan: Validate with `config_args='--enable-ld-override'`

Reviewers: austin, hvr, simonmar

Subscribers: duog, nh2, rwbarton, thomie, erikd, snowleopard

GHC Trac Issues: #13541, #13810, #13883

Differential Revision: https://phabricator.haskell.org/D3449

aclocal.m4
configure.ac
distrib/configure.ac.in
testsuite/tests/rts/all.T

index b94f70b..677c0e7 100644 (file)
@@ -590,7 +590,7 @@ AC_DEFUN([FP_SET_CFLAGS_C99],
 
 # FPTOOLS_SET_C_LD_FLAGS
 # ----------------------------------
-# Set the C, LD and CPP flags for a given platform
+# Set the C, LD and CPP flags for a given platform.
 # $1 is the platform
 # $2 is the name of the CC flags variable
 # $3 is the name of the linker flags variable when linking with gcc
@@ -598,7 +598,6 @@ AC_DEFUN([FP_SET_CFLAGS_C99],
 # $5 is the name of the CPP flags variable
 AC_DEFUN([FPTOOLS_SET_C_LD_FLAGS],
 [
-    FIND_LD([$$1],[UseLd])
     AC_MSG_CHECKING([Setting up $2, $3, $4 and $5])
     case $$1 in
     i386-*)
@@ -665,15 +664,6 @@ AC_DEFUN([FPTOOLS_SET_C_LD_FLAGS],
 
     esac
 
-    case $UseLd in
-         *ld.gold)
-         $3="$$3 -fuse-ld=gold"
-         ;;
-         *ld.bfd)
-         $3="$$3 -fuse-ld=bfd"
-         ;;
-    esac
-
     # If gcc knows about the stack protector, turn it off.
     # Otherwise the stack-smash handler gets triggered.
     echo 'int main(void) {return 0;}' > conftest.c
@@ -2015,41 +2005,6 @@ AC_DEFUN([FIND_LLVM_PROG],[
     fi
 ])
 
-# FIND_LD
-# ---------
-# Find the version of `ld` to use. This is used in both in the top level
-# configure.ac and in distrib/configure.ac.in.
-#
-# $1 = the platform
-# $2 = the variable to set
-#
-AC_DEFUN([FIND_LD],[
-    AC_CHECK_TARGET_TOOL([LD], [ld])
-    case $1 in
-        arm*linux*       | \
-        aarch64*linux*   )
-            # Arm and Aarch64 requires use of the binutils ld.gold linker.
-            # This case should catch at least arm-unknown-linux-gnueabihf,
-            # arm-linux-androideabi, arm64-unknown-linux and
-            # aarch64-linux-android
-            AC_CHECK_TARGET_TOOL([LD_GOLD], [ld.gold])
-            if test "$LD_GOLD" != ""; then
-                $2="$LD_GOLD"
-            elif test `$LD --version | grep -c "GNU gold"` -gt 0; then
-                AC_MSG_NOTICE([ld is ld.gold])
-                $2="$LD"
-            else
-                AC_MSG_WARN([could not find ld.gold, falling back to $LD])
-                $2="$LD"
-            fi
-            ;;
-        *)
-            $2="$LD"
-            ;;
-    esac
-    CHECK_LD_COPY_BUG($1)
-])
-
 # CHECK_LD_COPY_BUG()
 # -------------------
 # Check for binutils bug #16177 present in some versions of the bfd ld
@@ -2284,4 +2239,63 @@ AC_DEFUN([FP_BFD_SUPPORT], [
     )
 ])
 
+
+# FP_CC_LINKER_FLAG_TRY()
+# --------------------
+# Try a particular linker to see whether we can use it. In particular, determine
+# whether we can convince gcc to use it via a -fuse-ld=... flag.
+#
+# $1 = the name of the linker to try
+# $2 = the variable to set with the appropriate GHC flag if the linker is
+# found to be usable
+AC_DEFUN([FP_CC_LINKER_FLAG_TRY], [
+    AC_MSG_CHECKING([whether C compiler supports -fuse-ld=$1])
+    echo 'int main(void) {return 0;}' > conftest.c
+    if $CC -o conftest.o -fuse-ld=$1 conftest.c > /dev/null 2>&1
+    then
+        $2="-fuse-ld=$1"
+        AC_MSG_RESULT([yes])
+    else
+        AC_MSG_RESULT([no])
+    fi
+    rm -f conftest.c conftest.o
+])
+
+# FIND_LD
+# ---------
+# Find the version of `ld` to use and figure out how to get gcc to use it for
+# linking (if --enable-ld-override is enabled). This is used in both in the top
+# level configure.ac and in distrib/configure.ac.in.
+#
+# $1 = the platform
+# $2 = the variable to set with GHC options to configure gcc to use the chosen linker
+#
+AC_DEFUN([FIND_LD],[
+    AC_ARG_ENABLE(ld-override,
+      [AC_HELP_STRING([--disable-ld-override],
+        [Prevent GHC from overriding the default linker used by gcc. If ld-override is enabled GHC will try to tell gcc to use whichever linker is selected by the LD environment variable. [default=override enabled]])],
+      [],
+      [enable_ld_override=yes])
+
+    if test "x$enable_ld_override" = "xyes"; then
+        AC_CHECK_TARGET_TOOLS([LD], [ld.gold ld.lld ld])
+        UseLd=''
+
+        out=`$LD --version`
+        case $out in
+          "GNU ld"*)   FP_CC_LINKER_FLAG_TRY(bfd, $2) ;;
+          "GNU gold"*) FP_CC_LINKER_FLAG_TRY(gold, $2) ;;
+          "LLD"*)      FP_CC_LINKER_FLAG_TRY(lld, $2) ;;
+          *) AC_MSG_NOTICE([unknown linker version $out]) ;;
+        esac
+        if test "z$2" = "z"; then
+            AC_MSG_NOTICE([unable to convince '$CC' to use linker '$LD'])
+        fi
+   else
+        AC_CHECK_TARGET_TOOL([LD], [ld])
+   fi
+
+   CHECK_LD_COPY_BUG([$1])
+])
+
 # LocalWords:  fi
index c0961cf..92d3714 100644 (file)
@@ -414,7 +414,6 @@ then
     # are screwed up. Configure doesn't think they're ever equal and
     # so never tried without the prefix.
     AC_PATH_PROG([CC],[gcc], [clang])
-    AC_PATH_PROG([LD],[ld], [lld])
     AC_PATH_PROG([NM],[nm])
     AC_PATH_PROG([AR],[ar])
     AC_PATH_PROG([RANLIB],[ranlib])
@@ -530,9 +529,12 @@ FP_SET_CFLAGS_C99([CC_STAGE0],[CONF_CC_OPTS_STAGE0],[CONF_CPP_OPTS_STAGE0])
 FP_SET_CFLAGS_C99([CC],[CONF_CC_OPTS_STAGE1],[CONF_CPP_OPTS_STAGE1])
 FP_SET_CFLAGS_C99([CC],[CONF_CC_OPTS_STAGE2],[CONF_CPP_OPTS_STAGE2])
 
-dnl ** Which ld to use?
+dnl ** Choose a linker
 dnl --------------------------------------------------------------
-FIND_LD([$target],[LdCmd])
+FIND_LD([$target],[GccUseLdOpt])
+CONF_GCC_LINKER_OPTS_STAGE1="$CONF_GCC_LINKER_OPTS_STAGE1 $GccUseLdOpt"
+CONF_GCC_LINKER_OPTS_STAGE2="$CONF_GCC_LINKER_OPTS_STAGE2 $GccUseLdOpt"
+LdCmd="$LD"
 AC_SUBST([LdCmd])
 
 dnl ** Which nm to use?
@@ -694,7 +696,6 @@ FP_PROG_LD_BUILD_ID
 FP_PROG_LD_NO_COMPACT_UNWIND
 FP_PROG_LD_FILELIST
 
-
 FPTOOLS_SET_C_LD_FLAGS([target],[CFLAGS],[LDFLAGS],[IGNORE_LINKER_LD_FLAGS],[CPPFLAGS])
 FPTOOLS_SET_C_LD_FLAGS([build],[CONF_CC_OPTS_STAGE0],[CONF_GCC_LINKER_OPTS_STAGE0],[CONF_LD_LINKER_OPTS_STAGE0],[CONF_CPP_OPTS_STAGE0])
 FPTOOLS_SET_C_LD_FLAGS([target],[CONF_CC_OPTS_STAGE1],[CONF_GCC_LINKER_OPTS_STAGE1],[CONF_LD_LINKER_OPTS_STAGE1],[CONF_CPP_OPTS_STAGE1])
index cea3c49..53c79e1 100644 (file)
@@ -84,23 +84,11 @@ FIND_LLVM_PROG([OPT], [opt], [$LlvmVersion])
 OptCmd="$OPT"
 AC_SUBST([OptCmd])
 
-dnl ** Which ld to use?
-dnl --------------------------------------------------------------
-FIND_LD([$target],[LdCmd])
-AC_SUBST([LdCmd])
-
 FP_GCC_VERSION
 FP_GCC_SUPPORTS_NO_PIE
 AC_PROG_CPP
 
-FP_PROG_LD_IS_GNU
-FP_PROG_LD_BUILD_ID
-FP_PROG_LD_NO_COMPACT_UNWIND
-FP_PROG_LD_FILELIST
-
-#
 dnl ** Check gcc version and flags we need to pass it **
-#
 FP_GCC_EXTRA_FLAGS
 
 FP_SET_CFLAGS_C99([CC],[CFLAGS],[CPPFLAGS])
@@ -127,6 +115,19 @@ AC_SUBST(CONF_CPP_OPTS_STAGE0)
 AC_SUBST(CONF_CPP_OPTS_STAGE1)
 AC_SUBST(CONF_CPP_OPTS_STAGE2)
 
+dnl ** Which ld to use?
+dnl --------------------------------------------------------------
+FIND_LD([$target],[GccUseLdOpt])
+CONF_GCC_LINKER_OPTS_STAGE1="$CONF_GCC_LINKER_OPTS_STAGE1 $GccUseLdOpt"
+CONF_GCC_LINKER_OPTS_STAGE2="$CONF_GCC_LINKER_OPTS_STAGE2 $GccUseLdOpt"
+LdCmd="$LD"
+AC_SUBST([LdCmd])
+
+FP_PROG_LD_IS_GNU
+FP_PROG_LD_BUILD_ID
+FP_PROG_LD_NO_COMPACT_UNWIND
+FP_PROG_LD_FILELIST
+
 dnl ** Set up the variables for the platform in the settings file.
 dnl May need to use gcc to find platform details.
 dnl --------------------------------------------------------------
index f32a35b..e02f880 100644 (file)
@@ -169,6 +169,10 @@ def checkDynAsm(actual_file, normaliser):
     actual = actual_str.split()
     if actual == ['initArray1', 'initArray2', 'ctors1', 'ctors2', 'success']:
         return 1
+    elif actual == ['initArray1', 'initArray2', 'ctors2', 'ctors1', 'success']:
+        # gold seems to produce this ordering; this is slightly odd but if it's
+        # wrong it's not our fault. See #13883.
+        return 1
     elif actual == ['ctors1', 'ctors2', 'initArray1', 'initArray2', 'success']:
         if_verbose(1, 'T5435_dyn_asm detected old-style dlopen, see #8458')
         return 1