2024-07-31 10:19:44 +00:00
|
|
|
|
{
|
|
|
|
|
lib,
|
|
|
|
|
stdenv,
|
|
|
|
|
fetchFromGitHub,
|
|
|
|
|
fetchurl,
|
|
|
|
|
darwin,
|
|
|
|
|
libtapi,
|
|
|
|
|
libunwind,
|
|
|
|
|
llvm,
|
|
|
|
|
meson,
|
|
|
|
|
ninja,
|
|
|
|
|
openssl,
|
|
|
|
|
pkg-config,
|
|
|
|
|
python3,
|
|
|
|
|
swiftPackages,
|
|
|
|
|
xar,
|
|
|
|
|
gitUpdater,
|
|
|
|
|
}:
|
|
|
|
|
|
|
|
|
|
let
|
|
|
|
|
# The targetPrefix is prepended to binary names to allow multiple binutils on the PATH to be usable.
|
|
|
|
|
targetPrefix = lib.optionalString (
|
|
|
|
|
stdenv.targetPlatform != stdenv.hostPlatform
|
|
|
|
|
) "${stdenv.targetPlatform.config}-";
|
|
|
|
|
|
|
|
|
|
# ld64 needs CrashReporterClient.h, which is hard to find, but WebKit2 has it.
|
|
|
|
|
# Fetch it directly because the Darwin stdenv bootstrap can’t depend on fetchgit.
|
|
|
|
|
crashreporter_h = fetchurl {
|
|
|
|
|
url = "https://raw.githubusercontent.com/apple-oss-distributions/WebKit2/WebKit2-7605.1.33.0.2/Platform/spi/Cocoa/CrashReporterClientSPI.h";
|
|
|
|
|
hash = "sha256-0ybVcwHuGEdThv0PPjYQc3SW0YVOyrM3/L9zG/l1Vtk=";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
# First version with all the required definitions. This is used in preference to darwin.xnu to make it easier
|
|
|
|
|
# to support Linux and because the version of darwin.xnu available on x86_64-darwin in the 10.12 SDK is too old.
|
|
|
|
|
xnu = fetchFromGitHub {
|
|
|
|
|
name = "xnu-src";
|
|
|
|
|
owner = "apple-oss-distributions";
|
|
|
|
|
repo = "xnu";
|
|
|
|
|
rev = "xnu-6153.11.26";
|
|
|
|
|
hash = "sha256-dcnGcp7bIjQxeAn5pXt+mHSYEXb2Ad9Smhd/WUG4kb4=";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
# Avoid pulling in all of Swift just to build libdispatch
|
|
|
|
|
libdispatch = swiftPackages.Dispatch.override { useSwift = false; };
|
|
|
|
|
in
|
|
|
|
|
stdenv.mkDerivation (finalAttrs: {
|
|
|
|
|
pname = "ld64";
|
|
|
|
|
version = "951.9";
|
|
|
|
|
|
|
|
|
|
outputs = [
|
|
|
|
|
"out"
|
|
|
|
|
"dev"
|
|
|
|
|
"lib"
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
src = fetchFromGitHub {
|
|
|
|
|
owner = "apple-oss-distributions";
|
|
|
|
|
repo = "ld64";
|
|
|
|
|
rev = "ld64-${finalAttrs.version}";
|
|
|
|
|
hash = "sha256-hLkfqgBwVPlO4gfriYOawTO5E1zSD63ZcNetm1E5I70";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
xcodeHash = "sha256-+j7Ed/6aD46SJnr3DWPfWuYWylb2FNJRPmWsUVxZJHM=";
|
|
|
|
|
|
|
|
|
|
postUnpack = ''
|
|
|
|
|
unpackFile '${xnu}'
|
|
|
|
|
|
|
|
|
|
# Verify that the Xcode project has not changed unexpectedly.
|
|
|
|
|
hashType=$(echo $xcodeHash | cut -d- -f1)
|
|
|
|
|
expectedHash=$(echo $xcodeHash | cut -d- -f2)
|
|
|
|
|
hash=$(openssl "$hashType" -binary "$sourceRoot/ld64.xcodeproj/project.pbxproj" | base64)
|
|
|
|
|
|
|
|
|
|
if [ "$hash" != "$expectedHash" ]; then
|
|
|
|
|
echo 'error: hash mismatch in ld64.xcodeproj/project.pbxproj'
|
|
|
|
|
echo " specified: $xcodeHash"
|
|
|
|
|
echo " got: $hashType-$hash"
|
|
|
|
|
echo
|
|
|
|
|
echo 'Upstream Xcode project has changed. Update `meson.build` with any changes, then update `xcodeHash`.'
|
|
|
|
|
echo 'Use `nix-hash --flat --sri --type sha256 ld64.xcodeproj/project.pbxproj` to regenerate it.'
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
'';
|
|
|
|
|
|
|
|
|
|
patches = [
|
|
|
|
|
# Use std::atomic for atomics. Replaces private APIs (`os/lock_private.h`) with standard APIs.
|
|
|
|
|
./0004-Use-std-atomics-and-std-mutex.patch
|
|
|
|
|
# ld64 assumes the default libLTO.dylib can be found relative to its bindir, which is
|
|
|
|
|
# not the case in nixpkgs. Override it to default to `stdenv.cc`’s libLTO.dylib.
|
|
|
|
|
./0005-Support-LTO-in-nixpkgs.patch
|
|
|
|
|
# Add implementation of missing function required for code directory support.
|
|
|
|
|
./0006-Add-libcd_is_blob_a_linker_signature-implementation.patch
|
|
|
|
|
# Add OpenSSL implementation of CoreCrypto digest functions. Avoids use of private and non-free APIs.
|
|
|
|
|
./0007-Add-OpenSSL-based-CoreCrypto-digest-functions.patch
|
|
|
|
|
# ld64 will search `/usr/lib`, `/Library/Frameworks`, etc by default. Disable that.
|
|
|
|
|
./0008-Disable-searching-in-standard-library-locations.patch
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
postPatch = ''
|
|
|
|
|
substitute ${./meson.build} meson.build \
|
|
|
|
|
--subst-var version
|
|
|
|
|
cp ${./meson.options} meson.options
|
|
|
|
|
|
|
|
|
|
# Copy headers for certain private APIs
|
|
|
|
|
mkdir -p include
|
|
|
|
|
substitute ${crashreporter_h} include/CrashReporterClient.h \
|
|
|
|
|
--replace-fail 'USE(APPLE_INTERNAL_SDK)' '0'
|
|
|
|
|
|
|
|
|
|
# Copy from the source so the headers can be used on Linux and x86_64-darwin
|
|
|
|
|
mkdir -p include/System
|
|
|
|
|
for dir in arm i386 machine; do
|
|
|
|
|
cp -r ../xnu-src/osfmk/$dir include/System/$dir
|
|
|
|
|
done
|
|
|
|
|
mkdir -p include/sys
|
|
|
|
|
cp ../xnu-src/bsd/sys/commpage.h include/sys
|
|
|
|
|
|
|
|
|
|
# Match the version format used by upstream.
|
|
|
|
|
sed -i src/ld/Options.cpp \
|
|
|
|
|
-e '1iconst char ld_classicVersionString[] = "@(#)PROGRAM:ld PROJECT:ld64-${finalAttrs.version}\\n";'
|
|
|
|
|
|
|
|
|
|
# Instead of messing around with trying to extract and run the script from the Xcode project,
|
|
|
|
|
# just use our own Python script to generate `compile_stubs.h`
|
|
|
|
|
cp ${./gen_compile_stubs.py} gen_compile_stubs.py
|
|
|
|
|
|
|
|
|
|
# Enable LTO support using LLVM’s libLTO.dylib by default.
|
|
|
|
|
substituteInPlace src/ld/InputFiles.cpp \
|
|
|
|
|
--subst-var-by libllvm '${lib.getLib llvm}'
|
|
|
|
|
substituteInPlace src/ld/parsers/lto_file.cpp \
|
|
|
|
|
--subst-var-by libllvm '${lib.getLib llvm}'
|
|
|
|
|
|
|
|
|
|
# Use portable includes
|
|
|
|
|
substituteInPlace src/ld/code-sign-blobs/endian.h \
|
|
|
|
|
--replace-fail '#include <machine/endian.h>' '#include <sys/types.h>'
|
|
|
|
|
'';
|
|
|
|
|
|
|
|
|
|
strictDeps = true;
|
|
|
|
|
|
|
|
|
|
nativeBuildInputs = [
|
|
|
|
|
meson
|
|
|
|
|
ninja
|
|
|
|
|
openssl
|
|
|
|
|
pkg-config
|
|
|
|
|
python3
|
|
|
|
|
];
|
|
|
|
|
|
2024-09-26 11:04:55 +00:00
|
|
|
|
buildInputs =
|
|
|
|
|
[
|
|
|
|
|
libtapi
|
|
|
|
|
llvm
|
|
|
|
|
libunwind
|
|
|
|
|
openssl
|
|
|
|
|
xar
|
|
|
|
|
]
|
|
|
|
|
++ lib.optionals stdenv.hostPlatform.isDarwin [ darwin.dyld ]
|
|
|
|
|
++ lib.optionals stdenv.hostPlatform.isLinux [ libdispatch ];
|
2024-07-31 10:19:44 +00:00
|
|
|
|
|
|
|
|
|
# Note for overrides: ld64 cannot be built as a debug build because of UB in its iteration implementations,
|
|
|
|
|
# which trigger libc++ debug assertions due to trying to take the address of the first element of an emtpy vector.
|
|
|
|
|
mesonBuildType = "release";
|
|
|
|
|
|
|
|
|
|
mesonFlags = [
|
|
|
|
|
(lib.mesonOption "b_ndebug" "if-release")
|
|
|
|
|
(lib.mesonOption "default_library" (if stdenv.hostPlatform.isStatic then "static" else "shared"))
|
|
|
|
|
] ++ lib.optionals (targetPrefix != "") [ (lib.mesonOption "target_prefix" targetPrefix) ];
|
|
|
|
|
|
|
|
|
|
doInstallCheck = stdenv.buildPlatform.canExecute stdenv.hostPlatform;
|
|
|
|
|
|
|
|
|
|
# ld64 has a test suite, but many of the tests fail (even with ld from Xcode). Instead
|
|
|
|
|
# of running the test suite, rebuild ld64 using itself to link itself as a check.
|
|
|
|
|
# LTO is enabled only to confirm that it is set up and working properly in nixpkgs.
|
|
|
|
|
installCheckPhase = ''
|
|
|
|
|
runHook preInstallCheck
|
|
|
|
|
|
|
|
|
|
cd "$NIX_BUILD_TOP/$sourceRoot"
|
|
|
|
|
|
|
|
|
|
export NIX_CFLAGS_COMPILE+=" --ld-path=$out/bin/${targetPrefix}ld"
|
|
|
|
|
meson setup build-install-check -Db_lto=true --buildtype=$mesonBuildType${
|
|
|
|
|
lib.optionalString (targetPrefix != "") " -Dtarget_prefix=${targetPrefix}"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cd build-install-check
|
|
|
|
|
ninja ${targetPrefix}ld "-j$NIX_BUILD_CORES"
|
|
|
|
|
|
|
|
|
|
# Confirm that ld found the LTO library and reports it.
|
|
|
|
|
./${targetPrefix}ld -v 2>&1 | grep -q 'LTO support'
|
|
|
|
|
|
|
|
|
|
runHook postInstallCheck
|
|
|
|
|
'';
|
|
|
|
|
|
|
|
|
|
postInstall = ''
|
|
|
|
|
ln -s ld-classic.1 "$out/share/man/man1/ld.1"
|
|
|
|
|
ln -s ld.1 "$out/share/man/man1/ld64.1"
|
|
|
|
|
moveToOutput lib/libprunetrie.a "$dev"
|
|
|
|
|
'';
|
|
|
|
|
|
|
|
|
|
__structuredAttrs = true;
|
|
|
|
|
|
|
|
|
|
passthru.updateScript = gitUpdater { rev-prefix = "ld64-"; };
|
|
|
|
|
|
|
|
|
|
meta = {
|
|
|
|
|
description = "The classic linker for Darwin";
|
|
|
|
|
homepage = "https://opensource.apple.com/releases/";
|
|
|
|
|
license = lib.licenses.apple-psl20;
|
|
|
|
|
mainProgram = "ld";
|
|
|
|
|
maintainers = with lib.maintainers; [ reckenrode ];
|
|
|
|
|
platforms = lib.platforms.darwin; # Porting to other platforms is incomplete. Support only Darwin for now.
|
|
|
|
|
};
|
|
|
|
|
})
|