Skip to content

Commit

Permalink
haskell.compiler.ghc*: use matching CLANG & CC on Darwin with LLVM
Browse files Browse the repository at this point in the history
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 (bcbdb80), 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).
  • Loading branch information
sternenseemann committed Sep 8, 2024
1 parent 2dae227 commit 19c88fb
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 9 deletions.
23 changes: 20 additions & 3 deletions pkgs/development/compilers/ghc/8.10.7.nix
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ let
if stdenv.targetPlatform.isDarwin
then cc.bintools
else cc.bintools.bintools;

# clang is used as an assembler on darwin with the LLVM backend
clang = cc;
}.${name};
in
"${tools}/bin/${tools.targetPrefix}${name}";
Expand Down Expand Up @@ -335,7 +338,17 @@ stdenv.mkDerivation (rec {
export OPT="${lib.getBin buildTargetLlvmPackages.llvm}/bin/opt"
'' + 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
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
export CC_STAGE0="$CC_FOR_BUILD"
Expand Down Expand Up @@ -477,10 +490,14 @@ stdenv.mkDerivation (rec {
"LLVM llc command" "${lib.getBin llvmPackages.llvm}/bin/llc" \
"LLVM opt command" "${lib.getBin llvmPackages.llvm}/bin/opt"
''
# FIXME(@sternenseemann): use installCC instead if possible
+ lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) ''
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"
}"
''
+ ''
Expand Down
23 changes: 20 additions & 3 deletions pkgs/development/compilers/ghc/common-hadrian.nix
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,9 @@ let
if stdenv.targetPlatform.isDarwin
then cc.bintools
else cc.bintools.bintools;

# clang is used as an assembler on darwin with the LLVM backend
clang = cc;
}.${name};
in
"${tools}/bin/${tools.targetPrefix}${name}";
Expand Down Expand Up @@ -409,7 +412,17 @@ stdenv.mkDerivation ({
export OPT="${lib.getBin buildTargetLlvmPackages.llvm}/bin/opt"
'' + 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
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") ''
export LOCALE_ARCHIVE="${glibcLocales}/lib/locale/locale-archive"
Expand Down Expand Up @@ -627,10 +640,14 @@ stdenv.mkDerivation ({
"LLVM llc command" "${lib.getBin llvmPackages.llvm}/bin/llc" \
"LLVM opt command" "${lib.getBin llvmPackages.llvm}/bin/opt"
''
# FIXME(@sternenseemann): use installCC instead if possible
+ lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) ''
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
# name than is used in the settings file.
Expand Down
23 changes: 20 additions & 3 deletions pkgs/development/compilers/ghc/common-make-native-bignum.nix
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ let
if stdenv.targetPlatform.isDarwin
then cc.bintools
else cc.bintools.bintools;

# clang is used as an assembler on darwin with the LLVM backend
clang = cc;
}.${name};
in
"${tools}/bin/${tools.targetPrefix}${name}";
Expand Down Expand Up @@ -335,7 +338,17 @@ stdenv.mkDerivation (rec {
export OPT="${lib.getBin buildTargetLlvmPackages.llvm}/bin/opt"
'' + 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
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
Expand Down Expand Up @@ -494,10 +507,14 @@ stdenv.mkDerivation (rec {
"LLVM llc command" "${lib.getBin llvmPackages.llvm}/bin/llc" \
"LLVM opt command" "${lib.getBin llvmPackages.llvm}/bin/opt"
''
# FIXME(@sternenseemann): use installCC instead if possible
+ lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) ''
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"
}"
''
+ ''
Expand Down

0 comments on commit 19c88fb

Please sign in to comment.