c810782ee6
Clang 11 performs an optimization on x86_64 that is sensitive to the presence of debug information. This results in GCC’s bootstrap failing because it builds stage 2 with debug information and stage 3 without, and the resulting objects do not match. This patch uses the cctools assembler on LLVM 11 and x86_64-darwin while using the integrated assembler on newer versions, which matches the platform tools (Apple has uses the integrated assembler since Xcode 12).
113 lines
4.2 KiB
Nix
113 lines
4.2 KiB
Nix
# Create a cctools-compatible bintools that uses equivalent tools from LLVM in place of the ones
|
||
# from cctools when possible.
|
||
|
||
{ lib, stdenv, makeWrapper, cctools-port, llvmPackages, enableManpages ? stdenv.targetPlatform == stdenv.hostPlatform }:
|
||
|
||
let
|
||
inherit (stdenv) targetPlatform hostPlatform;
|
||
|
||
cctoolsVersion = lib.getVersion cctools-port;
|
||
llvmVersion = llvmPackages.release_version;
|
||
|
||
# `bitcode_strip` is not available until LLVM 12.
|
||
useLLVMBitcodeStrip = lib.versionAtLeast llvmVersion "12";
|
||
|
||
# A compatible implementation of `otool` was not added until LLVM 13.
|
||
useLLVMOtool = lib.versionAtLeast llvmVersion "13";
|
||
|
||
# Older versions of `strip` cause problems for the version of `codesign_allocate` available in
|
||
# the version of cctools in nixpkgs. The version of `codesign_allocate` in cctools-1005.2 does
|
||
# not appear to have issues, but the source is not available yet (as of June 2023).
|
||
useLLVMStrip = lib.versionAtLeast llvmVersion "15" || lib.versionAtLeast cctoolsVersion "1005.2";
|
||
|
||
# Clang 11 performs an optimization on x86_64 that is sensitive to the presence of debug info.
|
||
# This causes GCC to fail to bootstrap due to object file differences between stages 2 and 3.
|
||
useClangAssembler = lib.versionAtLeast llvmVersion "12" || !stdenv.isx86_64;
|
||
|
||
llvm_bins = [
|
||
"dwarfdump"
|
||
"nm"
|
||
"objdump"
|
||
"size"
|
||
"strings"
|
||
]
|
||
++ lib.optional useLLVMBitcodeStrip "bitcode-strip"
|
||
++ lib.optional useLLVMOtool "otool"
|
||
++ lib.optional useLLVMStrip "strip";
|
||
|
||
# Only include the tools that LLVM doesn’t provide and that are present normally on Darwin.
|
||
# The only exceptions are the following tools, which should be reevaluated when LLVM is bumped.
|
||
# - install_name_tool (llvm-objcopy): unrecognized linker commands when building open source CF;
|
||
# - libtool (llvm-libtool-darwin): not fully compatible when used with xcbuild; and
|
||
# - lipo (llvm-lipo): crashes when running the LLVM test suite.
|
||
cctools_bins = [
|
||
"cmpdylib"
|
||
"codesign_allocate"
|
||
"ctf_insert"
|
||
"install_name_tool"
|
||
"ld"
|
||
"libtool"
|
||
"lipo"
|
||
"nmedit"
|
||
"pagestuff"
|
||
"ranlib"
|
||
"segedit"
|
||
"vtool"
|
||
]
|
||
++ lib.optional (!useLLVMBitcodeStrip) "bitcode_strip"
|
||
++ lib.optional (!useLLVMOtool) "otool"
|
||
++ lib.optional (!useLLVMStrip) "strip"
|
||
++ lib.optional (!useClangAssembler) "as";
|
||
|
||
targetPrefix = lib.optionalString (targetPlatform != hostPlatform) "${targetPlatform.config}-";
|
||
|
||
linkManPages = pkg: source: target: lib.optionalString enableManpages ''
|
||
sourcePath=${pkg}/share/man/man1/${source}.1.gz
|
||
targetPath=$man/share/man/man1/${target}.1.gz
|
||
|
||
if [ -f "$sourcePath" ]; then
|
||
mkdir -p "$(dirname "$targetPath")"
|
||
ln -s "$sourcePath" "$targetPath"
|
||
fi
|
||
'';
|
||
in
|
||
stdenv.mkDerivation {
|
||
pname = "cctools-llvm";
|
||
version = "${llvmVersion}-${cctoolsVersion}";
|
||
|
||
nativeBuildInputs = [ makeWrapper ];
|
||
|
||
# The `man` output has to be included unconditionally because darwin.binutils expects it.
|
||
outputs = [ "out" "dev" "man" ];
|
||
|
||
buildCommand = ''
|
||
mkdir -p "$out/bin" "$man"
|
||
ln -s ${lib.getDev cctools-port} "$dev"
|
||
|
||
'' + lib.optionalString useClangAssembler ''
|
||
# Use the clang-integrated assembler instead of using `as` from cctools.
|
||
makeWrapper "${lib.getBin llvmPackages.clang-unwrapped}/bin/clang" "$out/bin/${targetPrefix}as" \
|
||
--add-flags "-x assembler -integrated-as -c"
|
||
|
||
'' + ''
|
||
ln -s "${lib.getBin llvmPackages.bintools-unwrapped}/bin/${targetPrefix}llvm-ar" "$out/bin/${targetPrefix}ar"
|
||
${linkManPages llvmPackages.llvm-manpages "llvm-ar" "ar"}
|
||
|
||
for tool in ${toString llvm_bins}; do
|
||
cctoolsTool=''${tool/-/_}
|
||
ln -s "${lib.getBin llvmPackages.llvm}/bin/llvm-$tool" "$out/bin/${targetPrefix}$cctoolsTool"
|
||
${linkManPages llvmPackages.llvm-manpages "llvm-$tool" "$cctoolsTool"}
|
||
done
|
||
|
||
for tool in ${toString cctools_bins}; do
|
||
ln -s "${lib.getBin cctools-port}/bin/${targetPrefix}$tool" "$out/bin/${targetPrefix}$tool"
|
||
${linkManPages (lib.getMan cctools-port) "$tool" "$tool"}
|
||
done
|
||
|
||
${linkManPages (lib.getMan cctools-port) "ld64" "ld64"}
|
||
${lib.optionalString (!useLLVMOtool) # The actual man page for otool in cctools is llvm-otool
|
||
(linkManPages (lib.getMan cctools-port) "llvm-otool" "llvm-otool")}
|
||
'';
|
||
|
||
passthru = { inherit targetPrefix; };
|
||
}
|