haskell.compiler.ghc*: use matching CLANG & CC on Darwin with LLVM

The Darwin LLVM backend of GHC (which is mostly interesting for
GHC < 9.2) uses clang as configured via the CLANG environment variable
as an assembler. Since it processes outputs of clang as configured via
the CC variable, we need to make sure these versions match or risk CLANG
clang not understanding the output of CC clang.

In the past this wasn't really a problem as due to the fairly old
default clang version in the stdenv, clang 11 would be used for CC.
CLANG would always be a newer version and deal with the output without
any problems.

Ever since the upgrade of the default clang version for
darwin (bcbdb800cf), CC would often be a
newer version of clang than CLANG, causing build problems in some
packages like crypton (for GHC 8.10.7 and 9.0.2 on aarch64-darwin where
the darwin LLVM backend was actually used).
This commit is contained in:
sternenseemann 2024-09-01 13:32:41 +02:00
parent 35f1a5b515
commit b039994dad
3 changed files with 60 additions and 9 deletions

View File

@ -184,6 +184,9 @@ let
if stdenv.targetPlatform.isDarwin if stdenv.targetPlatform.isDarwin
then cc.bintools then cc.bintools
else cc.bintools.bintools; else cc.bintools.bintools;
# clang is used as an assembler on darwin with the LLVM backend
clang = cc;
}.${name}; }.${name};
in in
"${tools}/bin/${tools.targetPrefix}${name}"; "${tools}/bin/${tools.targetPrefix}${name}";
@ -335,7 +338,17 @@ stdenv.mkDerivation (rec {
export OPT="${lib.getBin buildTargetLlvmPackages.llvm}/bin/opt" export OPT="${lib.getBin buildTargetLlvmPackages.llvm}/bin/opt"
'' + lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) '' '' + lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) ''
# LLVM backend on Darwin needs clang: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/codegens.html#llvm-code-generator-fllvm # LLVM backend on Darwin needs clang: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/codegens.html#llvm-code-generator-fllvm
export CLANG="${buildTargetLlvmPackages.clang}/bin/${buildTargetLlvmPackages.clang.targetPrefix}clang" # The executable we specify via $CLANG is used as an assembler (exclusively, it seems, but this isn't
# clarified in any user facing documentation). As such, it'll be called on assembly produced by $CC
# which usually comes from the darwin stdenv. To prevent a situation where $CLANG doesn't understand
# the assembly it is given, we need to make sure that it matches the LLVM version of $CC if possible.
# It is unclear (at the time of writing 2024-09-01) whether $CC should match the LLVM version we use
# for llc and opt which would require using a custom darwin stdenv for targetCC.
export CLANG="${
if targetCC.isClang
then toolPath "clang" targetCC
else "${buildTargetLlvmPackages.clang}/bin/${buildTargetLlvmPackages.clang.targetPrefix}clang"
}"
'' + '' '' + ''
# No need for absolute paths since these tools only need to work during the build # No need for absolute paths since these tools only need to work during the build
export CC_STAGE0="$CC_FOR_BUILD" export CC_STAGE0="$CC_FOR_BUILD"
@ -477,10 +490,14 @@ stdenv.mkDerivation (rec {
"LLVM llc command" "${lib.getBin llvmPackages.llvm}/bin/llc" \ "LLVM llc command" "${lib.getBin llvmPackages.llvm}/bin/llc" \
"LLVM opt command" "${lib.getBin llvmPackages.llvm}/bin/opt" "LLVM opt command" "${lib.getBin llvmPackages.llvm}/bin/opt"
'' ''
# FIXME(@sternenseemann): use installCC instead if possible
+ lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) '' + lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) ''
ghc-settings-edit "$settingsFile" \ ghc-settings-edit "$settingsFile" \
"LLVM clang command" "${llvmPackages.clang}/bin/${llvmPackages.clang.targetPrefix}clang" "LLVM clang command" "${
# See comment for CLANG in preConfigure
if installCC.isClang
then toolPath "clang" installCC
else "${llvmPackages.clang}/bin/${llvmPackages.clang.targetPrefix}clang"
}"
'' ''
+ '' + ''

View File

@ -323,6 +323,9 @@ let
if stdenv.targetPlatform.isDarwin if stdenv.targetPlatform.isDarwin
then cc.bintools then cc.bintools
else cc.bintools.bintools; else cc.bintools.bintools;
# clang is used as an assembler on darwin with the LLVM backend
clang = cc;
}.${name}; }.${name};
in in
"${tools}/bin/${tools.targetPrefix}${name}"; "${tools}/bin/${tools.targetPrefix}${name}";
@ -412,7 +415,17 @@ stdenv.mkDerivation ({
export OPT="${lib.getBin buildTargetLlvmPackages.llvm}/bin/opt" export OPT="${lib.getBin buildTargetLlvmPackages.llvm}/bin/opt"
'' + lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) '' '' + lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) ''
# LLVM backend on Darwin needs clang: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/codegens.html#llvm-code-generator-fllvm # LLVM backend on Darwin needs clang: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/codegens.html#llvm-code-generator-fllvm
export CLANG="${buildTargetLlvmPackages.clang}/bin/${buildTargetLlvmPackages.clang.targetPrefix}clang" # The executable we specify via $CLANG is used as an assembler (exclusively, it seems, but this isn't
# clarified in any user facing documentation). As such, it'll be called on assembly produced by $CC
# which usually comes from the darwin stdenv. To prevent a situation where $CLANG doesn't understand
# the assembly it is given, we need to make sure that it matches the LLVM version of $CC if possible.
# It is unclear (at the time of writing 2024-09-01) whether $CC should match the LLVM version we use
# for llc and opt which would require using a custom darwin stdenv for targetCC.
export CLANG="${
if targetCC.isClang
then toolPath "clang" targetCC
else "${buildTargetLlvmPackages.clang}/bin/${buildTargetLlvmPackages.clang.targetPrefix}clang"
}"
'' + '' +
lib.optionalString (stdenv.isLinux && hostPlatform.libc == "glibc") '' lib.optionalString (stdenv.isLinux && hostPlatform.libc == "glibc") ''
export LOCALE_ARCHIVE="${glibcLocales}/lib/locale/locale-archive" export LOCALE_ARCHIVE="${glibcLocales}/lib/locale/locale-archive"
@ -630,10 +643,14 @@ stdenv.mkDerivation ({
"LLVM llc command" "${lib.getBin llvmPackages.llvm}/bin/llc" \ "LLVM llc command" "${lib.getBin llvmPackages.llvm}/bin/llc" \
"LLVM opt command" "${lib.getBin llvmPackages.llvm}/bin/opt" "LLVM opt command" "${lib.getBin llvmPackages.llvm}/bin/opt"
'' ''
# FIXME(@sternenseemann): use installCC instead if possible
+ lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) '' + lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) ''
ghc-settings-edit "$settingsFile" \ ghc-settings-edit "$settingsFile" \
"LLVM clang command" "${llvmPackages.clang}/bin/${llvmPackages.clang.targetPrefix}clang" "LLVM clang command" "${
# See comment for CLANG in preConfigure
if installCC.isClang
then toolPath "clang" installCC
else "${llvmPackages.clang}/bin/${llvmPackages.clang.targetPrefix}clang"
}"
'' ''
# Work around a GHC bug which causes unlit to be installed under a different # Work around a GHC bug which causes unlit to be installed under a different
# name than is used in the settings file. # name than is used in the settings file.

View File

@ -187,6 +187,9 @@ let
if stdenv.targetPlatform.isDarwin if stdenv.targetPlatform.isDarwin
then cc.bintools then cc.bintools
else cc.bintools.bintools; else cc.bintools.bintools;
# clang is used as an assembler on darwin with the LLVM backend
clang = cc;
}.${name}; }.${name};
in in
"${tools}/bin/${tools.targetPrefix}${name}"; "${tools}/bin/${tools.targetPrefix}${name}";
@ -335,7 +338,17 @@ stdenv.mkDerivation (rec {
export OPT="${lib.getBin buildTargetLlvmPackages.llvm}/bin/opt" export OPT="${lib.getBin buildTargetLlvmPackages.llvm}/bin/opt"
'' + lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) '' '' + lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) ''
# LLVM backend on Darwin needs clang: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/codegens.html#llvm-code-generator-fllvm # LLVM backend on Darwin needs clang: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/codegens.html#llvm-code-generator-fllvm
export CLANG="${buildTargetLlvmPackages.clang}/bin/${buildTargetLlvmPackages.clang.targetPrefix}clang" # The executable we specify via $CLANG is used as an assembler (exclusively, it seems, but this isn't
# clarified in any user facing documentation). As such, it'll be called on assembly produced by $CC
# which usually comes from the darwin stdenv. To prevent a situation where $CLANG doesn't understand
# the assembly it is given, we need to make sure that it matches the LLVM version of $CC if possible.
# It is unclear (at the time of writing 2024-09-01) whether $CC should match the LLVM version we use
# for llc and opt which would require using a custom darwin stdenv for targetCC.
export CLANG="${
if targetCC.isClang
then toolPath "clang" targetCC
else "${buildTargetLlvmPackages.clang}/bin/${buildTargetLlvmPackages.clang.targetPrefix}clang"
}"
'' ''
+ '' + ''
# No need for absolute paths since these tools only need to work during the build # No need for absolute paths since these tools only need to work during the build
@ -494,10 +507,14 @@ stdenv.mkDerivation (rec {
"LLVM llc command" "${lib.getBin llvmPackages.llvm}/bin/llc" \ "LLVM llc command" "${lib.getBin llvmPackages.llvm}/bin/llc" \
"LLVM opt command" "${lib.getBin llvmPackages.llvm}/bin/opt" "LLVM opt command" "${lib.getBin llvmPackages.llvm}/bin/opt"
'' ''
# FIXME(@sternenseemann): use installCC instead if possible
+ lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) '' + lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) ''
ghc-settings-edit "$settingsFile" \ ghc-settings-edit "$settingsFile" \
"LLVM clang command" "${llvmPackages.clang}/bin/${llvmPackages.clang.targetPrefix}clang" "LLVM clang command" "${
# See comment for CLANG in preConfigure
if installCC.isClang
then toolPath "clang" installCC
else "${llvmPackages.clang}/bin/${llvmPackages.clang.targetPrefix}clang"
}"
'' ''
+ '' + ''