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],
# 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
......@@ -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])
......
......@@ -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 --------------------------------------------------------------
......
......@@ -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
......
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