From 19c88fb8f6adaeda478842afee469041648948e9 Mon Sep 17 00:00:00 2001 From: sternenseemann Date: Sun, 1 Sep 2024 13:32:41 +0200 Subject: [PATCH] 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 (bcbdb800cf7659d6ff36ac114121a056fe8c9656), 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). --- pkgs/development/compilers/ghc/8.10.7.nix | 23 ++++++++++++++++--- .../compilers/ghc/common-hadrian.nix | 23 ++++++++++++++++--- .../ghc/common-make-native-bignum.nix | 23 ++++++++++++++++--- 3 files changed, 60 insertions(+), 9 deletions(-) diff --git a/pkgs/development/compilers/ghc/8.10.7.nix b/pkgs/development/compilers/ghc/8.10.7.nix index bf1c27f2a812e..81ec3eb84d112 100644 --- a/pkgs/development/compilers/ghc/8.10.7.nix +++ b/pkgs/development/compilers/ghc/8.10.7.nix @@ -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}"; @@ -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" @@ -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" + }" '' + '' diff --git a/pkgs/development/compilers/ghc/common-hadrian.nix b/pkgs/development/compilers/ghc/common-hadrian.nix index f9b24f291aaa0..09893ab4bdfa6 100644 --- a/pkgs/development/compilers/ghc/common-hadrian.nix +++ b/pkgs/development/compilers/ghc/common-hadrian.nix @@ -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}"; @@ -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" @@ -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. diff --git a/pkgs/development/compilers/ghc/common-make-native-bignum.nix b/pkgs/development/compilers/ghc/common-make-native-bignum.nix index 03d7697e2de39..b1b139a290d86 100644 --- a/pkgs/development/compilers/ghc/common-make-native-bignum.nix +++ b/pkgs/development/compilers/ghc/common-make-native-bignum.nix @@ -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}"; @@ -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 @@ -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" + }" '' + ''