Commit 625143f4 authored by Ben Gamari's avatar Ben Gamari Committed by Ben Gamari

configure: Coerce gcc to use $LD instead of system default

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
parent 007f2556
...@@ -590,7 +590,7 @@ AC_DEFUN([FP_SET_CFLAGS_C99], ...@@ -590,7 +590,7 @@ AC_DEFUN([FP_SET_CFLAGS_C99],
# FPTOOLS_SET_C_LD_FLAGS # 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 # $1 is the platform
# $2 is the name of the CC flags variable # $2 is the name of the CC flags variable
# $3 is the name of the linker flags variable when linking with gcc # $3 is the name of the linker flags variable when linking with gcc
...@@ -598,7 +598,6 @@ AC_DEFUN([FP_SET_CFLAGS_C99], ...@@ -598,7 +598,6 @@ AC_DEFUN([FP_SET_CFLAGS_C99],
# $5 is the name of the CPP flags variable # $5 is the name of the CPP flags variable
AC_DEFUN([FPTOOLS_SET_C_LD_FLAGS], AC_DEFUN([FPTOOLS_SET_C_LD_FLAGS],
[ [
FIND_LD([$$1],[UseLd])
AC_MSG_CHECKING([Setting up $2, $3, $4 and $5]) AC_MSG_CHECKING([Setting up $2, $3, $4 and $5])
case $$1 in case $$1 in
i386-*) i386-*)
...@@ -665,15 +664,6 @@ AC_DEFUN([FPTOOLS_SET_C_LD_FLAGS], ...@@ -665,15 +664,6 @@ AC_DEFUN([FPTOOLS_SET_C_LD_FLAGS],
esac 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. # If gcc knows about the stack protector, turn it off.
# Otherwise the stack-smash handler gets triggered. # Otherwise the stack-smash handler gets triggered.
echo 'int main(void) {return 0;}' > conftest.c echo 'int main(void) {return 0;}' > conftest.c
...@@ -2015,41 +2005,6 @@ AC_DEFUN([FIND_LLVM_PROG],[ ...@@ -2015,41 +2005,6 @@ AC_DEFUN([FIND_LLVM_PROG],[
fi 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_LD_COPY_BUG()
# ------------------- # -------------------
# Check for binutils bug #16177 present in some versions of the bfd ld # Check for binutils bug #16177 present in some versions of the bfd ld
...@@ -2284,4 +2239,63 @@ AC_DEFUN([FP_BFD_SUPPORT], [ ...@@ -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 # LocalWords: fi
...@@ -414,7 +414,6 @@ then ...@@ -414,7 +414,6 @@ then
# are screwed up. Configure doesn't think they're ever equal and # are screwed up. Configure doesn't think they're ever equal and
# so never tried without the prefix. # so never tried without the prefix.
AC_PATH_PROG([CC],[gcc], [clang]) AC_PATH_PROG([CC],[gcc], [clang])
AC_PATH_PROG([LD],[ld], [lld])
AC_PATH_PROG([NM],[nm]) AC_PATH_PROG([NM],[nm])
AC_PATH_PROG([AR],[ar]) AC_PATH_PROG([AR],[ar])
AC_PATH_PROG([RANLIB],[ranlib]) AC_PATH_PROG([RANLIB],[ranlib])
...@@ -530,9 +529,12 @@ FP_SET_CFLAGS_C99([CC_STAGE0],[CONF_CC_OPTS_STAGE0],[CONF_CPP_OPTS_STAGE0]) ...@@ -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_STAGE1],[CONF_CPP_OPTS_STAGE1])
FP_SET_CFLAGS_C99([CC],[CONF_CC_OPTS_STAGE2],[CONF_CPP_OPTS_STAGE2]) FP_SET_CFLAGS_C99([CC],[CONF_CC_OPTS_STAGE2],[CONF_CPP_OPTS_STAGE2])
dnl ** Which ld to use? dnl ** Choose a linker
dnl -------------------------------------------------------------- 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]) AC_SUBST([LdCmd])
dnl ** Which nm to use? dnl ** Which nm to use?
...@@ -694,7 +696,6 @@ FP_PROG_LD_BUILD_ID ...@@ -694,7 +696,6 @@ FP_PROG_LD_BUILD_ID
FP_PROG_LD_NO_COMPACT_UNWIND FP_PROG_LD_NO_COMPACT_UNWIND
FP_PROG_LD_FILELIST FP_PROG_LD_FILELIST
FPTOOLS_SET_C_LD_FLAGS([target],[CFLAGS],[LDFLAGS],[IGNORE_LINKER_LD_FLAGS],[CPPFLAGS]) 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([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]) FPTOOLS_SET_C_LD_FLAGS([target],[CONF_CC_OPTS_STAGE1],[CONF_GCC_LINKER_OPTS_STAGE1],[CONF_LD_LINKER_OPTS_STAGE1],[CONF_CPP_OPTS_STAGE1])
......
...@@ -84,23 +84,11 @@ FIND_LLVM_PROG([OPT], [opt], [$LlvmVersion]) ...@@ -84,23 +84,11 @@ FIND_LLVM_PROG([OPT], [opt], [$LlvmVersion])
OptCmd="$OPT" OptCmd="$OPT"
AC_SUBST([OptCmd]) AC_SUBST([OptCmd])
dnl ** Which ld to use?
dnl --------------------------------------------------------------
FIND_LD([$target],[LdCmd])
AC_SUBST([LdCmd])
FP_GCC_VERSION FP_GCC_VERSION
FP_GCC_SUPPORTS_NO_PIE FP_GCC_SUPPORTS_NO_PIE
AC_PROG_CPP 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 ** dnl ** Check gcc version and flags we need to pass it **
#
FP_GCC_EXTRA_FLAGS FP_GCC_EXTRA_FLAGS
FP_SET_CFLAGS_C99([CC],[CFLAGS],[CPPFLAGS]) FP_SET_CFLAGS_C99([CC],[CFLAGS],[CPPFLAGS])
...@@ -127,6 +115,19 @@ AC_SUBST(CONF_CPP_OPTS_STAGE0) ...@@ -127,6 +115,19 @@ AC_SUBST(CONF_CPP_OPTS_STAGE0)
AC_SUBST(CONF_CPP_OPTS_STAGE1) AC_SUBST(CONF_CPP_OPTS_STAGE1)
AC_SUBST(CONF_CPP_OPTS_STAGE2) 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 ** Set up the variables for the platform in the settings file.
dnl May need to use gcc to find platform details. dnl May need to use gcc to find platform details.
dnl -------------------------------------------------------------- dnl --------------------------------------------------------------
......
...@@ -169,6 +169,10 @@ def checkDynAsm(actual_file, normaliser): ...@@ -169,6 +169,10 @@ def checkDynAsm(actual_file, normaliser):
actual = actual_str.split() actual = actual_str.split()
if actual == ['initArray1', 'initArray2', 'ctors1', 'ctors2', 'success']: if actual == ['initArray1', 'initArray2', 'ctors1', 'ctors2', 'success']:
return 1 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']: elif actual == ['ctors1', 'ctors2', 'initArray1', 'initArray2', 'success']:
if_verbose(1, 'T5435_dyn_asm detected old-style dlopen, see #8458') if_verbose(1, 'T5435_dyn_asm detected old-style dlopen, see #8458')
return 1 return 1
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment