nixpkgs/pkgs/os-specific/darwin/cctools/llvm.nix
Randy Eckenrode c810782ee6
cctools-llvm: use cctools assembler on x86_64-darwin and LLVM 11
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).
2023-07-09 13:29:11 -06:00

113 lines
4.2 KiB
Nix
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 doesnt 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; };
}