From cdb8e81ab358745d6a53227267df5b0f7b3a9acc Mon Sep 17 00:00:00 2001 From: sternenseemann Date: Sat, 6 Sep 2025 22:12:47 +0200 Subject: [PATCH 1/3] haskell.compiler.*: add helper for calculating LLVM tools' paths Verified that there are no hash changes (eval platform x86_64-linux) in: - haskell.compiler - pkgsCross.armv7l-hf-multiplatform.haskell.compiler - pkgsCross.armv7l-hf-multiplatform.buildPackages.haskell.compiler --- .../compilers/ghc/common-hadrian.nix | 20 +++++++++---------- .../ghc/common-make-native-bignum.nix | 20 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/pkgs/development/compilers/ghc/common-hadrian.nix b/pkgs/development/compilers/ghc/common-hadrian.nix index 0b22b1ff3812e..baa00b3f7551a 100644 --- a/pkgs/development/compilers/ghc/common-hadrian.nix +++ b/pkgs/development/compilers/ghc/common-hadrian.nix @@ -433,7 +433,10 @@ let } .${name}; in - "${tools}/bin/${tools.targetPrefix}${name}"; + getToolExe tools name; + + # targetPrefix aware lib.getExe' + getToolExe = drv: name: lib.getExe' drv "${drv.targetPrefix or ""}${name}"; # Use gold either following the default, or to avoid the BFD linker due to some bugs / perf issues. # But we cannot avoid BFD when using musl libc due to https://sourceware.org/bugzilla/show_bug.cgi?id=23856 @@ -530,8 +533,8 @@ stdenv.mkDerivation ( export INSTALL_NAME_TOOL="${toolPath "install_name_tool" targetCC}" '' + lib.optionalString useLLVM '' - export LLC="${lib.getBin buildTargetLlvmPackages.llvm}/bin/llc" - export OPT="${lib.getBin buildTargetLlvmPackages.llvm}/bin/opt" + export LLC="${getToolExe buildTargetLlvmPackages.llvm "llc"}" + export OPT="${getToolExe buildTargetLlvmPackages.llvm "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 @@ -545,7 +548,7 @@ stdenv.mkDerivation ( if targetCC.isClang then toolPath "clang" targetCC else - "${buildTargetLlvmPackages.clang}/bin/${buildTargetLlvmPackages.clang.targetPrefix}clang" + getToolExe buildTargetLlvmPackages.clang "clang" }" '' + lib.optionalString (stdenv.buildPlatform.libc == "glibc") '' @@ -826,17 +829,14 @@ stdenv.mkDerivation ( '' + lib.optionalString useLLVM '' ghc-settings-edit "$settingsFile" \ - "LLVM llc command" "${lib.getBin llvmPackages.llvm}/bin/llc" \ - "LLVM opt command" "${lib.getBin llvmPackages.llvm}/bin/opt" + "LLVM llc command" "${getToolExe llvmPackages.llvm "llc"}" \ + "LLVM opt command" "${getToolExe llvmPackages.llvm "opt"}" '' + lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) '' ghc-settings-edit "$settingsFile" \ "LLVM clang command" "${ # See comment for CLANG in preConfigure - if installCC.isClang then - toolPath "clang" installCC - else - "${llvmPackages.clang}/bin/${llvmPackages.clang.targetPrefix}clang" + if installCC.isClang then toolPath "clang" installCC else getToolExe llvmPackages.clang "clang" }" '' + lib.optionalString stdenv.targetPlatform.isWindows '' diff --git a/pkgs/development/compilers/ghc/common-make-native-bignum.nix b/pkgs/development/compilers/ghc/common-make-native-bignum.nix index 8cde6f42148c9..9facbfc1f22da 100644 --- a/pkgs/development/compilers/ghc/common-make-native-bignum.nix +++ b/pkgs/development/compilers/ghc/common-make-native-bignum.nix @@ -225,7 +225,10 @@ let } .${name}; in - "${tools}/bin/${tools.targetPrefix}${name}"; + getToolExe tools name; + + # targetPrefix aware lib.getExe' + getToolExe = drv: name: lib.getExe' drv "${drv.targetPrefix or ""}${name}"; # Use gold either following the default, or to avoid the BFD linker due to some bugs / perf issues. # But we cannot avoid BFD when using musl libc due to https://sourceware.org/bugzilla/show_bug.cgi?id=23856 @@ -408,8 +411,8 @@ stdenv.mkDerivation ( export INSTALL_NAME_TOOL="${toolPath "install_name_tool" targetCC}" '' + lib.optionalString useLLVM '' - export LLC="${lib.getBin buildTargetLlvmPackages.llvm}/bin/llc" - export OPT="${lib.getBin buildTargetLlvmPackages.llvm}/bin/opt" + export LLC="${getToolExe buildTargetLlvmPackages.llvm "llc"}" + export OPT="${getToolExe buildTargetLlvmPackages.llvm "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 @@ -423,7 +426,7 @@ stdenv.mkDerivation ( if targetCC.isClang then toolPath "clang" targetCC else - "${buildTargetLlvmPackages.clang}/bin/${buildTargetLlvmPackages.clang.targetPrefix}clang" + getToolExe buildTargetLlvmPackages.clang "clang" }" '' + '' @@ -624,17 +627,14 @@ stdenv.mkDerivation ( '' + lib.optionalString useLLVM '' ghc-settings-edit "$settingsFile" \ - "LLVM llc command" "${lib.getBin llvmPackages.llvm}/bin/llc" \ - "LLVM opt command" "${lib.getBin llvmPackages.llvm}/bin/opt" + "LLVM llc command" "${getToolExe llvmPackages.llvm "llc"}" \ + "LLVM opt command" "${getToolExe llvmPackages.llvm "opt"}" '' + lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) '' ghc-settings-edit "$settingsFile" \ "LLVM clang command" "${ # See comment for CLANG in preConfigure - if installCC.isClang then - toolPath "clang" installCC - else - "${llvmPackages.clang}/bin/${llvmPackages.clang.targetPrefix}clang" + if installCC.isClang then toolPath "clang" installCC else getToolExe llvmPackages.clang "clang" }" '' + '' From a9e965e0f690077f64e3aad25942f4560897bdef Mon Sep 17 00:00:00 2001 From: sternenseemann Date: Sun, 7 Sep 2025 01:00:53 +0200 Subject: [PATCH 2/3] haskell.compiler.ghc91{0,2}: provide LLVM compatible assembler If we don't explicitly pass something as LLVMAS, GHC >= 9.10 will try to invoke "clang" at runtime which fails. Upstream change: https://gitlab.haskell.org/ghc/ghc/-/merge_requests/12005 I've tested pkgsCross.armv7l-hf-multiplatform.buildPackages.haskell.compiler.ghc9102 which was reported to be failing here: https://github.com/NixOS/nixpkgs/pull/440271#issuecomment-3262885486 --- pkgs/development/compilers/ghc/common-hadrian.nix | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pkgs/development/compilers/ghc/common-hadrian.nix b/pkgs/development/compilers/ghc/common-hadrian.nix index baa00b3f7551a..382b1f2d6413d 100644 --- a/pkgs/development/compilers/ghc/common-hadrian.nix +++ b/pkgs/development/compilers/ghc/common-hadrian.nix @@ -536,6 +536,13 @@ stdenv.mkDerivation ( export LLC="${getToolExe buildTargetLlvmPackages.llvm "llc"}" export OPT="${getToolExe buildTargetLlvmPackages.llvm "opt"}" '' + # LLVMAS should be a "specific LLVM compatible assembler" which needs to understand + # assembly produced by LLVM. The easiest way to be sure is to use clang from the same + # version as llc and opt. Note that the naming chosen by GHC is misleading, clang can + # be used as an assembler, llvm-as converts IR into machine code. + + lib.optionalString (useLLVM && lib.versionAtLeast version "9.10") '' + export LLVMAS="${getToolExe buildTargetLlvmPackages.clang "clang"}" + '' + 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 # The executable we specify via $CLANG is used as an assembler (exclusively, it seems, but this isn't @@ -544,6 +551,7 @@ stdenv.mkDerivation ( # 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. + # 2025-09-06: The existence of LLVMAS suggests that matching $CC is fine (correct?) here. export CLANG="${ if targetCC.isClang then toolPath "clang" targetCC @@ -832,6 +840,11 @@ stdenv.mkDerivation ( "LLVM llc command" "${getToolExe llvmPackages.llvm "llc"}" \ "LLVM opt command" "${getToolExe llvmPackages.llvm "opt"}" '' + # See comment for LLVMAS in preConfigure + + lib.optionalString (useLLVM && lib.versionAtLeast version "9.10") '' + ghc-settings-edit "$settingsFile" \ + "LLVM llvm-as command" "${getToolExe llvmPackages.clang "clang"}" + '' + lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) '' ghc-settings-edit "$settingsFile" \ "LLVM clang command" "${ From a2b66241392827e69ce1bee92a0836ed3b3e36a1 Mon Sep 17 00:00:00 2001 From: sternenseemann Date: Tue, 9 Sep 2025 01:36:40 +0200 Subject: [PATCH 3/3] {forceLlvmCodegenBackend,ghcWithPackages}: update clang -fllvm logic - The LLVM backend always needs an LLVM specific assembler, i.e. clang that ideally matches the version of LLVM actually used for codegen. - The LLVM backend on Darwin requires some version of clang to be available. In light of LLVMAS, using a matching version seems to be best though this does risk messing with clang used for compiling C in the derivation. This mess can be avoided by compiling GHC with useLLVM = true which sets absolute paths in GHC's settings file. Due to closure size constraints, we can't really do that if NCG is available. --- pkgs/development/haskell-modules/make-package-set.nix | 9 ++++++++- .../haskell-modules/with-packages-wrapper.nix | 8 ++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/pkgs/development/haskell-modules/make-package-set.nix b/pkgs/development/haskell-modules/make-package-set.nix index d53c092ed0224..320b331fc25d8 100644 --- a/pkgs/development/haskell-modules/make-package-set.nix +++ b/pkgs/development/haskell-modules/make-package-set.nix @@ -734,6 +734,13 @@ package-set { inherit pkgs lib callPackage; } self */ forceLlvmCodegenBackend = overrideCabal (drv: { configureFlags = drv.configureFlags or [ ] ++ [ "--ghc-option=-fllvm" ]; - buildTools = drv.buildTools or [ ] ++ [ self.ghc.llvmPackages.llvm ]; + buildTools = + drv.buildTools or [ ] + ++ [ self.ghc.llvmPackages.llvm ] + # GHC >= 9.10 needs LLVM specific assembler, i.e. clang + # On Darwin clang is always required + ++ lib.optionals (lib.versionAtLeast self.ghc.version "9.10" || stdenv.hostPlatform.isDarwin) [ + self.ghc.llvmPackages.clang + ]; }); } diff --git a/pkgs/development/haskell-modules/with-packages-wrapper.nix b/pkgs/development/haskell-modules/with-packages-wrapper.nix index 0df9ec093ef7e..20b9a0803d3e2 100644 --- a/pkgs/development/haskell-modules/with-packages-wrapper.nix +++ b/pkgs/development/haskell-modules/with-packages-wrapper.nix @@ -68,10 +68,14 @@ let ) ); hasLibraries = lib.any (x: x.isHaskellLibrary) paths; - # CLang is needed on Darwin for -fllvm to work: + # Clang is needed on Darwin for -fllvm to work. + # GHC >= 9.10 needs an LLVM specific assembler which we use clang for. # https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/codegens.html#llvm-code-generator-fllvm llvm = lib.makeBinPath ( - [ ghc.llvmPackages.llvm ] ++ lib.optional stdenv.targetPlatform.isDarwin ghc.llvmPackages.clang + [ ghc.llvmPackages.llvm ] + ++ lib.optionals (lib.versionAtLeast ghc.version "9.10" || stdenv.targetPlatform.isDarwin) [ + ghc.llvmPackages.clang + ] ); in