[Git][ghc/ghc][wip/ghc-toolchain-fixes] 16 commits: Add some javascript special cases to ghc-toolchain

Matthew Pickering (@mpickering) gitlab at gitlab.haskell.org
Wed Aug 9 11:27:04 UTC 2023



Matthew Pickering pushed to branch wip/ghc-toolchain-fixes at Glasgow Haskell Compiler / GHC


Commits:
161d92a0 by Matthew Pickering at 2023-08-09T12:18:09+01:00
Add some javascript special cases to ghc-toolchain

On javascript there isn't a choice of toolchain but some of the
configure checks were not accurately providing the correct answer.

1. The linker was reported as gnu LD because the --version output
   mentioned gnu LD.
2. The --target flag makes no sense on javascript but it was just
   ignored by the linker, so we add a special case to stop ghc-toolchain
   thinking that emcc supports --target when used as a linker.

- - - - -
f0ecbedf by Matthew Pickering at 2023-08-09T12:20:31+01:00
check for emcc in gnu_LD check

- - - - -
95604c12 by Matthew Pickering at 2023-08-09T12:25:53+01:00
Add ldOverrideWhitelist to only default to ldOverride on windows/linux

On some platforms - ie darwin, javascript etc we really do not want to
allow the user to use any linker other than the default one as this
leads to all kinds of bugs. Therefore it is a bit more prudant to add a
whitelist which specifies on which platforms it might be possible to use
a different linker.

- - - - -
fd8e5888 by Matthew Pickering at 2023-08-09T12:26:53+01:00
Fix plaform glob in FPTOOLS_SET_C_LD_FLAGS

A normal triple may look like

x86_64-unknown-linux

but when cross-compiling you get $target set to a quad such as..

aarch64-unknown-linux-gnu

Which should also match this check.

- - - - -
518c02fa by Matthew Pickering at 2023-08-09T12:26:53+01:00
ghc-toolchain: Pass ld-override onto ghc-toolchain

- - - - -
d6377861 by Matthew Pickering at 2023-08-09T12:26:53+01:00
ld override: Make whitelist override user given option

- - - - -
d2799acc by Matthew Pickering at 2023-08-09T12:26:53+01:00
ghc-toolchain: Add format mode to normalise differences before diffing.

The "format" mode takes an "--input" and "--ouput" target file and
formats it.

This is intended to be useful on windows where the
configure/ghc-toolchain target files can't be diffed very easily because
the path separators are different.

- - - - -
20235c76 by Matthew Pickering at 2023-08-09T12:26:53+01:00
ghc-toolchain: Bump ci-images commit to get new ghc-wasm-meta

We needed to remove -Wno-unused-command-line-argument from the arguments
passed in order for the configure check to report correctly.

See https://gitlab.haskell.org/ghc/ghc/-/merge_requests/10976#note_516335

- - - - -
01132101 by Matthew Pickering at 2023-08-09T12:26:53+01:00
configure: MergeObjsCmd - distinguish between empty string and unset variable

If `MergeObjsCmd` is explicitly set to the empty string then we should
assume that MergeObjs is just not supported.

This is especially important for windows where we set MergeObjsCmd to ""
in m4/fp_setup_windows_toolchain.m4.

- - - - -
e01f687d by Matthew Pickering at 2023-08-09T12:26:53+01:00
configure: Add proper check to see if object merging works

- - - - -
a8ec9f6e by Matthew Pickering at 2023-08-09T12:26:53+01:00
ghc-toolchain: If MergeObjsCmd is not set, replace setting with Nothing

If the user explicitly chooses to not set a MergeObjsCmd then it is
correct to use Nothing for tgtMergeObjs field in the Target file.

- - - - -
207cb97c by Matthew Pickering at 2023-08-09T12:26:53+01:00
HsCppArgs: Augment the HsCppOptions

This is important when we pass -I when setting up the windows toolchain.

- - - - -
209beb6e by Matthew Pickering at 2023-08-09T12:26:54+01:00
Set USER_CPP_ARGS when setting up windows toolchain

- - - - -
032beecd by Rodrigo Mesquita at 2023-08-09T12:26:54+01:00
Improve handling of Cc as a fallback

- - - - -
688393a3 by Rodrigo Mesquita at 2023-08-09T12:26:54+01:00
ghc-toolchain: Configure Cpp and HsCpp correctly when user specifies flags

In ghc-toolchain, we were only /not/ configuring required flags when the
user specified any flags at all for the  of the HsCpp and Cpp tools.

Otherwise, the linker takes into consideration the user specified flags
to determine whether to search for a better linker implementation, but
already configured the remaining GHC and platform-specific flags
regardless of the user options.

Other Tools consider the user options as a baseline for further
configuration (see `findProgram`), so #23689 is not applicable.

Closes #23689

- - - - -
31cceda9 by Matthew Pickering at 2023-08-09T12:26:54+01:00
CPP_ARGS: Put new options after user specified options

This matches up with the behaviour of ghc-toolchain, so that the output
of both matches.

- - - - -


16 changed files:

- .gitlab-ci.yml
- configure.ac
- distrib/configure.ac.in
- hadrian/cfg/default.target.in
- m4/find_merge_objects.m4
- m4/fp_cpp_cmd_with_args.m4
- m4/fp_hs_cpp_cmd_with_args.m4
- m4/fp_prog_ld_is_gnu.m4
- m4/fp_setup_windows_toolchain.m4
- m4/fptools_set_c_ld_flags.m4
- m4/ghc_toolchain.m4
- m4/prep_target_file.m4
- utils/ghc-toolchain/exe/Main.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Program.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Tools/Cpp.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Tools/Link.hs


Changes:

=====================================
.gitlab-ci.yml
=====================================
@@ -2,7 +2,7 @@ variables:
   GIT_SSL_NO_VERIFY: "1"
 
   # Commit of ghc/ci-images repository from which to pull Docker images
-  DOCKER_REV: a9c0f5efbe503c17f63070583b2d815e498acc68
+  DOCKER_REV: 17f816b010d4e585d3a935530ea3d1fc743eac0d
 
   # Sequential version number of all cached things.
   # Bump to invalidate GitLab CI cache.


=====================================
configure.ac
=====================================
@@ -1204,8 +1204,9 @@ checkMake380 make
 checkMake380 gmake
 
 # Toolchain target files
+FIND_GHC_TOOLCHAIN_BIN([NO])
 PREP_TARGET_FILE
-FIND_GHC_TOOLCHAIN([hadrian/cfg],[NO])
+FIND_GHC_TOOLCHAIN([hadrian/cfg])
 
 AC_CONFIG_FILES(
 [ mk/project.mk
@@ -1343,3 +1344,5 @@ For more information on how to configure your GHC build, see
 
 VALIDATE_GHC_TOOLCHAIN([hadrian/cfg/default.target],[hadrian/cfg/default.target.ghc-toolchain])
 
+rm -Rf acargs acghc-toolchain actmp-ghc-toolchain
+


=====================================
distrib/configure.ac.in
=====================================
@@ -315,11 +315,14 @@ checkMake380 make
 checkMake380 gmake
 
 # Toolchain target files
+FIND_GHC_TOOLCHAIN_BIN([YES])
 PREP_TARGET_FILE
-FIND_GHC_TOOLCHAIN([.],[YES])
+FIND_GHC_TOOLCHAIN([.])
 
 VALIDATE_GHC_TOOLCHAIN([default.target],[default.target.ghc-toolchain])
 
+rm -Rf acargs acghc-toolchain actmp-ghc-toolchain
+
 echo "****************************************************"
 echo "Configuration done, ready to 'make install'"
 echo "(see README and INSTALL files for more info.)"


=====================================
hadrian/cfg/default.target.in
=====================================
@@ -34,6 +34,6 @@ Target
 
 , tgtRanlib = Just (Ranlib {ranlibProgram = Program {prgPath = "@RanlibCmd@", prgFlags = []}})
 , tgtNm = Nm {nmProgram = Program {prgPath = "@NmCmd@", prgFlags = []}}
-, tgtMergeObjs = Just (MergeObjs {mergeObjsProgram = Program {prgPath = "@MergeObjsCmd@", prgFlags = @MergeObjsArgsList@}, mergeObjsSupportsResponseFiles = @MergeObjsSupportsResponseFilesBool@})
+, tgtMergeObjs = @MergeObjsCmdMaybe@
 , tgtWindres = @WindresCmdMaybeProg@
 }


=====================================
m4/find_merge_objects.m4
=====================================
@@ -3,25 +3,59 @@
 # Find which linker to use to merge object files.
 #
 # See Note [Merging object files for GHCi] in GHC.Driver.Pipeline.
+
+
+AC_DEFUN([CHECK_MERGE_OBJECTS],[
+  AC_REQUIRE([FP_FIND_NM])
+  AC_MSG_NOTICE([Checking whether $MergeObjsCmd can merge objects])
+  echo 'int funA(int x) {return x;}' > conftesta.c
+  echo 'int funB(int x) {return x;}' > conftestb.c
+  $CC -c -o conftesta.o conftesta.c
+  $CC -c -o conftestb.o conftestb.c
+  $MergeObjsCmd $MergeObjsArgs conftesta.o conftestb.o -o conftestc.o || AC_MSG_ERROR([ $MergeObjsCmd could not merge objects ])
+
+  # Check the resulting object file has both functions.
+  $NM conftestc.o | grep funA > /dev/null 2>&1 || AC_MSG_ERROR([ $MergeObjsCmd could not merge objects ])
+  $NM conftestc.o | grep funB > /dev/null 2>&1 || AC_MSG_ERROR([ $MergeObjsCmd could not merge objects ])
+
+  rm -r conftest*.c conftest*.o
+])
+
 AC_DEFUN([FIND_MERGE_OBJECTS],[
     AC_REQUIRE([FIND_LD])
 
-    if test -z "$MergeObjsCmd"; then
+    if test -z ${MergeObjsCmd+x}; then
+        AC_MSG_NOTICE([Setting cmd])
         MergeObjsCmd="$(command -v $LD)"
     fi
-    if test -z "$MergeObjsArgs"; then
+    if test -z ${MergeObjsArgs+x}; then
         MergeObjsArgs="-r"
     fi
 
-    CHECK_FOR_GOLD_T22266($MergeObjsCmd)
-    if test "$result" = "1"; then
-        AC_MSG_NOTICE([$MergeObjsCmd is broken due to binutils 22266, looking for another linker...])
-        MergeObjsCmd=""
-        AC_CHECK_TARGET_TOOL([MergeObjsCmd], [ld])
-        CHECK_FOR_GOLD_T22266($MergeObjsCmd)
-        if test "$result" = "1"; then
-            AC_MSG_ERROR([Linker is affected by binutils 22266 but couldn't find another unaffected linker. Please set the MergeObjsCmd variable to a functional linker.])
-        fi
+
+    # If MergeObjsCmd="" then we assume that the user is explicitly telling us that
+    # they do not want to configure the MergeObjsCmd, this is particularly important for
+    # the bundled windows toolchain.
+    if test -z "$MergeObjsCmd"; then
+      AC_MSG_NOTICE([No command for merging objects as explicitly instructed by user])
+
+    else
+      # Check first that gold works
+      CHECK_FOR_GOLD_T22266($MergeObjsCmd)
+      if test "$result" = "1"; then
+          AC_MSG_NOTICE([$MergeObjsCmd is broken due to binutils 22266, looking for another linker...])
+          MergeObjsCmd=""
+          AC_CHECK_TARGET_TOOL([MergeObjsCmd], [ld])
+          CHECK_FOR_GOLD_T22266($MergeObjsCmd)
+          if test "$result" = "1"; then
+              AC_MSG_ERROR([Linker is affected by binutils 22266 but couldn't find another unaffected linker. Please set the MergeObjsCmd variable to a functional linker.])
+          fi
+
+      fi
+
+      # Now just check that merging objects works at all
+      CHECK_MERGE_OBJECTS()
+
     fi
 
     AC_SUBST([MergeObjsCmd])


=====================================
m4/fp_cpp_cmd_with_args.m4
=====================================
@@ -51,7 +51,7 @@ AC_ARG_WITH(cpp-flags,
 [
   # Augment CPP_ARGS with whatever flags were previously configured and passed
   # as an argument.
-  CPP_ARGS="$CPP_ARGS $$3"
+  CPP_ARGS="$$3 $CPP_ARGS"
 ])
 
 $2="$CPP_CMD"


=====================================
m4/fp_hs_cpp_cmd_with_args.m4
=====================================
@@ -64,6 +64,6 @@ AC_ARG_WITH(hs-cpp-flags,
 )
 
 $1=$HS_CPP_CMD
-$2=$HS_CPP_ARGS
+$2="$$2 $HS_CPP_ARGS"
 
 ])


=====================================
m4/fp_prog_ld_is_gnu.m4
=====================================
@@ -4,10 +4,19 @@
 # GNU ld or not.
 AC_DEFUN([FP_PROG_LD_IS_GNU],[
 AC_CACHE_CHECK([whether ld is GNU ld], [fp_cv_gnu_ld],
-[[if $LD --version 2> /dev/null | grep "GNU" > /dev/null 2>&1; then
-  fp_cv_gnu_ld=YES
-else
+[[
+
+if $LD --version 2> /dev/null | grep "emcc" > /dev/null 2>&1;
+then
   fp_cv_gnu_ld=NO
-fi]])
+else
+  if $LD --version 2> /dev/null | grep "GNU" > /dev/null 2>&1; then
+    fp_cv_gnu_ld=YES
+  else
+    fp_cv_gnu_ld=NO
+  fi
+fi
+
+]])
 AC_SUBST([LdIsGNULd],["$fp_cv_gnu_ld"])
 ])# FP_PROG_LD_IS_GNU


=====================================
m4/fp_setup_windows_toolchain.m4
=====================================
@@ -133,6 +133,7 @@ AC_DEFUN([FP_SETUP_WINDOWS_TOOLCHAIN],[
     dnl configuration to the bundled windows toolchain, and these are the
     dnl options required by the bundled windows toolchain.
     USER_CFLAGS="$CFLAGS"
+    USER_CPP_ARGS="$CONF_CPP_OPTS_STAGE2"
     USER_CXXFLAGS="$CXXFLAGS"
     USER_HS_CPP_ARGS="$HaskellCPPArgs"
     USER_LDFLAGS="$CONF_GCC_LINKER_OPTS_STAGE2"


=====================================
m4/fptools_set_c_ld_flags.m4
=====================================
@@ -19,7 +19,7 @@ AC_DEFUN([FPTOOLS_SET_C_LD_FLAGS],
 
     # See Note [ELF needed shared libs]
     case $$1 in
-    *-linux|*-freebsd*)
+    *-linux*|*-freebsd*)
         FP_LINK_SUPPORTS_NO_AS_NEEDED([$3])
         ;;
     esac


=====================================
m4/ghc_toolchain.m4
=====================================
@@ -24,8 +24,12 @@ AC_DEFUN([ENABLE_GHC_TOOLCHAIN_ARG],
 [
     if test "$2" = "YES"; then
         echo "--enable-$1" >> acargs
+    elif test "$2" = "yes"; then
+        echo "--enable-$1" >> acargs
     elif test "$2" = "NO"; then
         echo "--disable-$1" >> acargs
+    elif test "$2" = "no"; then
+        echo "--disable-$1" >> acargs
     fi
 ])
 
@@ -35,6 +39,10 @@ AC_DEFUN([ENABLE_GHC_TOOLCHAIN_NOT_ARG],
         echo "--enable-$1" >> acargs
     elif test "$2" = "YES"; then
         echo "--disable-$1" >> acargs
+    elif test "$2" = "no"; then
+        echo "--enable-$1" >> acargs
+    elif test "$2" = "yes"; then
+        echo "--disable-$1" >> acargs
     fi
 ])
 
@@ -52,31 +60,8 @@ AC_DEFUN([INVOKE_GHC_TOOLCHAIN],
 ])
 
 dnl $1 is the path to the directory where to put the configured default.host.target.ghc-toolchain and default.target.ghc-toolchain
-dnl $2 is YES or NO,
-dnl     * YES means we're calling GHC_TOOLCHAIN from the bindist configure script,
-dnl         and that ghc-toolchain is already an available binary
-dnl     * NO means we're calling GHC_TOOLCHAIN from the source tree configure script,
-dnl         and that we must compile ghc-toolchain before invoking it
 AC_DEFUN([FIND_GHC_TOOLCHAIN],
 [
-    case "$2" in
-        YES)
-            # We're configuring the bindist, and the binary is already available
-            GHC_TOOLCHAIN_BIN="bin/ghc-toolchain-bin"
-            ;;
-        NO)
-            # We're in the source tree, so compile ghc-toolchain
-            "$GHC" -v0 \
-                -ilibraries/ghc-platform/src -iutils/ghc-toolchain/src \
-                -XNoImplicitPrelude \
-                -odir actmp-ghc-toolchain -hidir actmp-ghc-toolchain \
-                utils/ghc-toolchain/exe/Main.hs -o acghc-toolchain
-            GHC_TOOLCHAIN_BIN="./acghc-toolchain"
-            ;;
-        *)
-            AC_MSG_ERROR([In m4/ghc_toolchain.m4, expecting $2 to be either YES or NO.])
-            ;;
-    esac
 
     # (1) Configure a toolchain for the build and host platform (we require that BUILD=HOST, so one toolchain suffices)
     rm -f acargs
@@ -137,18 +122,43 @@ AC_DEFUN([FIND_GHC_TOOLCHAIN],
 
     INVOKE_GHC_TOOLCHAIN()
 
-    rm -Rf acargs acghc-toolchain actmp-ghc-toolchain
-
     dnl Note: if we weren't passing the paths to the programs explicitly, to make
     dnl ghc-toolchain use the bundled windows toolchain, simply add it to the search PATH
 ])
 
 
+dnl $1 is YES or NO,
+dnl     * YES means we're calling GHC_TOOLCHAIN from the bindist configure script,
+dnl         and that ghc-toolchain is already an available binary
+dnl     * NO means we're calling GHC_TOOLCHAIN from the source tree configure script,
+dnl         and that we must compile ghc-toolchain before invoking it
+AC_DEFUN([FIND_GHC_TOOLCHAIN_BIN],[
+    case "$1" in
+        YES)
+            # We're configuring the bindist, and the binary is already available
+            GHC_TOOLCHAIN_BIN="bin/ghc-toolchain-bin"
+            ;;
+        NO)
+            # We're in the source tree, so compile ghc-toolchain
+            "$GHC" -v0 \
+                -ilibraries/ghc-platform/src -iutils/ghc-toolchain/src \
+                -XNoImplicitPrelude \
+                -odir actmp-ghc-toolchain -hidir actmp-ghc-toolchain \
+                utils/ghc-toolchain/exe/Main.hs -o acghc-toolchain
+            GHC_TOOLCHAIN_BIN="./acghc-toolchain"
+            ;;
+        *)
+            AC_MSG_ERROR([In m4/ghc_toolchain.m4, expecting $2 to be either YES or NO.])
+            ;;
+    esac
+])
+
+
 dnl Note [ghc-toolchain consistency checking]
 dnl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 dnl ghc-toolchain is the brand new way (2023) to configure toolchains for GHC,
 dnl but this novelty musn't break user's installations, so we still
-dnl conservatively use the toolchains configured by configure (see also m4/prep_target_file.m4).
+dnl conservatively use the toolchains configured by configure (see also m4/tprep_target_file.m4).
 dnl
 dnl However, we already ship and run ghc-toolchain at configure time to /validate/ ghc-toolchain:
 dnl * PREP_TARGET_FILE substitutes the toolchain into default.target.in and default.host.target.in
@@ -163,7 +173,11 @@ dnl files generated by ghc-toolchain instead).
 dnl $1 like "default.target"
 dnl $2 like "default.target.ghc-toolchain"
 AC_DEFUN([VALIDATE_GHC_TOOLCHAIN],[
-    diff_output=`diff "$1" "$2" 2>&1`
+    o1=$(mktemp)
+    o2=$(mktemp)
+    "$GHC_TOOLCHAIN_BIN" format --input="$1" --output="$o1"
+    "$GHC_TOOLCHAIN_BIN" format --input="$2" --output="$o2"
+    diff_output=`diff "$o1" "$o2" 2>&1`
     if test -z "$diff_output"; then
       true
     else


=====================================
m4/prep_target_file.m4
=====================================
@@ -160,6 +160,14 @@ AC_DEFUN([PREP_TARGET_FILE],[
     PREP_LIST([CONF_CXX_OPTS_STAGE0])
     PREP_LIST([CONF_GCC_LINKER_OPTS_STAGE0])
 
+
+    if test -z "$MergeObjsCmd"; then
+      MergeObjsCmdMaybe=Nothing
+    else
+      MergeObjsCmdMaybe="Just (MergeObjs {mergeObjsProgram = Program {prgPath = \"$MergeObjsCmd\", prgFlags = $MergeObjsArgsList}, mergeObjsSupportsResponseFiles = $MergeObjsSupportsResponseFilesBool})"
+    fi
+    AC_SUBST([MergeObjsCmdMaybe])
+
     dnl PREP_ENDIANNESS
     case "$TargetWordBigEndian" in
         YES)


=====================================
utils/ghc-toolchain/exe/Main.hs
=====================================
@@ -1,5 +1,6 @@
 {-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE TypeApplications #-}
 
 module Main where
 
@@ -10,6 +11,7 @@ import System.Exit
 import System.Console.GetOpt
 import System.Environment
 import System.FilePath ((</>))
+import qualified System.IO (readFile, writeFile)
 
 import GHC.Platform.ArchOS
 
@@ -55,6 +57,22 @@ data Opts = Opts
     , optKeepTemp  :: Bool
     }
 
+data FormatOpts = FormatOpts
+    { formatOptInput :: FilePath
+    , formatOptOutput :: FilePath
+    }
+
+_formatOptOutput :: Lens FormatOpts String
+_formatOptOutput = Lens formatOptOutput (\x o -> o {formatOptOutput=x})
+
+_formatOptInput :: Lens FormatOpts String
+_formatOptInput = Lens formatOptInput (\x o -> o {formatOptInput=x})
+
+emptyFormatOpts :: FormatOpts
+emptyFormatOpts = FormatOpts { formatOptInput = error "formatOpts: input"
+                             , formatOptOutput = error "formatOpts: output"
+                             }
+
 emptyOpts :: Opts
 emptyOpts = Opts
     { optTriple    = ""
@@ -202,10 +220,41 @@ options =
     outputOpt = Option ['o'] ["output"] (ReqArg (set _optOutput) "OUTPUT")
         "The output path for the generated target toolchain configuration"
 
+formatOpts :: [OptDescr (FormatOpts -> FormatOpts)]
+formatOpts = [
+    (Option ['o'] ["output"] (ReqArg (set _formatOptOutput) "OUTPUT")
+        "The output path for the formatted target toolchain configuration")
+    , (Option ['i'] ["input"] (ReqArg (set _formatOptInput) "INPUT")
+        "The target file to format")
+    ]
+
 main :: IO ()
 main = do
     argv <- getArgs
-    let (opts0, _nonopts, errs) = getOpt RequireOrder options argv
+    case argv of
+      ("format": args) -> doFormat args
+      _ -> doConfigure argv
+
+-- The format mode is very useful for normalising paths and newlines on windows.
+doFormat :: [String] -> IO ()
+doFormat args = do
+  let (opts0, _nonopts, errs) = getOpt RequireOrder formatOpts args
+  case errs of
+    [] -> do
+      let opts = foldr (.) id opts0 emptyFormatOpts
+      tgt <- read @Target <$> System.IO.readFile (view _formatOptInput opts)
+      let file = formatOptOutput opts
+      System.IO.writeFile file (show tgt)
+    _ -> do
+      mapM_ putStrLn errs
+      putStrLn $ usageInfo "ghc-toolchain" formatOpts
+      exitWith (ExitFailure 1)
+
+
+
+doConfigure :: [String] -> IO ()
+doConfigure args = do
+    let (opts0, _nonopts, errs) = getOpt RequireOrder options args
     let opts = foldr (.) id opts0 emptyOpts
     case errs of
       [] -> do
@@ -309,6 +358,15 @@ archHasNativeAdjustors = \case
   _          -> False
 
 
+-- | The platforms which we attempt to override ld
+ldOverrideWhitelist :: ArchOS -> Bool
+ldOverrideWhitelist a =
+  case archOS_OS a of
+    OSLinux   -> True
+    OSMinGW32 -> True
+    _ -> False
+
+
 mkTarget :: Opts -> M Target
 mkTarget opts = do
     -- Use Llvm target if specified, otherwise use triple as llvm target
@@ -320,7 +378,7 @@ mkTarget opts = do
     (archOs, tgtVendor) <- parseTriple cc0 (optTriple opts)
     cc <- addPlatformDepCcFlags archOs cc0
     readelf <- optional $ findReadelf (optReadelf opts)
-    ccLink <- findCcLink tgtLlvmTarget (optCcLink opts) (fromMaybe True (optLdOverride opts)) archOs cc readelf
+    ccLink <- findCcLink tgtLlvmTarget (optCcLink opts) (ldOverrideWhitelist archOs && fromMaybe True (optLdOverride opts)) archOs cc readelf
 
     ar <- findAr tgtVendor (optAr opts)
     -- TODO: We could have


=====================================
utils/ghc-toolchain/src/GHC/Toolchain/Program.hs
=====================================
@@ -2,6 +2,7 @@ module GHC.Toolchain.Program
     ( Program(..)
     , _prgPath
     , _prgFlags
+    , addFlagIfNew
       -- * Running programs
     , runProgram
     , callProgram
@@ -10,6 +11,7 @@ module GHC.Toolchain.Program
       -- * Finding 'Program's
     , ProgOpt(..)
     , emptyProgOpt
+    , programFromOpt
     , _poPath
     , _poFlags
     , findProgram
@@ -33,7 +35,12 @@ import GHC.Toolchain.Utils
 data Program = Program { prgPath :: FilePath
                        , prgFlags :: [String]
                        }
-    deriving (Show, Read, Eq, Ord)
+    deriving (Read, Eq, Ord)
+
+instance Show Program where
+  -- Normalise filepaths before showing to aid with diffing the target files.
+  show (Program p f) = unwords
+    [ "Program { prgPath = ", show (normalise p), ", prgFlags =", show f , "}"]
 
 _prgPath :: Lens Program FilePath
 _prgPath = Lens prgPath (\x o -> o {prgPath = x})
@@ -41,6 +48,13 @@ _prgPath = Lens prgPath (\x o -> o {prgPath = x})
 _prgFlags :: Lens Program [String]
 _prgFlags = Lens prgFlags (\x o -> o {prgFlags = x})
 
+-- | Prepends a flag to a program's flags if the flag is not in the existing flags.
+addFlagIfNew :: String -> Program -> Program
+addFlagIfNew flag prog@(Program path flags)
+  = if flag `elem` flags
+       then prog
+       else Program path (flags ++ [flag])
+
 runProgram :: Program -> [String] -> M ExitCode
 runProgram prog args = do
     logExecute prog args
@@ -98,6 +112,14 @@ _poFlags = Lens poFlags (\x o -> o {poFlags=x})
 emptyProgOpt :: ProgOpt
 emptyProgOpt = ProgOpt Nothing Nothing
 
+-- | Make a @'Program'@ from user specified program options (@'ProgOpt'@),
+-- defaulting to the given path and flags if unspecified in the @'ProgOpt'@.
+programFromOpt :: ProgOpt
+               -> FilePath -- ^ Program path to default to
+               -> [String] -- ^ Program flags to default to
+               -> Program
+programFromOpt userSpec path flags = Program { prgPath = fromMaybe path (poPath userSpec), prgFlags = fromMaybe flags (poFlags userSpec) }
+
 -- | Tries to find the user specified program by path or tries to look for one
 -- in the given list of candidates.
 --


=====================================
utils/ghc-toolchain/src/GHC/Toolchain/Tools/Cpp.hs
=====================================
@@ -24,17 +24,14 @@ newtype HsCpp = HsCpp { hsCppProgram :: Program
 
 findHsCpp :: ProgOpt -> Cc -> M HsCpp
 findHsCpp progOpt cc = checking "for Haskell C preprocessor" $ do
-  -- Use the specified HS CPP or try to find one (candidate is the c compiler)
-  foundHsCppProg <- findProgram "Haskell C preprocessor" progOpt [takeFileName $ prgPath $ ccProgram cc]
-  case poFlags progOpt of
-    -- If the user specified HS CPP flags don't second-guess them
-    Just _ -> return HsCpp{hsCppProgram=foundHsCppProg}
-    -- Otherwise, configure the HS CPP flags for this CPP program
-    Nothing -> do
-      let rawHsCppProgram = over _prgFlags (["-E"]++) foundHsCppProg
-      hppArgs <- findHsCppArgs rawHsCppProgram
-      let hsCppProgram = over _prgFlags (++hppArgs) rawHsCppProgram
-      return HsCpp{hsCppProgram}
+  -- Use the specified Hs Cpp or try to use the c compiler
+  foundHsCppProg <- findProgram "Haskell C preprocessor" progOpt [] <|> pure (programFromOpt progOpt (prgPath $ ccProgram cc) [])
+  -- Always add the -E flag to the CPP, regardless of the user options
+  let rawHsCppProgram = addFlagIfNew "-E" foundHsCppProg
+  -- Always try to add the Haskell-specific CPP flags, regardless of the user options
+  hppArgs <- findHsCppArgs rawHsCppProgram
+  let hsCppProgram = over _prgFlags (++hppArgs) rawHsCppProgram
+  return HsCpp{hsCppProgram}
 
 -- | Given a C preprocessor, figure out how it should be invoked to preprocess
 -- Haskell source.
@@ -84,13 +81,9 @@ findHsCppArgs cpp = withTempDir $ \dir -> do
 
 findCpp :: ProgOpt -> Cc -> M Cpp
 findCpp progOpt cc = checking "for C preprocessor" $ do
-  -- Use the specified CPP or try to find one (candidate is the c compiler)
-  foundCppProg <- findProgram "C preprocessor" progOpt [prgPath $ ccProgram cc]
-  case poFlags progOpt of
-    -- If the user specified CPP flags don't second-guess them
-    Just _ -> return Cpp{cppProgram=foundCppProg}
-    -- Otherwise, configure the CPP flags for this CPP program
-    Nothing -> do
-      let cppProgram = over _prgFlags (["-E"]++) foundCppProg
-      return Cpp{cppProgram}
+  -- Use the specified CPP or try to use the c compiler
+  foundCppProg <- findProgram "C preprocessor" progOpt [] <|> pure (programFromOpt progOpt (prgPath $ ccProgram cc) [])
+  -- Always add the -E flag to the CPP, regardless of the user options
+  let cppProgram = addFlagIfNew "-E" foundCppProg
+  return Cpp{cppProgram}
 


=====================================
utils/ghc-toolchain/src/GHC/Toolchain/Tools/Link.hs
=====================================
@@ -46,8 +46,8 @@ findCcLink :: String -- ^ The llvm target to use if CcLink supports --target
            -> Bool   -- ^ Whether we should search for a more efficient linker
            -> ArchOS -> Cc -> Maybe Readelf -> M CcLink
 findCcLink target progOpt ldOverride archOs cc readelf = checking "for C compiler for linking command" $ do
-  -- Use the specified linker or try to find one
-  rawCcLink <- findProgram "C compiler for linking" progOpt [takeFileName $ prgPath $ ccProgram cc]
+  -- Use the specified linker or try using the C compiler
+  rawCcLink <- findProgram "C compiler for linking" progOpt [] <|> pure (programFromOpt progOpt (prgPath $ ccProgram cc) [])
   ccLinkProgram <- case poFlags progOpt of
                      Just _ ->
                          -- If the user specified linker flags don't second-guess them
@@ -55,11 +55,11 @@ findCcLink target progOpt ldOverride archOs cc readelf = checking "for C compile
                      Nothing -> do
                          -- If not then try to find decent linker flags
                          findLinkFlags ldOverride cc rawCcLink <|> pure rawCcLink
-  ccLinkProgram <- linkSupportsTarget cc target ccLinkProgram
-  ccLinkSupportsNoPie         <- checkSupportsNoPie            ccLinkProgram
+  ccLinkProgram <- linkSupportsTarget archOs cc target ccLinkProgram
+  ccLinkSupportsNoPie         <- checkSupportsNoPie  ccLinkProgram
   ccLinkSupportsCompactUnwind <- checkSupportsCompactUnwind archOs cc ccLinkProgram
-  ccLinkSupportsFilelist      <- checkSupportsFilelist      cc ccLinkProgram
-  ccLinkIsGnu                 <- checkLinkIsGnu                ccLinkProgram
+  ccLinkSupportsFilelist      <- checkSupportsFilelist cc ccLinkProgram
+  ccLinkIsGnu                 <- checkLinkIsGnu archOs ccLinkProgram
   checkBfdCopyBug archOs cc readelf ccLinkProgram
   ccLinkProgram <- addPlatformDepLinkFlags archOs cc ccLinkProgram
   let ccLink = CcLink {ccLinkProgram, ccLinkSupportsNoPie,
@@ -87,8 +87,13 @@ findLinkFlags enableOverride cc ccLink
   | otherwise =
     return ccLink
 
-linkSupportsTarget :: Cc -> String -> Program -> M Program
-linkSupportsTarget cc target link
+linkSupportsTarget :: ArchOS -> Cc -> String -> Program -> M Program
+-- Javascript toolchain provided by emsdk just ignores --target flag so
+-- we have this special case to match with ./configure (#23744)
+linkSupportsTarget archOS _ _ c
+  | ArchJavaScript <- archOS_arch archOS
+  = return c
+linkSupportsTarget _ cc target link
   = checking "whether cc linker supports --target" $
     supportsTarget (Lens id const) (checkLinkWorks cc) target link
 
@@ -170,8 +175,11 @@ checkLinkWorks cc ccLink = withTempDir $ \dir -> do
       -- Linking in windows might produce an executable with an ".exe" extension
       <|> expectFileExists (out <.> "exe") err
 
-checkLinkIsGnu :: Program -> M Bool
-checkLinkIsGnu ccLink = do
+checkLinkIsGnu :: ArchOS -> Program -> M Bool
+checkLinkIsGnu archOs _
+  -- emsdk is never going to provide gnu ld (See #23744)
+  | ArchJavaScript <- archOS_arch archOs = return False
+checkLinkIsGnu _ ccLink = do
   out <- readProgramStdout ccLink ["-Wl,--version"]
   return ("GNU" `isInfixOf` out)
 



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/1e68d6c8b63c4c530c567c40b6310d6c561721e2...31cceda923b739fc9a0337cf3909a2e4468dcdb8

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/1e68d6c8b63c4c530c567c40b6310d6c561721e2...31cceda923b739fc9a0337cf3909a2e4468dcdb8
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20230809/f762e95d/attachment-0001.html>


More information about the ghc-commits mailing list