diff --git a/pkgs/build-support/bintools-wrapper/default.nix b/pkgs/build-support/bintools-wrapper/default.nix index b7561f1aab55e..215dd0f39cd7f 100644 --- a/pkgs/build-support/bintools-wrapper/default.nix +++ b/pkgs/build-support/bintools-wrapper/default.nix @@ -60,9 +60,6 @@ (!(targetPlatform.isAarch && targetPlatform.isStatic)) ]) ]) "pie" - -# Darwin code signing support utilities -, postLinkSignHook ? null, signingUtils ? null }: assert propagateDoc -> bintools ? man; @@ -357,7 +354,7 @@ stdenvNoCC.mkDerivation { ## # TODO(@sternenseemann): make a generic strip wrapper? - + optionalString (bintools.isGNU or false) '' + + optionalString (bintools.isGNU or false || bintools.isCCTools or false) '' wrap ${targetPrefix}strip ${./gnu-binutils-strip-wrapper.sh} \ "${bintools_bin}/bin/${targetPrefix}strip" '' @@ -396,24 +393,6 @@ stdenvNoCC.mkDerivation { '' ) - ## - ## Code signing on Apple Silicon - ## - + optionalString (targetPlatform.isDarwin && targetPlatform.isAarch64) '' - echo 'source ${postLinkSignHook}' >> $out/nix-support/post-link-hook - - export signingUtils=${signingUtils} - - wrap \ - ${targetPrefix}install_name_tool \ - ${./darwin-install_name_tool-wrapper.sh} \ - "${bintools_bin}/bin/${targetPrefix}install_name_tool" - - wrap \ - ${targetPrefix}strip ${./darwin-strip-wrapper.sh} \ - "${bintools_bin}/bin/${targetPrefix}strip" - '' - ## ## Extra custom steps ## diff --git a/pkgs/build-support/bintools-wrapper/ld-wrapper.sh b/pkgs/build-support/bintools-wrapper/ld-wrapper.sh index dcbe8a4c24948..3bd9c68f23366 100644 --- a/pkgs/build-support/bintools-wrapper/ld-wrapper.sh +++ b/pkgs/build-support/bintools-wrapper/ld-wrapper.sh @@ -257,10 +257,13 @@ PATH="$path_backup" # Old bash workaround, see above. if (( "${NIX_LD_USE_RESPONSE_FILE:-@use_response_file_by_default@}" >= 1 )); then - @prog@ @<(printf "%q\n" \ - ${extraBefore+"${extraBefore[@]}"} \ - ${params+"${params[@]}"} \ - ${extraAfter+"${extraAfter[@]}"}) + responseFile=$(mktemp "${TMPDIR:-/tmp}/ld-params.XXXXXX") + trap 'rm -f -- "$responseFile"' EXIT + printf "%q\n" \ + ${extraBefore+"${extraBefore[@]}"} \ + ${params+"${params[@]}"} \ + ${extraAfter+"${extraAfter[@]}"} > "$responseFile" + @prog@ "@$responseFile" else @prog@ \ ${extraBefore+"${extraBefore[@]}"} \ diff --git a/pkgs/build-support/libredirect/default.nix b/pkgs/build-support/libredirect/default.nix index c4399189b7a21..9998241673886 100644 --- a/pkgs/build-support/libredirect/default.nix +++ b/pkgs/build-support/libredirect/default.nix @@ -1,12 +1,5 @@ -{ lib, stdenv, bintools-unwrapped, llvmPackages, llvmPackages_13, coreutils }: - -let - # aarch64-darwin needs a clang that can build arm64e binaries, so make sure a version of LLVM - # is used that can do that, but prefer the stdenv one if it is new enough. - llvmPkgs = if (lib.versionAtLeast (lib.getVersion llvmPackages.clang) "13") - then llvmPackages - else llvmPackages_13; - in +{ lib, stdenv, bintools-unwrapped, llvmPackages, coreutils }: + if stdenv.hostPlatform.isStatic then throw '' libredirect is not available on static builds. @@ -46,11 +39,11 @@ else stdenv.mkDerivation rec { # and the library search directory for libdl. # We can't build this on x86_64, because the libSystem we point to doesn't # like arm64(e). - PATH=${bintools-unwrapped}/bin:${llvmPkgs.clang-unwrapped}/bin:$PATH \ + PATH=${bintools-unwrapped}/bin:${llvmPackages.clang-unwrapped}/bin:$PATH \ clang -arch x86_64 -arch arm64 -arch arm64e \ - -isystem ${llvmPkgs.clang.libc}/include \ - -isystem ${llvmPkgs.libclang.lib}/lib/clang/*/include \ - -L${llvmPkgs.clang.libc}/lib \ + -isystem ${llvmPackages.clang.libc}/include \ + -isystem ${llvmPackages.libclang.lib}/lib/clang/*/include \ + -L${llvmPackages.clang.libc}/lib \ -Wl,-install_name,$libName \ -Wall -std=c99 -O3 -fPIC libredirect.c \ -shared -o "$libName" diff --git a/pkgs/by-name/cc/cctools/0001-Fix-build-issues-with-misc-redo_prebinding.c.patch b/pkgs/by-name/cc/cctools/0001-Fix-build-issues-with-misc-redo_prebinding.c.patch new file mode 100644 index 0000000000000..5908d030dbfd2 --- /dev/null +++ b/pkgs/by-name/cc/cctools/0001-Fix-build-issues-with-misc-redo_prebinding.c.patch @@ -0,0 +1,53 @@ +From 55b2a5fcc38eb62f53e155bd8c741481690f1c73 Mon Sep 17 00:00:00 2001 +From: Randy Eckenrode +Date: Wed, 10 Apr 2024 19:08:39 -0400 +Subject: [PATCH 1/6] Fix build issues with misc/redo_prebinding.c + +- Add missing headers; and +- Add missing arguments to `writeout`. +--- + misc/redo_prebinding.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/misc/redo_prebinding.c b/misc/redo_prebinding.c +index a5a3c81..9d0f4c8 100644 +--- a/misc/redo_prebinding.c ++++ b/misc/redo_prebinding.c +@@ -83,6 +83,7 @@ + #include + #endif /* defined(LIBRARY_API) */ + ++#import + #import + #import + #import +@@ -106,7 +107,7 @@ + #import + #import + #import +-//#import ++#import + #import + + #include +@@ -918,7 +919,7 @@ char *envp[]) + if(write_to_stdout) + output_file = NULL; + writeout(archs, narchs, output_file, mode, TRUE, FALSE, FALSE, +- FALSE, NULL); ++ FALSE, FALSE, NULL); + if(errors){ + if(write_to_stdout == FALSE) + unlink(output_file); +@@ -928,7 +929,7 @@ char *envp[]) + else{ + output_file = makestr(input_file, ".redo_prebinding", NULL); + writeout(archs, narchs, output_file, mode, TRUE, FALSE, FALSE, +- FALSE, NULL); ++ FALSE, FALSE, NULL); + if(errors){ + unlink(output_file); + return(2); +-- +2.45.2 + diff --git a/pkgs/by-name/cc/cctools/0002-Rely-on-libcd_is_blob_a_linker_signature.patch b/pkgs/by-name/cc/cctools/0002-Rely-on-libcd_is_blob_a_linker_signature.patch new file mode 100644 index 0000000000000..014281039ae87 --- /dev/null +++ b/pkgs/by-name/cc/cctools/0002-Rely-on-libcd_is_blob_a_linker_signature.patch @@ -0,0 +1,25 @@ +From 419c469634891d09f6688d56da9e26431018f342 Mon Sep 17 00:00:00 2001 +From: Randy Eckenrode +Date: Wed, 10 Apr 2024 20:36:53 -0400 +Subject: [PATCH 2/6] Rely on libcd_is_blob_a_linker_signature + +--- + libstuff/code_directory.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libstuff/code_directory.c b/libstuff/code_directory.c +index 7c158fa..3b8eb77 100644 +--- a/libstuff/code_directory.c ++++ b/libstuff/code_directory.c +@@ -146,7 +146,7 @@ static const char* format_version_xyz(uint32_t version) + */ + int codedir_is_linker_signed(const char* data, uint32_t size) + { +-#if 1 ++#if 0 + // HACK: libcodedirectory.h is in both the macOS SDK in /usr/local/include, and in the tool chain at /usr/include. + // but there is no way to control clang's search path to look in the toolchain first. + // So, declare newer API locally. Once this new header is in all SDKs we can remove this. +-- +2.45.2 + diff --git a/pkgs/by-name/cc/cctools/0003-Fix-utimensat-compatability-with-the-10.12-SDK.patch b/pkgs/by-name/cc/cctools/0003-Fix-utimensat-compatability-with-the-10.12-SDK.patch new file mode 100644 index 0000000000000..4abe9ee863aa7 --- /dev/null +++ b/pkgs/by-name/cc/cctools/0003-Fix-utimensat-compatability-with-the-10.12-SDK.patch @@ -0,0 +1,50 @@ +From 989ba5e30cefa0dd8990da158661713c4a21c0fe Mon Sep 17 00:00:00 2001 +From: Randy Eckenrode +Date: Thu, 11 Apr 2024 18:05:34 -0400 +Subject: [PATCH 3/6] Fix utimensat compatability with the 10.12 SDK + +--- + include/compat.h | 3 +++ + libstuff/writeout.c | 2 +- + misc/lipo.c | 2 +- + 3 files changed, 5 insertions(+), 2 deletions(-) + create mode 100644 include/compat.h + +diff --git a/include/compat.h b/include/compat.h +new file mode 100644 +index 0000000..8b1b866 +--- /dev/null ++++ b/include/compat.h +@@ -0,0 +1,3 @@ ++#pragma once ++#include ++extern int utimensat(int dirfd, const char* pathname, const struct timespec times[_Nullable 2], int flags); +diff --git a/libstuff/writeout.c b/libstuff/writeout.c +index f904caa..03fa535 100644 +--- a/libstuff/writeout.c ++++ b/libstuff/writeout.c +@@ -297,7 +297,7 @@ no_throttle: + * have been zeroed out when the library was created. writeout + * will not zero out the modification time in the filesystem. + */ +- if (__builtin_available(macOS 10.12, *)) { ++ if (__builtin_available(macOS 10.13, *)) { + struct timespec times[2] = {0}; + memcpy(×[0], &toc_timespec, sizeof(struct timespec)); + memcpy(×[1], &toc_timespec, sizeof(struct timespec)); +diff --git a/misc/lipo.c b/misc/lipo.c +index 04a3eca..887c049 100644 +--- a/misc/lipo.c ++++ b/misc/lipo.c +@@ -607,7 +607,7 @@ unknown_flag: + if(close(fd) == -1) + system_fatal("can't close output file: %s",output_file); + #ifndef __OPENSTEP__ +- if (__builtin_available(macOS 10.12, *)) { ++ if (__builtin_available(macOS 10.13, *)) { + time_result = utimensat(AT_FDCWD, output_file, + output_times, 0); + } +-- +2.45.2 + diff --git a/pkgs/by-name/cc/cctools/0004-Use-nixpkgs-clang-with-the-assembler-driver.patch b/pkgs/by-name/cc/cctools/0004-Use-nixpkgs-clang-with-the-assembler-driver.patch new file mode 100644 index 0000000000000..058cfcdf0c490 --- /dev/null +++ b/pkgs/by-name/cc/cctools/0004-Use-nixpkgs-clang-with-the-assembler-driver.patch @@ -0,0 +1,57 @@ +From 86b5ad551ef0ffc7ca4da24b7619937bec738522 Mon Sep 17 00:00:00 2001 +From: Randy Eckenrode +Date: Mon, 15 Apr 2024 20:47:59 -0400 +Subject: [PATCH 4/6] Use nixpkgs clang with the assembler driver + +--- + as/driver.c | 20 +++----------------- + 1 file changed, 3 insertions(+), 17 deletions(-) + +diff --git a/as/driver.c b/as/driver.c +index a0d49ad..c15dcbf 100644 +--- a/as/driver.c ++++ b/as/driver.c +@@ -36,7 +36,7 @@ char **envp) + char *p, c, *arch_name, *as, *as_local; + char **new_argv; + const char *CLANG = "clang"; +- char *prefix, buf[MAXPATHLEN], resolved_name[PATH_MAX]; ++ char *prefix = "@clang-unwrapped@/bin/"; + uint32_t bufsize; + struct arch_flag arch_flag; + const struct arch_flag *arch_flags, *family_arch_flag; +@@ -50,22 +50,6 @@ char **envp) + qflag = FALSE; + Qflag = FALSE; + some_input_files = FALSE; +- /* +- * Construct the prefix to the assembler driver. +- */ +- bufsize = MAXPATHLEN; +- p = buf; +- i = _NSGetExecutablePath(p, &bufsize); +- if(i == -1){ +- p = allocate(bufsize); +- _NSGetExecutablePath(p, &bufsize); +- } +- prefix = realpath(p, resolved_name); +- if(prefix == NULL) +- system_fatal("realpath(3) for %s failed", p); +- p = rindex(prefix, '/'); +- if(p != NULL) +- p[1] = '\0'; + /* + * Process the assembler flags exactly like the assembler would (except + * let the assembler complain about multiple flags, bad combinations of +@@ -362,6 +346,8 @@ char **envp) + exit(1); + } + ++ prefix = "@gas@/bin/"; /* `libexec` is found relative to the assembler driver’s path. */ ++ + /* + * If this assembler exist try to run it else print an error message. + */ +-- +2.45.2 + diff --git a/pkgs/by-name/cc/cctools/0005-Find-ld64-in-the-store.patch b/pkgs/by-name/cc/cctools/0005-Find-ld64-in-the-store.patch new file mode 100644 index 0000000000000..8f51b38a9ca63 --- /dev/null +++ b/pkgs/by-name/cc/cctools/0005-Find-ld64-in-the-store.patch @@ -0,0 +1,28 @@ +From e62f7d75380540937f24f896c82736a1e653cc75 Mon Sep 17 00:00:00 2001 +From: Randy Eckenrode +Date: Mon, 22 Apr 2024 18:15:53 -0400 +Subject: [PATCH 5/6] Find ld64 in the store + +--- + libstuff/execute.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/libstuff/execute.c b/libstuff/execute.c +index 8526ab7..abbbf1b 100644 +--- a/libstuff/execute.c ++++ b/libstuff/execute.c +@@ -149,6 +149,11 @@ char * + cmd_with_prefix( + char *str) + { ++ // Return the path to ld64 in the store. ++ if (strcmp(str, "ld") == 0) { ++ return "@ld64_path@"; ++ } ++ + int i; + char *p; + char *prefix, buf[MAXPATHLEN], resolved_name[PATH_MAX]; +-- +2.45.2 + diff --git a/pkgs/by-name/cc/cctools/0006-Support-target-prefixes-in-ranlib-detection.patch b/pkgs/by-name/cc/cctools/0006-Support-target-prefixes-in-ranlib-detection.patch new file mode 100644 index 0000000000000..1189d20749844 --- /dev/null +++ b/pkgs/by-name/cc/cctools/0006-Support-target-prefixes-in-ranlib-detection.patch @@ -0,0 +1,30 @@ +From e25de788260051892b9e34177ea957cbafe6c415 Mon Sep 17 00:00:00 2001 +From: Randy Eckenrode +Date: Thu, 2 May 2024 07:55:05 -0400 +Subject: [PATCH 6/6] Support target prefixes in ranlib detection + +--- + misc/libtool.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/misc/libtool.c b/misc/libtool.c +index 289ec4d..8265d53 100644 +--- a/misc/libtool.c ++++ b/misc/libtool.c +@@ -426,11 +426,11 @@ char **envp) + p++; + else + p = argv[0]; +- if(strncmp(p, "ranlib", sizeof("ranlib") - 1) == 0) { ++ if(strncmp(p, "@targetPrefix@ranlib", sizeof("@targetPrefix@ranlib") - 1) == 0) { + cmd_flags.ranlib = TRUE; + } + else if (getenv("LIBTOOL_FORCE_RANLIB")) { +- progname = "ranlib"; ++ progname = "@targetPrefix@ranlib"; + cmd_flags.ranlib = TRUE; + } + +-- +2.45.2 + diff --git a/pkgs/by-name/cc/cctools/meson.build b/pkgs/by-name/cc/cctools/meson.build new file mode 100644 index 0000000000000..c2261d98c958a --- /dev/null +++ b/pkgs/by-name/cc/cctools/meson.build @@ -0,0 +1,657 @@ +# Build settings based on the upstream Xcode project. +# See: https://github.com/apple-oss-distributions/cctools/blob/main/cctools.xcodeproj/project.pbxproj + +# Project settings +project( + 'cctools', + 'c', + version : '@version@', + default_options : { + 'c_args': [ + '-DCCTB_MACOS=YES', + '-DCCTB_PROJECT=cctools', + '-DCCTB_PROJVERS=cctools-@version@', + '-DCCTB_VERSION=@version@', + '-DCURRENT_PROJECT_VERSION="@version@"', + '-DCODEDIRECTORY_SUPPORT', + '-DLTO_SUPPORT', + ], + }, +) + +fs = import('fs') + +# Options +target_prefix = get_option('target_prefix') + + +# Dependencies +cc = meson.get_compiler('c') + +libcodedirectory = cc.find_library('codedirectory') +libprunetrie = cc.find_library('prunetrie') + + +# Feature tests +# Add compatibility header for Darwin SDKs that don’t define `utimensat`. +utimensat_test = ''' +#include +#include +int main(int argc, char* argv[]) { + utimensat(AT_FDCWD, NULL, NULL, 0); + return 0; +} +''' +if host_machine.system() == 'darwin' and not cc.compiles(utimensat_test, name : 'supports utimensat') + add_project_arguments('-include', 'compat.h', language : 'c') + add_project_link_arguments('-undefined', 'dynamic_lookup', language : 'c') +endif + + +incdirs = include_directories('include') + +# Static libraries +libstuff = static_library( + 'stuff', + c_args : [ + '-DCPU_TYPE_RISCV32=24', # Per src/abstraction/MachOFileAbstraction.hpp from ld64 + ], + include_directories : [incdirs, 'include/stuff'], + sources : [ + 'libstuff/SymLoc.c', + 'libstuff/align.c', + 'libstuff/allocate.c', + 'libstuff/apple_version.c', + 'libstuff/arch.c', + 'libstuff/arch_usage.c', + 'libstuff/args.c', + 'libstuff/best_arch.c', + 'libstuff/breakout.c', + 'libstuff/bytesex.c', + 'libstuff/checkout.c', + 'libstuff/code_directory.c', + 'libstuff/coff_bytesex.c', + 'libstuff/crc32.c', + 'libstuff/depinfo.c', + 'libstuff/diagnostics.c', + 'libstuff/dylib_roots.c', + 'libstuff/dylib_table.c', + 'libstuff/errors.c', + 'libstuff/execute.c', + 'libstuff/fatal_arch.c', + 'libstuff/fatals.c', + 'libstuff/get_arch_from_host.c', + 'libstuff/get_toc_byte_sex.c', + 'libstuff/guess_short_name.c', + 'libstuff/hash_string.c', + 'libstuff/hppa.c', + 'libstuff/llvm.c', + 'libstuff/lto.c', + 'libstuff/macosx_deployment_target.c', + 'libstuff/ofile.c', + 'libstuff/ofile_error.c', + 'libstuff/ofile_get_word.c', + 'libstuff/print.c', + 'libstuff/reloc.c', + 'libstuff/rnd.c', + 'libstuff/seg_addr_table.c', + 'libstuff/set_arch_flag_name.c', + 'libstuff/swap_headers.c', + 'libstuff/symbol_list.c', + 'libstuff/unix_standard_mode.c', + 'libstuff/version_number.c', + 'libstuff/vm_flush_cache.c', + 'libstuff/write64.c', + 'libstuff/writeout.c', + 'libstuff/xcode.c', + ], +) + +libstuff_otool = static_library( + 'stuff_otool', + c_args : [ + '-DCPU_TYPE_RISCV32=24', # Per src/abstraction/MachOFileAbstraction.hpp from ld64 + ], + include_directories : [incdirs, 'include/stuff', 'otool'], + sources : [ + 'libstuff/SymLoc.c', + 'libstuff/align.c', + 'libstuff/allocate.c', + 'libstuff/apple_version.c', + 'libstuff/arch.c', + 'libstuff/arch_usage.c', + 'libstuff/args.c', + 'libstuff/best_arch.c', + 'libstuff/breakout.c', + 'libstuff/bytesex.c', + 'libstuff/checkout.c', + 'libstuff/code_directory.c', + 'libstuff/coff_bytesex.c', + 'libstuff/crc32.c', + 'libstuff/depinfo.c', + 'libstuff/diagnostics.c', + 'libstuff/dylib_roots.c', + 'libstuff/dylib_table.c', + 'libstuff/errors.c', + 'libstuff/execute.c', + 'libstuff/fatal_arch.c', + 'libstuff/fatals.c', + 'libstuff/get_arch_from_host.c', + 'libstuff/get_toc_byte_sex.c', + 'libstuff/guess_short_name.c', + 'libstuff/hash_string.c', + 'libstuff/hppa.c', + 'libstuff/llvm.c', + 'libstuff/lto.c', + 'libstuff/macosx_deployment_target.c', + 'libstuff/ofile.c', + 'libstuff/ofile_error.c', + 'libstuff/ofile_get_word.c', + 'libstuff/print.c', + 'libstuff/reloc.c', + 'libstuff/rnd.c', + 'libstuff/seg_addr_table.c', + 'libstuff/set_arch_flag_name.c', + 'libstuff/swap_headers.c', + 'libstuff/symbol_list.c', + 'libstuff/unix_standard_mode.c', + 'libstuff/version_number.c', + 'libstuff/vm_flush_cache.c', + 'libstuff/write64.c', + 'libstuff/writeout.c', + 'libstuff/xcode.c', + ], +) + + +# Binaries +ar = executable( + f'@target_prefix@ar', + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : [ + 'ar/append.c', + 'ar/ar.c', + 'ar/archive.c', + 'ar/contents.c', + 'ar/delete.c', + 'ar/extract.c', + 'ar/misc.c', + 'ar/move.c', + 'ar/print.c', + 'ar/replace.c', + ], +) +install_man( + 'ar/ar.1', + 'ar/ar.5', +) + +as = executable( + f'@target_prefix@gas', + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['as/driver.c'], +) + +as_common = files( + 'as/app.c', + 'as/as.c', + 'as/atof-generic.c', + 'as/atof-ieee.c', + 'as/dwarf2dbg.c', + 'as/expr.c', + 'as/fixes.c', + 'as/flonum-const.c', + 'as/flonum-copy.c', + 'as/flonum-mult.c', + 'as/frags.c', + 'as/hash.c', + 'as/hex-value.c', + 'as/input-file.c', + 'as/input-scrub.c', + 'as/layout.c', + 'as/messages.c', + 'as/obstack.c', + 'as/read.c', + 'as/sections.c', + 'as/symbols.c', + 'as/write_object.c', + 'as/xmalloc.c', +) + +as_arm = executable( + 'as-arm', + c_args : [ + '-DARM', + '-DNeXT_MOD', + ], + include_directories : [ + incdirs, + 'as', + 'include/gnu', + ], + install : true, + install_dir : 'libexec/as/arm', + link_with : [libstuff], + sources : [as_common, 'as/arm.c'], +) + +as_i386 = executable( + 'as-i386', + c_args : [ + '-DI386', + '-Di486', + '-Di586', + '-Di686', + '-DNeXT_MOD', + ], + include_directories : [ + incdirs, + 'as', + 'include/gnu', + ], + install : true, + install_dir : 'libexec/as/i386', + link_with : [libstuff], + sources : [as_common, 'as/i386.c'], +) + +as_x86_64 = executable( + 'as-x86_64', + c_args : [ + '-DI386', + '-Di486', + '-Di586', + '-Di686', + '-DARCH64', + '-DNeXT_MOD', + ], + include_directories : [ + incdirs, + 'as', + 'include/gnu' + ], + install : true, + install_dir : 'libexec/as/x86_64', + link_with : [libstuff], + sources : [as_common, 'as/i386.c'], +) + +# # ld # excluded because ld64 is built separately + +bitcode_strip = executable( + f'@target_prefix@bitcode_strip', + dependencies : [libcodedirectory], + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/bitcode_strip.c'], +) +install_man('man/bitcode_strip.1') + +check_dylib = executable( + f'@target_prefix@check_dylib', + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/check_dylib.c'], +) +install_man('man/check_dylib.1') + +checksyms = executable( + f'@target_prefix@checksyms', + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/checksyms.c'], +) +install_man('man/checksyms.1') + +cmpdylib = executable( + f'@target_prefix@cmpdylib', + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/cmpdylib.c'], +) +install_man('man/cmpdylib.1') + +codesign_allocate = executable( + f'@target_prefix@codesign_allocate', + dependencies : [libcodedirectory], + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/codesign_allocate.c'], +) +install_man('man/codesign_allocate.1') + +ctf_insert = executable( + f'@target_prefix@ctf_insert', + dependencies : [libcodedirectory], + include_directories : [incdirs, 'include/stuff'], + install : true, + link_with : [libstuff], + sources : ['misc/ctf_insert.c'], +) +install_man('man/ctf_insert.1') + +depinfo = executable( + f'@target_prefix@depinfo', + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/depinfo.c'], +) +install_man('man/depinfo.1') + +diagtest = executable( + f'@target_prefix@diagtest', + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/diagtest.c'], +) +install_man('man/diagtest.1') + +gprof = executable( + f'@target_prefix@gprof', + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : [ + 'gprof/arcs.c', + 'gprof/calls.c', + 'gprof/dfn.c', + 'gprof/getnfile.c', + 'gprof/gprof.c', + 'gprof/hertz.c', + 'gprof/lookup.c', + 'gprof/printgprof.c', + 'gprof/printlist.c', + 'gprof/scatter.c', + ], +) +install_man('man/gprof.1') + +# Not supported on 64-bit architectures +# indr = executable( +# f'@target_prefix@indr', +# include_directories : incdirs, +# sources : ['misc/indr.c'], +# ) +# install_man('man/indr.1') + +install_name_tool = executable( + f'@target_prefix@install_name_tool', + dependencies : [libcodedirectory], + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/install_name_tool.c'], +) +install_man('man/install_name_tool.1') + +libtool = executable( + f'@target_prefix@libtool', + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/libtool.c'], +) +install_man('man/libtool.1') + +lipo = executable( + f'@target_prefix@lipo', + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/lipo.c'], +) +install_man('man/lipo.1') + +mtoc = executable( + f'@target_prefix@mtoc', + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['efitools/mtoc.c'], +) +install_man('man/mtoc.1') + +mtor = executable( + f'@target_prefix@mtor', + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['efitools/mtor.c'], +) +install_man('man/mtor.1') + +nm = executable( + f'@target_prefix@nm', + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/nm.c'], +) +install_man('man/nm-classic.1') + +nmedit = executable( + f'@target_prefix@nmedit', + c_args : ['-DNMEDIT'], + dependencies : [libcodedirectory], + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/strip.c'], +) +install_man('man/nmedit.1') + +otool = executable( + f'@target_prefix@otool', + c_args : ['-DEFI_SUPPORT'], + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : [ + 'otool/arm64_disasm.c', + 'otool/arm_disasm.c', + 'otool/coff_print.c', + 'otool/dyld_bind_info.c', + 'otool/hppa_disasm.c', + 'otool/i386_disasm.c', + 'otool/i860_disasm.c', + 'otool/m68k_disasm.c', + 'otool/m88k_disasm.c', + 'otool/main.c', + 'otool/ofile_print.c', + 'otool/ppc_disasm.c', + 'otool/print_bitcode.c', + 'otool/print_objc.c', + 'otool/print_objc2_32bit.c', + 'otool/print_objc2_64bit.c', + 'otool/print_objc2_util.c', + 'otool/sparc_disasm.c', + ], +) +install_man('man/otool-classic.1') + +pagestuff = executable( + f'@target_prefix@pagestuff', + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/pagestuff.c'], +) +install_man('man/pagestuff.1') + +# ranlib is a symlink to libtool +install_man( + 'man/ranlib.1', + 'man/ranlib.5', +) + +redo_prebinding = executable( + f'@target_prefix@redo_prebinding', + dependencies : [libcodedirectory], + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/redo_prebinding.c'], +) +install_man('man/redo_prebinding.1') + +seg_addr_table = executable( + f'@target_prefix@seg_addr_table', + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/seg_addr_table.c'], +) +install_man('man/seg_addr_table.1') + +seg_hack = executable( + f'@target_prefix@seg_hack', + dependencies : [libcodedirectory], + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/seg_hack.c'], +) + +segedit = executable( + f'@target_prefix@segedit', + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/segedit.c'], +) +install_man('man/segedit.1',) + +size = executable( + f'@target_prefix@size', + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/size.c'], +) +install_man('man/size-classic.1') + +strings = executable( + f'@target_prefix@strings', + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/strings.c'], +) +install_man('man/strings.1') + +strip = executable( + f'@target_prefix@strip', + c_args : ['-DTRIE_SUPPORT'], + dependencies : [libcodedirectory, libprunetrie], + include_directories : incdirs, + install : true, + link_with : [libstuff], + sources : ['misc/strip.c'], +) +install_man('man/strip.1') + +vtool = executable( + f'@target_prefix@vtool', + dependencies : [libcodedirectory], + include_directories : [incdirs, 'include/stuff'], + install : true, + link_with : [libstuff], + sources : ['misc/vtool.c'], +) +install_man('man/vtool.1') + + +# Development files +# Static libraries +libmacho = static_library( + 'macho', + include_directories : incdirs, + sources : [ + 'libmacho/arch.c', + 'libmacho/get_end.c', + 'libmacho/getsecbyname.c', + 'libmacho/getsegbyname.c', + 'libmacho/hppa_swap.c', + 'libmacho/i386_swap.c', + 'libmacho/i860_swap.c', + 'libmacho/m68k_swap.c', + 'libmacho/m88k_swap.c', + 'libmacho/ppc_swap.c', + 'libmacho/slot_name.c', + 'libmacho/sparc_swap.c', + 'libmacho/swap.c', + ], +) + +libredo_prebinding = static_library( + 'redo_prebinding', + c_args : ['-DLIBRARY_API'], + include_directories : incdirs, + sources : ['misc/redo_prebinding.c'], +) +install_man('man/redo_prebinding.3') + + +# Development files +# Based on the contents of the upstream SDK. +install_headers( + 'include/mach-o/arch.h', + 'include/mach-o/fat.h', + 'include/mach-o/getsect.h', + 'include/mach-o/ldsyms.h', + 'include/mach-o/loader.h', + 'include/mach-o/nlist.h', + 'include/mach-o/ranlib.h', + 'include/mach-o/reloc.h', + 'include/mach-o/stab.h', + 'include/mach-o/swap.h', + subdir : 'mach-o', +) + +# Some of these architectures are irrelevant, but the Libsystem derivation expects their headers to be present. +# Not every arch has both headers, so tailor the lists for each that does. +foreach arch : ['arm', 'arm64', 'hppa', 'i860', 'm88k', 'ppc', 'sparc', 'x86_64'] + install_headers( + f'include/mach-o/@arch@/reloc.h', + subdir : f'mach-o/@arch@', + ) +endforeach +foreach arch : ['hppa', 'i386', 'i860', 'm68k', 'm88k', 'ppc', 'sparc'] + install_headers( + f'include/mach-o/@arch@/swap.h', + subdir : f'mach-o/@arch@', + ) +endforeach + +install_data( + 'include/modules/mach-o.modulemap', + install_dir : get_option('includedir'), + rename : 'mach-o/module.map', +) +install_man( + 'man/Mach-O.5', + 'man/NSModule.3', + 'man/NSObjectFileImage.3', + 'man/NSObjectFileImage_priv.3', + 'man/arch.3', + 'man/dyld.3', + 'man/end.3', + 'man/get_end.3', + 'man/getsectbyname.3', + 'man/getsectbynamefromheader.3', + 'man/getsectdata.3', + 'man/getsectdatafromheader.3', + 'man/getsegbyname.3', + 'man/stab.5', +) diff --git a/pkgs/by-name/cc/cctools/meson.options b/pkgs/by-name/cc/cctools/meson.options new file mode 100644 index 0000000000000..2417b81f0401e --- /dev/null +++ b/pkgs/by-name/cc/cctools/meson.options @@ -0,0 +1,6 @@ +option( + 'target_prefix', + type : 'string', + value : '', + description: 'Specifies the prefix to use when building for cross-compilation (e.g., `aarch64-apple-darwin`)' +) diff --git a/pkgs/by-name/cc/cctools/package.nix b/pkgs/by-name/cc/cctools/package.nix new file mode 100644 index 0000000000000..2ab074def6740 --- /dev/null +++ b/pkgs/by-name/cc/cctools/package.nix @@ -0,0 +1,175 @@ +{ + lib, + stdenv, + fetchFromGitHub, + buildPackages, + darwin, + ld64, + llvm, + memstreamHook, + meson, + ninja, + openssl, + xar, + gitUpdater, +}: + +let + # The targetPrefix is prepended to binary names to allow multiple binuntils on the PATH to both be usable. + targetPrefix = lib.optionalString ( + stdenv.targetPlatform != stdenv.hostPlatform + ) "${stdenv.targetPlatform.config}-"; + + # First version with all the required files + xnu = fetchFromGitHub { + name = "xnu-src"; + owner = "apple-oss-distributions"; + repo = "xnu"; + rev = "xnu-7195.50.7.100.1"; + hash = "sha256-uHmAOm6k9ZXWfyqHiDSpm+tZqUbERlr6rXSJ4xNACkM="; + }; +in +stdenv.mkDerivation (finalAttrs: { + pname = "${targetPrefix}cctools"; + version = "1010.6"; + + outputs = [ + "out" + "dev" + "man" + "gas" + ]; + + src = fetchFromGitHub { + owner = "apple-oss-distributions"; + repo = "cctools"; + rev = "cctools-${finalAttrs.version}"; + hash = "sha256-JiKCP6U+xxR4mk4TXWv/mEo9Idg+QQqUYmB/EeRksCE="; + }; + + xcodeHash = "sha256-5RBbGrz1UKV0wt2Uk7RIHdfgWH8sgw/jy7hfTVrtVuM="; + + 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/cctools.xcodeproj/project.pbxproj" | base64) + + if [ "$hash" != "$expectedHash" ]; then + echo 'error: hash mismatch in cctools.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 cctools.xcodeproj/project.pbxproj` to regenerate it.' + exit 1 + fi + ''; + + patches = [ + # Fix compile errors in redo_prebinding.c + ./0001-Fix-build-issues-with-misc-redo_prebinding.c.patch + # Use libcd_is_blob_a_linker_signature as defined in the libcodedirectory.h header + ./0002-Rely-on-libcd_is_blob_a_linker_signature.patch + # cctools uses availability checks for `utimensat`, but it checks the wrong version. + # Also, provide a definition to avoid implicit function definition errors. + ./0003-Fix-utimensat-compatability-with-the-10.12-SDK.patch + # Use the nixpkgs clang’s path as the prefix. + ./0004-Use-nixpkgs-clang-with-the-assembler-driver.patch + # Make sure cctools can find ld64 in the store + ./0005-Find-ld64-in-the-store.patch + # `ranlib` is a symlink to `libtool`. Make sure its detection works when it is used in cross-compilation. + ./0006-Support-target-prefixes-in-ranlib-detection.patch + ]; + + postPatch = '' + substitute ${./meson.build} meson.build \ + --subst-var version + cp ${./meson.options} meson.options + + # Make sure as’s clang driver uses clang from nixpkgs and finds the drivers in the store. + substituteInPlace as/driver.c \ + --subst-var-by clang-unwrapped '${lib.getBin buildPackages.clang.cc}' \ + --subst-var-by gas '${placeholder "gas"}' + + # Need to set the path to make sure cctools can find ld64 in the store. + substituteInPlace libstuff/execute.c \ + --subst-var-by ld64_path '${lib.getBin ld64}/bin/ld' + + # Set the target prefix for `ranlib` + substituteInPlace misc/libtool.c \ + --subst-var-by targetPrefix '${targetPrefix}' + + # The version of this file distributed with cctools defines several CPU types missing from the 10.12 SDK. + ln -s machine-cctools.h include/mach/machine.h + + # Use libxar from nixpkgs + for cctool_src in misc/nm.c otool/print_bitcode.c; do + substituteInPlace $cctool_src \ + --replace-fail 'makestr(prefix, "../lib/libxar.dylib", NULL)' '"${lib.getLib xar}/lib/libxar.dylib"' \ + --replace-fail '/usr/lib/libxar.dylib' '${lib.getLib xar}/lib/libxar.dylib' + done + + # Use libLTO.dylib from nixpkgs LLVM + substituteInPlace libstuff/llvm.c \ + --replace-fail 'getenv("LIBLTO_PATH")' '"${lib.getLib llvm}/lib/libLTO.dylib"' + + cp ../xnu-src/EXTERNAL_HEADERS/mach-o/fixup-chains.h include/mach-o/fixup-chains.h + ''; + + strictDeps = true; + + nativeBuildInputs = [ + meson + ninja + openssl + ]; + + buildInputs = + [ + ld64 + llvm + ] + ++ lib.optionals stdenv.isDarwin [ darwin.objc4 ] + ++ lib.optionals (stdenv.isDarwin && stdenv.isx86_64) [ memstreamHook ]; + + mesonBuildType = "release"; + + mesonFlags = [ + (lib.mesonOption "b_ndebug" "if-release") + ] ++ lib.optionals (targetPrefix != "") [ (lib.mesonOption "target_prefix" targetPrefix) ]; + + postInstall = '' + ln -s ${targetPrefix}libtool "$out/bin/${targetPrefix}ranlib" + ln -s nm-classic.1 "''${!outputMan}/share/man/man1/nm.1" + ln -s otool-classic.1 "''${!outputMan}/share/man/man1/otool.1" + ln -s size-classic.1 "''${!outputMan}/share/man/man1/size.1" + + # Move GNU as to its own output to prevent it from being used accidentally. + moveToOutput bin/gas "$gas" + moveToOutput libexec "$gas" + for arch in arm i386 x86_64; do + mv "$gas/libexec/as/$arch/as-$arch" "$gas/libexec/as/$arch/as" + done + ''; + + __structuredAttrs = true; + + passthru = { + inherit targetPrefix; + updateScript = gitUpdater { rev-prefix = "cctools-"; }; + }; + + meta = { + description = "The classic linker for Darwin"; + homepage = "https://opensource.apple.com/releases/"; + license = with lib.licenses; [ + apple-psl20 + gpl2 # GNU as + ]; + maintainers = with lib.maintainers; [ reckenrode ]; + platforms = lib.platforms.darwin; + }; +}) diff --git a/pkgs/by-name/ld/ld64/0004-Use-std-atomics-and-std-mutex.patch b/pkgs/by-name/ld/ld64/0004-Use-std-atomics-and-std-mutex.patch new file mode 100644 index 0000000000000..8c414fcb51d8b --- /dev/null +++ b/pkgs/by-name/ld/ld64/0004-Use-std-atomics-and-std-mutex.patch @@ -0,0 +1,181 @@ +From 5e92d65ef2b5cc07dc25b5b1bf645b314599f5d1 Mon Sep 17 00:00:00 2001 +From: Randy Eckenrode +Date: Sat, 6 Apr 2024 20:29:25 -0400 +Subject: [PATCH 4/8] Use std::atomics and std::mutex + +--- + src/ld/InputFiles.cpp | 13 ++++++------- + src/ld/InputFiles.h | 9 +++++---- + src/ld/OutputFile.cpp | 13 ++++++------- + src/ld/ld.cpp | 11 +++++------ + 4 files changed, 22 insertions(+), 24 deletions(-) + +diff --git a/src/ld/InputFiles.cpp b/src/ld/InputFiles.cpp +index ec53a60..427ab09 100644 +--- a/src/ld/InputFiles.cpp ++++ b/src/ld/InputFiles.cpp +@@ -42,7 +42,6 @@ + #include + #include + #include +-#include + #if HAVE_LIBDISPATCH + #include + #endif +@@ -387,16 +386,16 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib + + ld::relocatable::File* objResult = mach_o::relocatable::parse(p, len, info.path, info.modTime, info.ordinal, objOpts); + if ( objResult != NULL ) { +- OSAtomicAdd64(len, &_totalObjectSize); +- OSAtomicIncrement32(&_totalObjectLoaded); ++ _totalObjectSize += len; ++ ++_totalObjectLoaded; + return objResult; + } + + // see if it is an llvm object file + objResult = lto::parse(p, len, info.path, info.modTime, info.ordinal, _options.architecture(), _options.subArchitecture(), _options.logAllFiles(), _options.verboseOptimizationHints()); + if ( objResult != NULL ) { +- OSAtomicAdd64(len, &_totalObjectSize); +- OSAtomicIncrement32(&_totalObjectLoaded); ++ _totalObjectSize += len; ++ ++_totalObjectLoaded; + return objResult; + } + +@@ -444,8 +443,8 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib + ld::archive::File* archiveResult = ::archive::parse(p, len, info.path, info.modTime, info.ordinal, archOpts); + if ( archiveResult != NULL ) { + +- OSAtomicAdd64(len, &_totalArchiveSize); +- OSAtomicIncrement32(&_totalArchivesLoaded); ++ _totalArchiveSize += len; ++ ++_totalArchivesLoaded; + return archiveResult; + } + +diff --git a/src/ld/InputFiles.h b/src/ld/InputFiles.h +index c18ccf8..ffff26b 100644 +--- a/src/ld/InputFiles.h ++++ b/src/ld/InputFiles.h +@@ -46,6 +46,7 @@ + #include + #endif + ++#include + #include + + #include "Options.h" +@@ -78,10 +79,10 @@ public: + size_t count() const { return _inputFiles.size(); } + + // for -print_statistics +- volatile int64_t _totalObjectSize; +- volatile int64_t _totalArchiveSize; +- volatile int32_t _totalObjectLoaded; +- volatile int32_t _totalArchivesLoaded; ++ std::atomic _totalObjectSize; ++ std::atomic _totalArchiveSize; ++ std::atomic _totalObjectLoaded; ++ std::atomic _totalArchivesLoaded; + int32_t _totalDylibsLoaded; + + +diff --git a/src/ld/OutputFile.cpp b/src/ld/OutputFile.cpp +index e2c0397..15912a2 100644 +--- a/src/ld/OutputFile.cpp ++++ b/src/ld/OutputFile.cpp +@@ -43,11 +43,10 @@ + #include + #include + #include +-#include + extern "C" { + #include + } +-#include ++#include + #include + #include + #include +@@ -1362,7 +1361,7 @@ void OutputFile::rangeCheckRISCVBranch20(int64_t displacement, ld::Internal& sta + + + #if SUPPORT_ARCH_arm64e +-static os_lock_unfair_s sAuthenticatedFixupDataLock = OS_LOCK_UNFAIR_INIT; // to serialize building of _authenticatedFixupData ++static std::mutex sAuthenticatedFixupDataLock; // to serialize building of _authenticatedFixupData + #endif + + void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::Atom* atom, uint8_t* buffer) +@@ -1737,11 +1736,11 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld:: + } + else { + auto fixupOffset = (uintptr_t)(fixUpLocation - mhAddress); +- os_lock_lock(&sAuthenticatedFixupDataLock); ++ sAuthenticatedFixupDataLock.lock(); + assert(_authenticatedFixupData.find(fixupOffset) == _authenticatedFixupData.end()); + auto authneticatedData = std::make_pair(authData, accumulator); + _authenticatedFixupData[fixupOffset] = authneticatedData; +- os_lock_unlock(&sAuthenticatedFixupDataLock); ++ sAuthenticatedFixupDataLock.unlock(); + // Zero out this entry which we will expect later. + set64LE(fixUpLocation, 0); + } +@@ -1768,11 +1767,11 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld:: + } + else { + auto fixupOffset = (uintptr_t)(fixUpLocation - mhAddress); +- os_lock_lock(&sAuthenticatedFixupDataLock); ++ sAuthenticatedFixupDataLock.lock(); + assert(_authenticatedFixupData.find(fixupOffset) == _authenticatedFixupData.end()); + auto authneticatedData = std::make_pair(authData, accumulator); + _authenticatedFixupData[fixupOffset] = authneticatedData; +- os_lock_unlock(&sAuthenticatedFixupDataLock); ++ sAuthenticatedFixupDataLock.unlock(); + // Zero out this entry which we will expect later. + set64LE(fixUpLocation, 0); + } +diff --git a/src/ld/ld.cpp b/src/ld/ld.cpp +index b7590a3..f1bf9df 100644 +--- a/src/ld/ld.cpp ++++ b/src/ld/ld.cpp +@@ -47,9 +47,8 @@ extern "C" double log2 ( double ); + #include + #include + #include +-#include + +-#include ++#include + #include + #include + #include +@@ -1603,8 +1602,8 @@ int main(int argc, const char* argv[]) + statistics.vmEnd.faults-statistics.vmStart.faults); + fprintf(stderr, "memory active: %lu, wired: %lu\n", statistics.vmEnd.active_count * vm_page_size, statistics.vmEnd.wire_count * vm_page_size); + char temp[40]; +- fprintf(stderr, "processed %3u object files, totaling %15s bytes\n", inputFiles._totalObjectLoaded, commatize(inputFiles._totalObjectSize, temp)); +- fprintf(stderr, "processed %3u archive files, totaling %15s bytes\n", inputFiles._totalArchivesLoaded, commatize(inputFiles._totalArchiveSize, temp)); ++ fprintf(stderr, "processed %3u object files, totaling %15s bytes\n", inputFiles._totalObjectLoaded.load(), commatize(inputFiles._totalObjectSize.load(), temp)); ++ fprintf(stderr, "processed %3u archive files, totaling %15s bytes\n", inputFiles._totalArchivesLoaded.load(), commatize(inputFiles._totalArchiveSize.load(), temp)); + fprintf(stderr, "processed %3u dylib files\n", inputFiles._totalDylibsLoaded); + fprintf(stderr, "wrote output file totaling %15s bytes\n", commatize(out.fileSize(), temp)); + } +@@ -1634,12 +1633,12 @@ int main(int argc, const char* argv[]) + #ifndef NDEBUG + + // now that the linker is multi-threaded, only allow one assert() to be processed +-static os_lock_unfair_s sAssertLock = OS_LOCK_UNFAIR_INIT; ++static std::mutex sAssertLock; + + // implement assert() function to print out a backtrace before aborting + void __assert_rtn(const char* func, const char* file, int line, const char* failedexpr) + { +- os_lock_lock(&sAssertLock); ++ sAssertLock.lock(); + + Snapshot *snapshot = Snapshot::globalSnapshot; + +-- +2.45.1 + diff --git a/pkgs/by-name/ld/ld64/0005-Support-LTO-in-nixpkgs.patch b/pkgs/by-name/ld/ld64/0005-Support-LTO-in-nixpkgs.patch new file mode 100644 index 0000000000000..fec7e31b5cdfc --- /dev/null +++ b/pkgs/by-name/ld/ld64/0005-Support-LTO-in-nixpkgs.patch @@ -0,0 +1,48 @@ +From faa5ab7c6e8d9a6c6157a2b681edad592ce78555 Mon Sep 17 00:00:00 2001 +From: Randy Eckenrode +Date: Sun, 7 Apr 2024 15:33:36 -0400 +Subject: [PATCH 5/8] Support LTO in nixpkgs + +--- + src/ld/InputFiles.cpp | 11 ++--------- + src/ld/parsers/lto_file.cpp | 2 +- + 2 files changed, 3 insertions(+), 10 deletions(-) + +diff --git a/src/ld/InputFiles.cpp b/src/ld/InputFiles.cpp +index 427ab09..b8a9870 100644 +--- a/src/ld/InputFiles.cpp ++++ b/src/ld/InputFiles.cpp +@@ -464,15 +464,8 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib + if ( _options.overridePathlibLTO() != NULL ) { + libLTO = _options.overridePathlibLTO(); + } +- else if ( _NSGetExecutablePath(ldPath, &bufSize) != -1 ) { +- if ( realpath(ldPath, tmpPath) != NULL ) { +- char* lastSlash = strrchr(tmpPath, '/'); +- if ( lastSlash != NULL ) +- strcpy(lastSlash, "/../lib/libLTO.dylib"); +- libLTO = tmpPath; +- if ( realpath(tmpPath, libLTOPath) != NULL ) +- libLTO = libLTOPath; +- } ++ else { ++ libLTO = "@libllvm@/lib/libLTO.dylib"; + } + throwf("could not process llvm bitcode object file, because %s could not be loaded", libLTO); + } +diff --git a/src/ld/parsers/lto_file.cpp b/src/ld/parsers/lto_file.cpp +index 5318212..e18e974 100644 +--- a/src/ld/parsers/lto_file.cpp ++++ b/src/ld/parsers/lto_file.cpp +@@ -1807,7 +1807,7 @@ bool optimize( const std::vector& allAtoms, + + }; // namespace lto + +-static const char *sLTODylib = "@rpath/libLTO.dylib"; ++static const char *sLTODylib = "@libllvm@/lib/libLTO.dylib"; + static std::atomic sLTOIsLoaded(false); + + static void *getHandle() { +-- +2.45.1 + diff --git a/pkgs/by-name/ld/ld64/0006-Add-libcd_is_blob_a_linker_signature-implementation.patch b/pkgs/by-name/ld/ld64/0006-Add-libcd_is_blob_a_linker_signature-implementation.patch new file mode 100644 index 0000000000000..e5485ab4cadc4 --- /dev/null +++ b/pkgs/by-name/ld/ld64/0006-Add-libcd_is_blob_a_linker_signature-implementation.patch @@ -0,0 +1,113 @@ +From add8bae5577ebe1c98cf7a711f87a3578a51d313 Mon Sep 17 00:00:00 2001 +From: Randy Eckenrode +Date: Mon, 8 Apr 2024 22:42:40 -0400 +Subject: [PATCH 6/8] Add libcd_is_blob_a_linker_signature implementation + +--- + compat/libcodedirectory.c | 74 +++++++++++++++++++++++++++++++++++++++ + src/ld/libcodedirectory.h | 8 +++++ + 2 files changed, 82 insertions(+) + create mode 100644 compat/libcodedirectory.c + +diff --git a/compat/libcodedirectory.c b/compat/libcodedirectory.c +new file mode 100644 +index 0000000..e584dfc +--- /dev/null ++++ b/compat/libcodedirectory.c +@@ -0,0 +1,74 @@ ++// SPDX-License-Identifier: APSL-2.0 ++// libcd_is_blob_a_linker_signature implementation written by Randy Eckenrode © 2024 ++ ++#include ++ ++#include ++ ++// References: ++// - https://forums.developer.apple.com/forums/thread/702351 ++// - https://redmaple.tech/blogs/macho-files/#codedirectory-blob ++ ++static inline uint32_t read32be(const uint8_t* data) ++{ ++ return (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]; ++} ++ ++static inline bool is_embedded_signature(uint32_t magic) { ++ switch (magic) { ++ case CSMAGIC_EMBEDDED_SIGNATURE: ++ case CSMAGIC_EMBEDDED_SIGNATURE_OLD: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static inline const uint8_t* find_code_directory(const uint8_t* data, size_t size) { ++ const uint8_t* index_ptr = data + offsetof(CS_SuperBlob, index); ++ ++ // There also needs to be space for the actual blobs, but there must be at least enough space ++ // for the blob indexes. If there’s not, then something’s wrong, and the blob is invalid. ++ uint32_t count = read32be(data + offsetof(CS_SuperBlob, count)); ++ if (count > ((data + size) - index_ptr) / sizeof(CS_BlobIndex)) { ++ return NULL; ++ } ++ ++ for (uint32_t n = 0; n < count; ++n) { ++ const uint8_t* current_index_ptr = index_ptr + n * sizeof(CS_BlobIndex); ++ uint32_t type = read32be(current_index_ptr + offsetof(CS_BlobIndex, type)); ++ if (type == CSSLOT_CODEDIRECTORY) { ++ uint32_t offset = read32be(current_index_ptr + offsetof(CS_BlobIndex, offset)); ++ if (offset > size - sizeof(CS_CodeDirectory)) { ++ return NULL; ++ } else { ++ return data + offset; ++ } ++ } ++ } ++ return NULL; ++} ++ ++enum libcd_signature_query_ret ++libcd_is_blob_a_linker_signature(const uint8_t* data, size_t size, int* linker_signed) ++{ ++ if (size < sizeof(CS_SuperBlob) + sizeof(CS_BlobIndex) + sizeof(CS_CodeDirectory)) { ++ return LIBCD_SIGNATURE_QUERY_INVALID_ARGUMENT; ++ } ++ ++ if (!is_embedded_signature(read32be(data + offsetof(CS_SuperBlob, magic)))) { ++ return LIBCD_SIGNATURE_QUERY_NOT_A_SIGNATURE; ++ } ++ ++ const uint8_t* cd = find_code_directory(data, size); ++ if (!cd) { ++ return LIBCD_SIGNATURE_QUERY_INVALID_ARGUMENT; ++ } ++ ++ uint32_t flags = read32be(cd + offsetof(CS_CodeDirectory, flags)); ++ if ((flags & CS_LINKER_SIGNED) == CS_LINKER_SIGNED) { ++ *linker_signed = 1; ++ } ++ ++ return LIBCD_SIGNATURE_QUERY_SUCCESS; ++} +diff --git a/src/ld/libcodedirectory.h b/src/ld/libcodedirectory.h +index 0e989a9..7532648 100644 +--- a/src/ld/libcodedirectory.h ++++ b/src/ld/libcodedirectory.h +@@ -116,6 +116,14 @@ enum libcd_set_linkage_ret { + + enum libcd_set_linkage_ret libcd_set_linkage(libcd *s, int linkage_hash_type, uint8_t *linkage_hash); + ++enum libcd_signature_query_ret { ++ LIBCD_SIGNATURE_QUERY_SUCCESS, ++ LIBCD_SIGNATURE_QUERY_INVALID_ARGUMENT, ++ LIBCD_SIGNATURE_QUERY_NOT_A_SIGNATURE, ++}; ++ ++enum libcd_signature_query_ret libcd_is_blob_a_linker_signature(const uint8_t* data, size_t size, int* linker_signed); ++ + __END_DECLS + + #endif // H_LIBCODEDIRECTORY +-- +2.45.1 + diff --git a/pkgs/by-name/ld/ld64/0007-Add-OpenSSL-based-CoreCrypto-digest-functions.patch b/pkgs/by-name/ld/ld64/0007-Add-OpenSSL-based-CoreCrypto-digest-functions.patch new file mode 100644 index 0000000000000..16879634338a6 --- /dev/null +++ b/pkgs/by-name/ld/ld64/0007-Add-OpenSSL-based-CoreCrypto-digest-functions.patch @@ -0,0 +1,311 @@ +From 36767c7345161baf0ab125f95c8557f8e24f25db Mon Sep 17 00:00:00 2001 +From: Randy Eckenrode +Date: Tue, 9 Apr 2024 19:28:17 -0400 +Subject: [PATCH 7/8] Add OpenSSL-based CoreCrypto digest functions + +--- + compat/CommonCrypto/CommonDigest.h | 6 +++ + compat/CommonCrypto/CommonDigestSPI.c | 21 +++++++++++ + compat/CommonCrypto/CommonDigestSPI.h | 14 +++++++ + compat/corecrypto/api_defines.h | 10 +++++ + compat/corecrypto/ccdigest.c | 53 +++++++++++++++++++++++++++ + compat/corecrypto/ccdigest.h | 27 ++++++++++++++ + compat/corecrypto/ccdigest_private.h | 19 ++++++++++ + compat/corecrypto/ccsha1.c | 22 +++++++++++ + compat/corecrypto/ccsha1.h | 9 +++++ + compat/corecrypto/ccsha2.c | 22 +++++++++++ + compat/corecrypto/ccsha2.h | 9 +++++ + 11 files changed, 212 insertions(+) + create mode 100644 compat/CommonCrypto/CommonDigest.h + create mode 100644 compat/CommonCrypto/CommonDigestSPI.c + create mode 100644 compat/CommonCrypto/CommonDigestSPI.h + create mode 100644 compat/corecrypto/api_defines.h + create mode 100644 compat/corecrypto/ccdigest.c + create mode 100644 compat/corecrypto/ccdigest.h + create mode 100644 compat/corecrypto/ccdigest_private.h + create mode 100644 compat/corecrypto/ccsha1.c + create mode 100644 compat/corecrypto/ccsha1.h + create mode 100644 compat/corecrypto/ccsha2.c + create mode 100644 compat/corecrypto/ccsha2.h + +diff --git a/compat/CommonCrypto/CommonDigest.h b/compat/CommonCrypto/CommonDigest.h +new file mode 100644 +index 0000000..a60eba7 +--- /dev/null ++++ b/compat/CommonCrypto/CommonDigest.h +@@ -0,0 +1,6 @@ ++// SPDX-License-Identifier: APSL-2.0 ++// CoreCrypto compatibility shims written by Randy Eckenrode © 2024 ++ ++#pragma once ++ ++#define CCSHA256_OUTPUT_SIZE 32 +diff --git a/compat/CommonCrypto/CommonDigestSPI.c b/compat/CommonCrypto/CommonDigestSPI.c +new file mode 100644 +index 0000000..41269fc +--- /dev/null ++++ b/compat/CommonCrypto/CommonDigestSPI.c +@@ -0,0 +1,21 @@ ++// SPDX-License-Identifier: APSL-2.0 ++// CoreCrypto compatibility shims written by Randy Eckenrode © 2024 ++ ++#include "CommonDigestSPI.h" ++ ++#include ++#include ++ ++#include ++ ++void CCDigest(int type, const uint8_t* bytes, size_t count, uint8_t* digest) { ++ if (type != kCCDigestSHA256) { ++ abort(); ++ } ++ const struct ccdigest_info* di = ccsha256_di(); ++ ++ ccdigest_di_decl(_di, ctx); ++ ccdigest_init(di, ctx); ++ ccdigest_update(di, ctx, count, bytes); ++ ccdigest_final(di, ctx, digest); ++} +diff --git a/compat/CommonCrypto/CommonDigestSPI.h b/compat/CommonCrypto/CommonDigestSPI.h +new file mode 100644 +index 0000000..172742a +--- /dev/null ++++ b/compat/CommonCrypto/CommonDigestSPI.h +@@ -0,0 +1,14 @@ ++// SPDX-License-Identifier: APSL-2.0 ++// CoreCrypto compatibility shims written by Randy Eckenrode © 2024 ++ ++#pragma once ++ ++#include ++ ++#include ++#include ++ ++ ++#define kCCDigestSHA256 10 ++ ++EXTERN_C void CCDigest(int type, const uint8_t* bytes, size_t count, uint8_t* digest); +diff --git a/compat/corecrypto/api_defines.h b/compat/corecrypto/api_defines.h +new file mode 100644 +index 0000000..13d1e7a +--- /dev/null ++++ b/compat/corecrypto/api_defines.h +@@ -0,0 +1,10 @@ ++// SPDX-License-Identifier: APSL-2.0 ++// CoreCrypto compatibility shims written by Randy Eckenrode © 2024 ++ ++#pragma once ++ ++#ifdef __cplusplus ++#define EXTERN_C extern "C" ++#else ++#define EXTERN_C ++#endif +diff --git a/compat/corecrypto/ccdigest.c b/compat/corecrypto/ccdigest.c +new file mode 100644 +index 0000000..e29dcb8 +--- /dev/null ++++ b/compat/corecrypto/ccdigest.c +@@ -0,0 +1,53 @@ ++// SPDX-License-Identifier: APSL-2.0 ++// CoreCrypto compatibility shims written by Randy Eckenrode © 2024 ++ ++#include "ccdigest.h" ++#include "ccdigest_private.h" ++ ++#include ++ ++#include ++ ++ ++struct ccdigest_context* _ccdigest_context_new(void) ++{ ++ struct ccdigest_context* ctx = malloc(sizeof(struct ccdigest_context)); ++ ctx->context = EVP_MD_CTX_new(); ++ return ctx; ++} ++ ++struct ccdigest_info* _ccdigest_newprovider(const char* name) ++{ ++ struct ccdigest_info* di = malloc(sizeof(struct ccdigest_info)); ++ di->provider = EVP_MD_fetch(NULL, name, NULL); ++ return di; ++} ++ ++void ccdigest_init(const struct ccdigest_info* di, struct ccdigest_context* ctx) ++{ ++ if (!EVP_DigestInit_ex2(ctx->context, di->provider, NULL)) { ++ ERR_print_errors_fp(stderr); ++ abort(); ++ } ++} ++ ++void ccdigest_update( ++ const struct ccdigest_info* _di, ++ struct ccdigest_context* ctx, ++ size_t count, ++ const void* bytes ++) ++{ ++ if (!EVP_DigestUpdate(ctx->context, bytes, count)) { ++ ERR_print_errors_fp(stderr); ++ abort(); ++ } ++} ++ ++void ccdigest_final(const struct ccdigest_info* _di, struct ccdigest_context* ctx, uint8_t* digest) ++{ ++ if (!EVP_DigestFinal_ex(ctx->context, digest, NULL)) { ++ ERR_print_errors_fp(stderr); ++ abort(); ++ } ++} +diff --git a/compat/corecrypto/ccdigest.h b/compat/corecrypto/ccdigest.h +new file mode 100644 +index 0000000..9af2394 +--- /dev/null ++++ b/compat/corecrypto/ccdigest.h +@@ -0,0 +1,27 @@ ++// SPDX-License-Identifier: APSL-2.0 ++// CoreCrypto compatibility shims written by Randy Eckenrode © 2024 ++ ++#pragma once ++ ++#include ++#include ++ ++#include "api_defines.h" ++ ++ ++struct ccdigest_info; ++struct ccdigest_context; ++ ++EXTERN_C struct ccdigest_context* _ccdigest_context_new(void); ++ ++#define ccdigest_di_decl(_di, ctxvar) \ ++ struct ccdigest_context* (ctxvar) = _ccdigest_context_new() ++ ++EXTERN_C void ccdigest_init(const struct ccdigest_info* di, struct ccdigest_context* ctx); ++EXTERN_C void ccdigest_update( ++ const struct ccdigest_info* _di, ++ struct ccdigest_context* ctx, ++ size_t count, ++ const void* bytes ++); ++EXTERN_C void ccdigest_final(const struct ccdigest_info* _di, struct ccdigest_context* ctx, uint8_t* digest); +diff --git a/compat/corecrypto/ccdigest_private.h b/compat/corecrypto/ccdigest_private.h +new file mode 100644 +index 0000000..0ea9759 +--- /dev/null ++++ b/compat/corecrypto/ccdigest_private.h +@@ -0,0 +1,19 @@ ++// SPDX-License-Identifier: APSL-2.0 ++// CoreCrypto compatibility shims written by Randy Eckenrode © 2024 ++ ++#pragma once ++ ++#include "api_defines.h" ++ ++#include ++ ++ ++struct ccdigest_info { ++ EVP_MD* provider; ++}; ++ ++struct ccdigest_context { ++ EVP_MD_CTX* context; ++}; ++ ++EXTERN_C struct ccdigest_info* _ccdigest_newprovider(const char* name); +diff --git a/compat/corecrypto/ccsha1.c b/compat/corecrypto/ccsha1.c +new file mode 100644 +index 0000000..e02b2b6 +--- /dev/null ++++ b/compat/corecrypto/ccsha1.c +@@ -0,0 +1,22 @@ ++// SPDX-License-Identifier: APSL-2.0 ++// CoreCrypto compatibility shims written by Randy Eckenrode © 2024 ++ ++#include "ccsha1.h" ++ ++#include ++ ++#include ++ ++#include "ccdigest_private.h" ++ ++ ++static struct ccdigest_info* di = NULL; ++ ++const struct ccdigest_info* ccsha1_di(void) ++{ ++ if (!di) { ++ di = _ccdigest_newprovider("SHA-1"); ++ assert(EVP_MD_get_size(di->provider) == CS_SHA1_LEN); ++ } ++ return di; ++} +diff --git a/compat/corecrypto/ccsha1.h b/compat/corecrypto/ccsha1.h +new file mode 100644 +index 0000000..8e3f85f +--- /dev/null ++++ b/compat/corecrypto/ccsha1.h +@@ -0,0 +1,9 @@ ++// SPDX-License-Identifier: APSL-2.0 ++// CoreCrypto compatibility shims written by Randy Eckenrode © 2024 ++ ++#pragma once ++ ++#include ++ ++ ++EXTERN_C const struct ccdigest_info* ccsha1_di(void); +diff --git a/compat/corecrypto/ccsha2.c b/compat/corecrypto/ccsha2.c +new file mode 100644 +index 0000000..6504503 +--- /dev/null ++++ b/compat/corecrypto/ccsha2.c +@@ -0,0 +1,22 @@ ++// SPDX-License-Identifier: APSL-2.0 ++// CoreCrypto compatibility shims written by Randy Eckenrode © 2024 ++ ++#include "ccsha2.h" ++ ++#include ++ ++#include ++ ++#include "ccdigest_private.h" ++ ++ ++static struct ccdigest_info* di = NULL; ++ ++const struct ccdigest_info* ccsha256_di(void) ++{ ++ if (!di) { ++ di = _ccdigest_newprovider("SHA-256"); ++ assert(EVP_MD_get_size(di->provider) == CS_SHA256_LEN); ++ } ++ return di; ++} +diff --git a/compat/corecrypto/ccsha2.h b/compat/corecrypto/ccsha2.h +new file mode 100644 +index 0000000..9f30e03 +--- /dev/null ++++ b/compat/corecrypto/ccsha2.h +@@ -0,0 +1,9 @@ ++// SPDX-License-Identifier: APSL-2.0 ++// CoreCrypto compatibility shims written by Randy Eckenrode © 2024 ++ ++#pragma once ++ ++#include ++ ++ ++EXTERN_C const struct ccdigest_info* ccsha256_di(void); +-- +2.45.1 + diff --git a/pkgs/by-name/ld/ld64/0008-Disable-searching-in-standard-library-locations.patch b/pkgs/by-name/ld/ld64/0008-Disable-searching-in-standard-library-locations.patch new file mode 100644 index 0000000000000..ddda588c6aafe --- /dev/null +++ b/pkgs/by-name/ld/ld64/0008-Disable-searching-in-standard-library-locations.patch @@ -0,0 +1,25 @@ +From 3e80d438e2a3ec50d666f2b6e32007c275d4a08a Mon Sep 17 00:00:00 2001 +From: Randy Eckenrode +Date: Thu, 11 Apr 2024 23:13:29 -0400 +Subject: [PATCH 8/8] Disable searching in standard library locations + +--- + src/ld/Options.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/ld/Options.cpp b/src/ld/Options.cpp +index 67a9f53..611b583 100644 +--- a/src/ld/Options.cpp ++++ b/src/ld/Options.cpp +@@ -4320,7 +4320,7 @@ bool Options::shouldUseBuildVersion(ld::Platform plat, uint32_t minOSvers) const + + void Options::buildSearchPaths(int argc, const char* argv[]) + { +- bool addStandardLibraryDirectories = true; ++ bool addStandardLibraryDirectories = false; + ld::Platform platform = ld::Platform::unknown; + std::vector libraryPaths; + std::vector frameworkPaths; +-- +2.45.1 + diff --git a/pkgs/by-name/ld/ld64/gen_compile_stubs.py b/pkgs/by-name/ld/ld64/gen_compile_stubs.py new file mode 100644 index 0000000000000..30fe30789a107 --- /dev/null +++ b/pkgs/by-name/ld/ld64/gen_compile_stubs.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python +import sys +from pathlib import Path + +byteseq = (str(int(x)) for x in Path(sys.argv[1]).read_bytes()) + +print("#pragma once") +print(f"static const char compile_stubs[] = {{ {', '.join(byteseq)} }};") diff --git a/pkgs/by-name/ld/ld64/meson.build b/pkgs/by-name/ld/ld64/meson.build new file mode 100644 index 0000000000000..0de64797c4aac --- /dev/null +++ b/pkgs/by-name/ld/ld64/meson.build @@ -0,0 +1,249 @@ +# Build settings based on the upstream Xcode project. +# See: https://github.com/apple-oss-distributions/ld64/blob/main/ld64.xcodeproj/project.pbxproj + +# Project settings +project( + 'ld64', + 'c', 'cpp', + version : '@version@', + default_options : {'cpp_std': 'c++20'}, +) + +fs = import('fs') + +# Options +target_prefix = get_option('target_prefix') + + +# Dependencies +cc = meson.get_compiler('c') +cxx = meson.get_compiler('cpp') +python = find_program('python3') + +libtapi = cxx.find_library('tapi') +openssl = dependency('openssl', version : '>=3.0') +xar = cc.find_library('xar') + + +# Feature tests + +# macOS 10.12 does not support `DISPATCH_APPLY_AUTO`. Fortunately, `DISPATCH_APPLY_CURRENT_ROOT_QUEUE` has the +# same value and was repurposed in subsequent releases as `DISPATCH_APPLY_AUTO`. +dispatch_apply_auto_test = ''' +#include +int main(int argc, char* argv[]) { + dispatch_queue_t queue = DISPATCH_APPLY_AUTO; + return 0; +} +''' +if not cc.compiles( + dispatch_apply_auto_test, + args : '-Wno-unused-command-line-argument', + name : 'supports DISPATCH_APPLY_AUTO', +) + add_project_arguments( + '-include', 'dispatch/private.h', + '-DDISPATCH_APPLY_AUTO=DISPATCH_APPLY_CURRENT_ROOT_QUEUE', + '-DPRIVATE', # The required API is private on the 10.12 SDK. + language: ['c', 'cpp'], + ) +endif + +# The return type of `dispatch_get_global_queue` was changed in 10.14. +# Use the older type if the SDK does not support it. +dispatch_queue_global_test = ''' +#include +int main(int argc, char* argv[]) { + dispatch_queue_global_t queue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0); + return 0; +} +''' +if not cc.compiles( + dispatch_queue_global_test, + args : '-Wno-unused-command-line-argument', + name : 'supports dispatch_queue_global_t', +) + add_project_arguments('-Ddispatch_queue_global_t=dispatch_queue_t', language : ['c', 'cpp']) +endif + + +# Generated files + +compile_stubs_h = custom_target( + 'compile_stubs.h', + capture : true, + command : [python, '@INPUT0@', '@INPUT1@'], + input : ['gen_compile_stubs.py', 'compile_stubs'], + output : ['compile_stubs.h'], +) + +configure_h = custom_target( + 'configure_h', + command : ['bash', '@INPUT@'], + env : { + 'DERIVED_FILE_DIR' : meson.current_build_dir(), + 'RC_ProjectSourceVersion': '@version@' + }, + input : ['src/create_configure'], + output : ['configure.h'], +) + +incdirs = include_directories( + 'compat', + 'include', + 'src/abstraction', + 'src/ld', + 'src/ld/code-sign-blobs', + 'src/ld/parsers', + 'src/ld/passes', + 'src/mach_o', +) + +# Dynamic libraries +libcodedirectory = library( + 'codedirectory', + dependencies : [openssl], + include_directories : incdirs, + install : true, + sources : [ + 'compat/corecrypto/ccdigest.c', + 'compat/corecrypto/ccsha1.c', + 'compat/corecrypto/ccsha2.c', + 'compat/libcodedirectory.c', + 'src/ld/libcodedirectory.c' + ], + soversion : 1, +) +install_headers( + 'src/ld/cs_blobs.h', + 'src/ld/libcodedirectory.h', +) + + +# Static libraries +libprunetrie = static_library( + 'prunetrie', + include_directories : incdirs, + install : true, + override_options : {'b_lto': false}, + sources : [ + 'src/mach_o/Error.cpp', + 'src/mach_o/ExportsTrie.cpp', + 'src/other/PruneTrie.cpp', + ], +) +install_headers( + 'src/other/prune_trie.h', + subdir : 'mach-o', +) + + +# Binaries +ld64 = executable( + f'@target_prefix@ld', + dependencies : [libtapi, openssl, xar], + include_directories : incdirs, + install : true, + # These linker flags mirror those used in a release build of the Xcode project. + # See: https://github.com/apple-oss-distributions/ld64/blob/47f477cb721755419018f7530038b272e9d0cdea/ld64.xcodeproj/project.pbxproj#L1292-L1299. + link_args : [ + '-Wl,-exported_symbol,__mh_execute_header', + '-Wl,-stack_size,0x02000000', + '-Wl,-client_name,ld', + ], + link_with : [libcodedirectory], + sources : [ + compile_stubs_h, + configure_h, + 'compat/CommonCrypto/CommonDigestSPI.c', + 'compat/corecrypto/ccdigest.c', + 'compat/corecrypto/ccsha1.c', + 'compat/corecrypto/ccsha2.c', + 'src/ld/FatFile.cpp', + 'src/ld/InputFiles.cpp', + 'src/ld/Mangling.cpp', + 'src/ld/Options.cpp', + 'src/ld/OutputFile.cpp', + 'src/ld/PlatformSupport.cpp', + 'src/ld/Resolver.cpp', + 'src/ld/ResponseFiles.cpp', + 'src/ld/Snapshot.cpp', + 'src/ld/SymbolTable.cpp', + 'src/ld/code-sign-blobs/blob.cpp', + 'src/ld/code-sign-blobs/blob.h', + 'src/ld/debugline.c', + 'src/ld/ld.cpp', + 'src/ld/parsers/archive_file.cpp', + 'src/ld/parsers/generic_dylib_file.cpp', + 'src/ld/parsers/lto_file.cpp', + 'src/ld/parsers/macho_dylib_file.cpp', + 'src/ld/parsers/macho_relocatable_file.cpp', + 'src/ld/parsers/opaque_section_file.cpp', + 'src/ld/parsers/textstub_dylib_file.cpp', + 'src/ld/passes/bitcode_bundle.cpp', + 'src/ld/passes/branch_island.cpp', + 'src/ld/passes/branch_shim.cpp', + 'src/ld/passes/code_dedup.cpp', + 'src/ld/passes/compact_unwind.cpp', + 'src/ld/passes/dtrace_dof.cpp', + 'src/ld/passes/dylibs.cpp', + 'src/ld/passes/got.cpp', + 'src/ld/passes/huge.cpp', + 'src/ld/passes/inits.cpp', + 'src/ld/passes/objc.cpp', + 'src/ld/passes/objc_constants.cpp', + 'src/ld/passes/objc_stubs.cpp', + 'src/ld/passes/order.cpp', + 'src/ld/passes/stubs/stubs.cpp', + 'src/ld/passes/thread_starts.cpp', + 'src/ld/passes/tlvp.cpp', + 'src/mach_o/Error.cpp', + 'src/mach_o/ExportsTrie.cpp', + ], +) +install_man('doc/man/man1/ld-classic.1') + +# Extra tools +unwinddump = executable( + f'@target_prefix@unwinddump', + include_directories : incdirs, + install : true, + sources : [ + configure_h, + 'src/other/UnwindDump.cpp', + ], +) +install_man('doc/man/man1/unwinddump.1') + +machocheck = executable( + f'@target_prefix@machocheck', + include_directories : incdirs, + install : true, + sources : [ + configure_h, + 'src/other/machochecker.cpp', + ], +) + +objectdump = executable( + f'@target_prefix@ObjectDump', + include_directories : incdirs, + install : true, + sources : [ + configure_h, + 'src/ld/PlatformSupport.cpp', + 'src/ld/debugline.c', + 'src/ld/parsers/macho_relocatable_file.cpp', + 'src/other/ObjectDump.cpp', + ], +) + +objcimageinfo = executable( + f'@target_prefix@objcimageinfo', + include_directories : incdirs, + install : true, + sources : [ + configure_h, + 'src/other/objcimageinfo.cpp', + ], +) diff --git a/pkgs/by-name/ld/ld64/meson.options b/pkgs/by-name/ld/ld64/meson.options new file mode 100644 index 0000000000000..2417b81f0401e --- /dev/null +++ b/pkgs/by-name/ld/ld64/meson.options @@ -0,0 +1,6 @@ +option( + 'target_prefix', + type : 'string', + value : '', + description: 'Specifies the prefix to use when building for cross-compilation (e.g., `aarch64-apple-darwin`)' +) diff --git a/pkgs/by-name/ld/ld64/package.nix b/pkgs/by-name/ld/ld64/package.nix new file mode 100644 index 0000000000000..ee773bacf3a5b --- /dev/null +++ b/pkgs/by-name/ld/ld64/package.nix @@ -0,0 +1,202 @@ +{ + 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 ' '#include ' + ''; + + strictDeps = true; + + nativeBuildInputs = [ + meson + ninja + openssl + pkg-config + python3 + ]; + + buildInputs = [ + libtapi + llvm + libunwind + openssl + xar + ] ++ lib.optionals stdenv.isDarwin [ darwin.dyld ] ++ lib.optionals stdenv.isLinux [ libdispatch ]; + + # 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 + + 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. + }; +}) diff --git a/pkgs/by-name/li/libtapi/0001-Check-for-no_exported_symbols-linker-support.patch b/pkgs/by-name/li/libtapi/0001-Check-for-no_exported_symbols-linker-support.patch new file mode 100644 index 0000000000000..1a1c77e6ce9ec --- /dev/null +++ b/pkgs/by-name/li/libtapi/0001-Check-for-no_exported_symbols-linker-support.patch @@ -0,0 +1,37 @@ +From e954aacbc075355419f5fc99db61f68aca1fcfe4 Mon Sep 17 00:00:00 2001 +From: Randy Eckenrode +Date: Fri, 5 Apr 2024 14:16:40 -0400 +Subject: [PATCH 1/3] Check for -no_exported_symbols linker support + +--- + CMakeLists.txt | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/tapi/CMakeLists.txt b/tapi/CMakeLists.txt +index 62affdf..82426de 100644 +--- a/tapi/CMakeLists.txt ++++ b/tapi/CMakeLists.txt +@@ -73,6 +73,9 @@ llvm_check_linker_flag(CXX "-Wl,-no_inits" LINKER_SUPPORTS_NO_INITS) + llvm_check_linker_flag(CXX "-Wl,-iosmac_version_min,13.0" LINKER_SUPPORTS_IOSMAC) + # MARZIPAN RENAME + ++# Older versions of ld64 (e.g., in the Darwin bootstrap) do not support this flag. ++llvm_check_linker_flag(CXX "-Wl,-no_exported_symbols" LINKER_SUPPORTS_NO_EXPORTED_SYMBOLS) ++ + # Check if i386 is supported. + SET(CMAKE_OLD_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + SET(CMAKE_OLD_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) +@@ -160,7 +163,9 @@ endmacro(add_tapi_library) + macro(add_tapi_executable name) + add_llvm_executable(${name} ${ARGN}) + set_target_properties(${name} PROPERTIES FOLDER "Tapi executables") +- target_link_options(${name} PRIVATE "-Wl,-no_exported_symbols") ++ if(LINKER_SUPPORTS_NO_EXPORTED_SYMBOLS) ++ target_link_options(${name} PRIVATE "-Wl,-no_exported_symbols") ++ endif() + endmacro(add_tapi_executable) + + function(tapi_clang_tablegen) +-- +2.42.0 + diff --git a/pkgs/by-name/li/libtapi/0002-Pass-fileType-to-writeToStream.patch b/pkgs/by-name/li/libtapi/0002-Pass-fileType-to-writeToStream.patch new file mode 100644 index 0000000000000..ffcedb0c6f6e1 --- /dev/null +++ b/pkgs/by-name/li/libtapi/0002-Pass-fileType-to-writeToStream.patch @@ -0,0 +1,25 @@ +From 77ca537cfc61765f2109c626757f2da8de602ce0 Mon Sep 17 00:00:00 2001 +From: Randy Eckenrode +Date: Fri, 5 Apr 2024 23:20:32 -0400 +Subject: [PATCH 2/3] Pass fileType to writeToStream + +--- + lib/Core/JSONReaderWriter.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tapi/lib/Core/JSONReaderWriter.cpp b/tapi/lib/Core/JSONReaderWriter.cpp +index c040670..c1be85f 100644 +--- a/tapi/lib/Core/JSONReaderWriter.cpp ++++ b/tapi/lib/Core/JSONReaderWriter.cpp +@@ -57,7 +57,7 @@ Error JSONWriter::writeFile(raw_ostream &os, const InterfaceFile *file, + if (file == nullptr) + return errorCodeToError(std::make_error_code(std::errc::invalid_argument)); + +- return TextAPIWriter::writeToStream(os, *file, /*Compact=*/false); ++ return TextAPIWriter::writeToStream(os, *file, fileType, /*Compact=*/false); + } + + TAPI_NAMESPACE_INTERNAL_END +-- +2.42.0 + diff --git a/pkgs/by-name/li/libtapi/0003-Match-designator-order-with-declaration-order.patch b/pkgs/by-name/li/libtapi/0003-Match-designator-order-with-declaration-order.patch new file mode 100644 index 0000000000000..2883af0a52289 --- /dev/null +++ b/pkgs/by-name/li/libtapi/0003-Match-designator-order-with-declaration-order.patch @@ -0,0 +1,28 @@ +From b69038edb2e0ace9128407ab3ee7bc1001ffd751 Mon Sep 17 00:00:00 2001 +From: Randy Eckenrode +Date: Sun, 7 Apr 2024 19:23:24 -0400 +Subject: [PATCH 3/3] Match designator order with declaration order + +--- + lib/Core/Demangler.cpp | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tapi/lib/Core/Demangler.cpp b/tapi/lib/Core/Demangler.cpp +index d85899a..f5c485a 100644 +--- a/tapi/lib/Core/Demangler.cpp ++++ b/tapi/lib/Core/Demangler.cpp +@@ -30,9 +30,10 @@ bool Demangler::isItaniumEncoding(StringRef mangledName) { + return mangledName.startswith("_Z") || mangledName.startswith("___Z"); + } + ++ + DemangledName Demangler::demangle(StringRef mangledName) { + DemangledName result{ +- .str = mangledName.str(), .isSwift = false, .isItanium = false}; ++ .str = mangledName.str(), .isItanium = false, .isSwift = false}; + char *demangled = nullptr; + + if (isItaniumEncoding(mangledName)) { +-- +2.42.0 + diff --git a/pkgs/by-name/li/libtapi/package.nix b/pkgs/by-name/li/libtapi/package.nix new file mode 100644 index 0000000000000..b11de1756c90a --- /dev/null +++ b/pkgs/by-name/li/libtapi/package.nix @@ -0,0 +1,184 @@ +{ + lib, + stdenv, + fetchFromGitHub, + fetchpatch, + cmake, + ninja, + python3, + zlib, +}: + +let + # libtapi is only supported building against Apple’s LLVM fork pinned to a specific revision. + # It can’t be built against upstream LLVM because it uses APIs that are specific to Apple’s fork. + # See: https://github.com/apple-oss-distributions/tapi/blob/main/Readme.md + + # Apple’s LLVM fork uses its own versioning scheme. + # See: https://en.wikipedia.org/wiki/Xcode#Toolchain_versions + # Note: Can’t use a sparse checkout because the Darwin stdenv bootstrap can’t depend on fetchgit. + appleLlvm = { + version = "15.0.0"; # As reported by upstream’s `tapi --version`. + rev = "2b5ff47e44b059c03de5779479d01a133ab4d581"; # Per the TAPI repo. + hash = "sha256-X37zBbpSEWmqtdTXsd1t++gp+0ggA8YtB73fGKNaiR0="; + }; +in +stdenv.mkDerivation (finalAttrs: { + pname = "libtapi"; + version = "1500.0.12.3"; + + outputs = [ + "out" + "bin" + "dev" + ]; + + srcs = [ + (fetchFromGitHub { + name = "tapi-src"; + owner = "apple-oss-distributions"; + repo = "tapi"; + rev = "tapi-${finalAttrs.version}"; + hash = "sha256-YeaA2OeSY1fXYJHPJJ0TrVC1brspSvutBtPMPGX6Y1o="; + }) + # libtapi can’t avoid pulling the whole repo even though it needs only a couple of folders because + # `fetchgit` can’t be used in the Darwin bootstrap. + (fetchFromGitHub { + name = "apple-llvm-src"; + owner = "apple"; + repo = "llvm-project"; + inherit (appleLlvm) rev hash; + }) + ]; + + patches = [ + # Older versions of ld64 may not support `-no_exported_symbols`, so use it only + # when the linker supports it. + # Note: This can be dropped once the bootstrap tools are updated after the ld64 update. + ./0001-Check-for-no_exported_symbols-linker-support.patch + # The recommended upstream revision of Apple’s LLVM fork needs this patch, or + # `tapi stubify` will crash when generating stubs. + (fetchpatch { + url = "https://github.com/apple/llvm-project/commit/455bf3d1ccd6a52df5e38103532c1b8f49924edc.patch"; + hash = "sha256-ujZcfdAls20JPIvjvO2Xv8st8cNTY/XTEQusICKBKSA"; + }) + # Updates `JSONReaderWriter` to work with the API change in the above patch. + ./0002-Pass-fileType-to-writeToStream.patch + # Fix build on Linux. GCC is more picky than clang about the field order. + ./0003-Match-designator-order-with-declaration-order.patch + ]; + + postPatch = + '' + # Enable building on non-Darwin platforms + substituteInPlace tapi/CMakeLists.txt \ + --replace-fail 'message(FATAL_ERROR "Unsupported configuration.")' "" + + # Remove the client limitation on linking to libtapi.dylib. + substituteInPlace tapi/tools/libtapi/CMakeLists.txt \ + --replace-fail '-allowable_client ld' "" + # Replace hard-coded installation paths with standard ones. + declare -A installdirs=( + [bin]=BINDIR + [include]=INCLUDEDIR + [lib]=LIBDIR + [local/bin]=BINDIR + [local/share/man]=MANDIR + [share/man]=MANDIR + ) + for dir in "''${!installdirs[@]}"; do + cmakevar=CMAKE_INSTALL_''${installdirs[$dir]} + for cmakelist in $(grep -rl "DESTINATION $dir" tapi); do + substituteInPlace "$cmakelist" \ + --replace-fail "DESTINATION $dir" "DESTINATION \''${$cmakevar}" + done + done + # Doesn’t seem to exist publically. + substituteInPlace tapi/test/CMakeLists.txt \ + --replace-fail tapi-configs "" + '' + + lib.optionalString stdenv.isLinux '' + # Remove Darwin-specific versioning flags. + substituteInPlace tapi/tools/libtapi/CMakeLists.txt \ + --replace-fail '-current_version ''${DYLIB_VERSION} -compatibility_version 1' "" + ''; + + preUnpack = '' + mkdir source + ''; + + sourceRoot = "source"; + + postUnpack = '' + chmod -R u+w apple-llvm-src tapi-src + mv apple-llvm-src/{clang,cmake,llvm,utils} source + mv tapi-src source/tapi + ''; + + strictDeps = true; + + buildInputs = [ zlib ]; # Upstream links against zlib in their distribution. + + nativeBuildInputs = [ + cmake + ninja + python3 + ]; + + cmakeDir = "../llvm"; + + cmakeFlags = [ + (lib.cmakeFeature "LLVM_ENABLE_PROJECTS" "clang;tapi") + (lib.cmakeFeature "LLVM_EXTERNAL_PROJECTS" "tapi") + (lib.cmakeBool "TAPI_INCLUDE_DOCS" true) + # Matches the version string format reported by upstream `tapi`. + (lib.cmakeFeature "TAPI_REPOSITORY_STRING" "tapi-${finalAttrs.version}") + (lib.cmakeFeature "TAPI_FULL_VERSION" appleLlvm.version) + # Match the versioning used by Apple’s LLVM fork (primarily used for .so versioning). + (lib.cmakeFeature "LLVM_VERSION_MAJOR" (lib.versions.major appleLlvm.version)) + (lib.cmakeFeature "LLVM_VERSION_MINOR" (lib.versions.minor appleLlvm.version)) + (lib.cmakeFeature "LLVM_VERSION_PATCH" (lib.versions.patch appleLlvm.version)) + (lib.cmakeFeature "LLVM_VERSION_SUFFIX" "") + # Upstream `tapi` does not link against ncurses. Disable it explicitly to make sure + # it is not detected incorrectly from the bootstrap tools tarball. + (lib.cmakeBool "LLVM_ENABLE_TERMINFO" false) + # Disabling the benchmarks avoids a failure during the configure phase because + # the sparse checkout does not include the benchmarks. + (lib.cmakeBool "LLVM_INCLUDE_BENCHMARKS" false) + # tapi’s tests expect to target macOS 13.0 and build both x86_64 and universal + # binaries regardless of the host platform. + (lib.cmakeBool "LLVM_INCLUDE_TESTS" false) + (lib.cmakeBool "TAPI_INCLUDE_TESTS" false) + ]; + + ninjaFlags = [ + "libtapi" + "tapi-sdkdb" + "tapi" + ]; + + installTargets = [ + "install-libtapi" + "install-tapi-docs" + "install-tapi-headers" + "install-tapi-sdkdb" + "install-tapi" + ]; + + postInstall = '' + # The man page is installed for these, but they’re not included in the source release. + rm $bin/share/man/man1/tapi-analyze.1 $bin/share/man/man1/tapi-api-verify.1 + ''; + + meta = { + description = "Replaces the Mach-O Dynamic Library Stub files in Apple's SDKs to reduce the size"; + homepage = "https://github.com/apple-oss-distributions/tapi/"; + license = lib.licenses.ncsa; + mainProgram = "tapi"; + maintainers = with lib.maintainers; [ + matthewbauer + reckenrode + ]; + platforms = lib.platforms.unix; + }; +}) diff --git a/pkgs/development/compilers/dotnet/vmr.nix b/pkgs/development/compilers/dotnet/vmr.nix index 306dab376e062..197b0e1727a20 100644 --- a/pkgs/development/compilers/dotnet/vmr.nix +++ b/pkgs/development/compilers/dotnet/vmr.nix @@ -41,7 +41,6 @@ let isDarwin buildPlatform targetPlatform; - inherit (darwin) cctools-llvm; inherit (swiftPackages) apple_sdk swift; releaseManifest = lib.importJSON releaseManifestFile; @@ -53,16 +52,6 @@ let sigtool = callPackage ./sigtool.nix {}; - # we need dwarfdump from cctools, but can't have e.g. 'ar' overriding stdenv - dwarfdump = stdenvNoCC.mkDerivation { - name = "dwarfdump-wrapper"; - dontUnpack = true; - installPhase = '' - mkdir -p "$out/bin" - ln -s "${cctools-llvm}/bin/dwarfdump" "$out/bin" - ''; - }; - _icu = if isDarwin then darwin.ICU else icu; in stdenv.mkDerivation rec { @@ -118,7 +107,6 @@ in stdenv.mkDerivation rec { buildInputs = old.buildInputs ++ old.propagatedBuildInputs; propagatedBuildInputs = []; })) - dwarfdump sigtool Foundation CoreFoundation diff --git a/pkgs/development/compilers/ghc/8.10.7.nix b/pkgs/development/compilers/ghc/8.10.7.nix index a0ba35619a47c..a6694e2e99c9c 100644 --- a/pkgs/development/compilers/ghc/8.10.7.nix +++ b/pkgs/development/compilers/ghc/8.10.7.nix @@ -157,18 +157,16 @@ let otool = cc.bintools.bintools; - # GHC needs install_name_tool on all darwin platforms. On aarch64-darwin it is - # part of the bintools wrapper (due to codesigning requirements), but not on - # x86_64-darwin. We decide based on target platform to have consistent tools - # across all GHC stages. - install_name_tool = - if stdenv.targetPlatform.isAarch64 - then cc.bintools - else cc.bintools.bintools; - # Same goes for strip. + # GHC needs install_name_tool on all darwin platforms. The same one can + # be used on both platforms. It is safe to use with linker-generated + # signatures because it will update the signatures automatically after + # modifying the target binary. + install_name_tool = cc.bintools.bintools; + + # strip on darwin is wrapped to enable deterministic mode. strip = # TODO(@sternenseemann): also use wrapper if linker == "bfd" or "gold" - if stdenv.targetPlatform.isAarch64 && stdenv.targetPlatform.isDarwin + if stdenv.targetPlatform.isDarwin then cc.bintools else cc.bintools.bintools; }.${name}; diff --git a/pkgs/development/compilers/ghc/common-hadrian.nix b/pkgs/development/compilers/ghc/common-hadrian.nix index 5a9be57e613cd..b6d4d7236fe6b 100644 --- a/pkgs/development/compilers/ghc/common-hadrian.nix +++ b/pkgs/development/compilers/ghc/common-hadrian.nix @@ -288,18 +288,16 @@ let otool = cc.bintools.bintools; - # GHC needs install_name_tool on all darwin platforms. On aarch64-darwin it is - # part of the bintools wrapper (due to codesigning requirements), but not on - # x86_64-darwin. We decide based on target platform to have consistent tools - # across all GHC stages. - install_name_tool = - if stdenv.targetPlatform.isAarch64 - then cc.bintools - else cc.bintools.bintools; - # Same goes for strip. + # GHC needs install_name_tool on all darwin platforms. The same one can + # be used on both platforms. It is safe to use with linker-generated + # signatures because it will update the signatures automatically after + # modifying the target binary. + install_name_tool = cc.bintools.bintools; + + # strip on darwin is wrapped to enable deterministic mode. strip = # TODO(@sternenseemann): also use wrapper if linker == "bfd" or "gold" - if stdenv.targetPlatform.isAarch64 && stdenv.targetPlatform.isDarwin + if stdenv.targetPlatform.isDarwin then cc.bintools else cc.bintools.bintools; }.${name}; diff --git a/pkgs/development/compilers/ghc/common-make-native-bignum.nix b/pkgs/development/compilers/ghc/common-make-native-bignum.nix index 79fced444f562..2b23cd75a0ed7 100644 --- a/pkgs/development/compilers/ghc/common-make-native-bignum.nix +++ b/pkgs/development/compilers/ghc/common-make-native-bignum.nix @@ -157,18 +157,16 @@ let otool = cc.bintools.bintools; - # GHC needs install_name_tool on all darwin platforms. On aarch64-darwin it is - # part of the bintools wrapper (due to codesigning requirements), but not on - # x86_64-darwin. We decide based on target platform to have consistent tools - # across all GHC stages. - install_name_tool = - if stdenv.targetPlatform.isAarch64 - then cc.bintools - else cc.bintools.bintools; - # Same goes for strip. + # GHC needs install_name_tool on all darwin platforms. The same one can + # be used on both platforms. It is safe to use with linker-generated + # signatures because it will update the signatures automatically after + # modifying the target binary. + install_name_tool = cc.bintools.bintools; + + # strip on darwin is wrapped to enable deterministic mode. strip = # TODO(@sternenseemann): also use wrapper if linker == "bfd" or "gold" - if stdenv.targetPlatform.isAarch64 && stdenv.targetPlatform.isDarwin + if stdenv.targetPlatform.isDarwin then cc.bintools else cc.bintools.bintools; }.${name}; diff --git a/pkgs/development/tools/misc/binutils/default.nix b/pkgs/development/tools/misc/binutils/default.nix index 308ac9d5913fb..610f04fd35a53 100644 --- a/pkgs/development/tools/misc/binutils/default.nix +++ b/pkgs/development/tools/misc/binutils/default.nix @@ -58,10 +58,7 @@ stdenv.mkDerivation (finalAttrs: { pname = targetPrefix + "binutils"; inherit version; - # HACK: Ensure that we preserve source from bootstrap binutils to not rebuild LLVM - src = stdenv.__bootPackages.binutils-unwrapped.src - or srcs.${targetPlatform.system} - or srcs.normal; + src = srcs.${targetPlatform.system} or srcs.normal; # WARN: this package is used for bootstrapping fetchurl, and thus cannot use # fetchpatch! All mutable patches (generated by GitHub or cgit) that are diff --git a/pkgs/os-specific/darwin/apple-sdk/default.nix b/pkgs/os-specific/darwin/apple-sdk/default.nix index 7298eba6c50aa..30081c8243784 100644 --- a/pkgs/os-specific/darwin/apple-sdk/default.nix +++ b/pkgs/os-specific/darwin/apple-sdk/default.nix @@ -363,7 +363,7 @@ in rec { objc4 = pkgs.darwin.libobjc; - sdkRoot = pkgs.callPackage ./sdkRoot.nix { sdkVersion = "10.12"; }; + sdkRoot = pkgs.callPackage ./sdkRoot.nix { sdkVersion = "10.12.4"; }; inherit (pkgs.darwin) Libsystem; diff --git a/pkgs/os-specific/darwin/apple-source-releases/AvailabilityVersions/0001-Support-setting-an-upper-bound-on-versions.patch b/pkgs/os-specific/darwin/apple-source-releases/AvailabilityVersions/0001-Support-setting-an-upper-bound-on-versions.patch new file mode 100644 index 0000000000000..6dcf8eef36196 --- /dev/null +++ b/pkgs/os-specific/darwin/apple-source-releases/AvailabilityVersions/0001-Support-setting-an-upper-bound-on-versions.patch @@ -0,0 +1,244 @@ +From dd3a2378cca465ec783fd792158b2fc11f83722c Mon Sep 17 00:00:00 2001 +From: Randy Eckenrode +Date: Tue, 2 Jul 2024 20:04:56 -0400 +Subject: [PATCH] Support setting an upper bound on versions + +--- + availability | 94 ++++++++++++++++++++++++++++++++++------------------ + 1 file changed, 61 insertions(+), 33 deletions(-) + +diff --git a/availability b/availability +index 8ebd250..5bb9edb 100755 +--- a/availability ++++ b/availability +@@ -17,12 +17,34 @@ MIN_PYTHON = (3, 7) #Required for ordered dictionaries as default + if sys.version_info < MIN_PYTHON: + sys.exit("Python %s.%s or later is required.\n" % MIN_PYTHON) + ++ ++def parse_version(ver): ++ if hasattr(ver, "string"): ++ ver = ver.string() ++ ++ return (tuple(map(int, ver.split("."))) + (0, 0))[:3] ++ ++ ++def version_older_or_equal(lhs, rhs): ++ if not rhs: ++ return True ++ ++ lhs_major, lhs_minor, lhs_patch = parse_version(lhs) ++ rhs_major, rhs_minor, rhs_patch = parse_version(rhs) ++ ++ return ( ++ lhs_major < rhs_major ++ or (lhs_major == rhs_major and lhs_minor < rhs_minor) ++ or (lhs_major == rhs_major and lhs_minor == rhs_minor and lhs_patch <= rhs_patch) ++ ) ++ ++ + # The build script will embed the DSL content here, otherwise we build it at runtime + dslContent = None + # @@INSERT_DSL_CONTENT()@@ + + class VersionSetDSL: +- def __init__(self, data): self.parsedDSL = self.Parser(data) ++ def __init__(self, data, threshold): self.parsedDSL = self.Parser(data, threshold) + def sets(self): return self.parsedDSL.version_sets + def platforms(self): return self.parsedDSL.platforms + +@@ -104,12 +126,15 @@ class VersionSetDSL: + self.availability_deprecation_define_name = optionals["availability_deprecation_define_name"] + if "version_define_name" in optionals: + self.availability_define_prefix = f"__{optionals['version_define_name']}_" +- def add_version(self, version): return self.versions.append(version); ++ def add_version(self, version, threshold): ++ if version_older_or_equal(version, threshold): ++ self.versions.append(version) + def add_variant(self, variant): return self.variants.append(variant); + class Parser: + platforms = {} + version_sets = [] +- def __init__(self, data): ++ def __init__(self, data, threshold): ++ self.threshold = threshold + for line in data.splitlines(): + line = line.strip().split('#',1)[0] + if not line: +@@ -129,7 +154,7 @@ class VersionSetDSL: + def set(self, name, version, uversion): + platforms = {} + for (platformName, platform) in self.platforms.items(): +- if platform.versioned: ++ if platform.versioned and platform.versions: + platforms[platformName] = platform.versions[-1] + version_set = {} + version_set["name"] = name +@@ -138,7 +163,7 @@ class VersionSetDSL: + self.version_sets.append(version_set) + # TODO add error checking for version decrease + def version(self, platform, version): +- if platform in self.platforms: self.platforms[platform].add_version(VersionSetDSL.Version(version)) ++ if platform in self.platforms: self.platforms[platform].add_version(VersionSetDSL.Version(version), self.threshold) + else: + print(f"Unknown platform \"{platform}\"") + exit(-1) +@@ -165,9 +190,8 @@ if not dslContent: + parts = line.split() + if uversion and parts and parts[0] == "set" and parts[3] == uversion: + break +-versions = VersionSetDSL(dslContent) + +-def print_sets(): ++def print_sets(versions): + print("---") + for set in versions.sets(): + print(f'{set["name"]}:') +@@ -178,7 +202,8 @@ def print_versions(platform): + print(" ".join([version.string() for version in versions.platforms()[platform].versions])) + + class Preprocessor: +- def __init__(self, inputFile, outputFile): ++ def __init__(self, versions, inputFile, outputFile): ++ self.versions = versions + bufferedOutput = "" + with tempfile.NamedTemporaryFile('w') as tmp: + with open(inputFile, 'r') as input: +@@ -207,10 +232,10 @@ class Preprocessor: + output.write("\"\"\"\n") + def VERSION_MAP(self, output): + sets = [] +- for set in versions.sets(): ++ for set in self.versions.sets(): + set_string = ", ".join(sorted({".{} = {}".format(os,osVersion.hex()) for (os,osVersion) in set["platforms"].items()})) + sets.append("\t{{ .set = {}, {} }}".format(set["version"].hex(), set_string)) +- platform_string = "\n".join([" uint32_t {} = 0;".format(name) for name in versions.platforms().keys()]) ++ platform_string = "\n".join([" uint32_t {} = 0;".format(name) for name in self.versions.platforms().keys()]) + output.write(""" + #include + #include +@@ -229,16 +254,16 @@ static const std::array sVersionMap = {{{{ + }}; + """.format(platform_string, len(sets), ",\n".join(sets))) + def DYLD_HEADER_VERSIONS(self, output): +- for (name,platform) in versions.platforms().items(): ++ for (name,platform) in self.versions.platforms().items(): + for version in platform.versions: + output.write(f"#define {platform.dyld_version_define_name + version.symbol() : <48}{version.hex()}\n"); + output.write("\n") +- for set in versions.sets(): ++ for set in self.versions.sets(): + set_string = " / ".join(sorted({"{} {}".format(os,osVersion.string()) for(os,osVersion) in set["platforms"].items()})) + output.write("// dyld_{}_os_versions => {}\n".format(set["name"], set_string)) + output.write("#define dyld_{}_os_versions".format(set["name"]).ljust(56, ' ')) + output.write("({{ (dyld_build_version_t){{0xffffffff, {}}}; }})\n\n".format(set["version"].hex())) +- for (name,platform) in versions.platforms().items(): ++ for (name,platform) in self.versions.platforms().items(): + for version in platform.versions: + output.write("#define dyld_platform_version_{}_{}".format(platform.stylized_name, version.symbol()).ljust(56, ' ')) + output.write("({{ (dyld_build_version_t){{{}, {}{}}}; }})\n".format(platform.platform_define, platform.dyld_version_define_name, version.symbol())) +@@ -247,14 +272,14 @@ static const std::array sVersionMap = {{{{ + def ALIAS_VERSION_MACROS(self, output, platformString, newName, oldName, **optionals): + minVersion = literal_eval(optionals.get("minVersion", "0x00000000")) + maxVersion = literal_eval(optionals.get("maxVersion", "0xFFFFFFFF")) +- platform = versions.platforms()[platformString]; ++ platform = self.versions.platforms()[platformString]; + for version in platform.versions: + if literal_eval(version.hex()) < minVersion: continue + if literal_eval(version.hex()) >= maxVersion: continue + output.write(f'#define {newName + version.symbol() : <48} {oldName + version.symbol()}\n') + def AVAILABILITY_DEFINES(self, output): +- for platformString in versions.platforms(): +- platform = versions.platforms()[platformString]; ++ for platformString in self.versions.platforms(): ++ platform = self.versions.platforms()[platformString]; + if platform.bleached: + output.write(f"#ifndef __APPLE_BLEACH_SDK__\n") + output.write(f"#ifndef __API_TO_BE_DEPRECATED_{platform.availability_deprecation_define_name}\n") +@@ -268,16 +293,16 @@ static const std::array sVersionMap = {{{{ + output.write(f"#endif /* __APPLE_BLEACH_SDK__ */\n") + output.write(f"\n"); + def AVAILABILITY_VERSION_DEFINES(self, output): +- for platformString in versions.platforms(): +- short = platform = versions.platforms()[platformString].short_version_numbers +- platform = versions.platforms()[platformString]; ++ for platformString in self.versions.platforms(): ++ short = platform = self.versions.platforms()[platformString].short_version_numbers ++ platform = self.versions.platforms()[platformString]; + for version in platform.versions: + output.write(f"#define {platform.availability_define_prefix + version.symbol() : <48}{version.decimal(short)}\n") + output.write(f"/* {platform.availability_define_prefix}_NA is not defined to a value but is used as a token by macros to indicate that the API is unavailable */\n\n") + def AVAILABILITY_MIN_MAX_DEFINES(self, output): +- for platformString in versions.platforms(): +- platform = versions.platforms()[platformString]; +- if not platform.versioned: ++ for platformString in self.versions.platforms(): ++ platform = self.versions.platforms()[platformString]; ++ if not platform.versioned or not platform.versions: + continue + if platform.bleached: + output.write(f"#ifndef __APPLE_BLEACH_SDK__\n") +@@ -310,8 +335,8 @@ static const std::array sVersionMap = {{{{ + output.write(f" #define __API_UNAVAILABLE_PLATFORM_{displayName} {realName},unavailable\n") + output.write(f"#if defined(__has_feature) && defined(__has_attribute)\n") + output.write(f" #if __has_attribute(availability)\n") +- for platformString in versions.platforms(): +- platform = versions.platforms()[platformString]; ++ for platformString in self.versions.platforms(): ++ platform = self.versions.platforms()[platformString]; + if platform.bleached: + output.write(f"#ifndef __APPLE_BLEACH_SDK__\n") + writeDefines(platformString, platformString, platform.versioned) +@@ -326,9 +351,9 @@ static const std::array sVersionMap = {{{{ + output.write(f" #endif /* __has_attribute(availability) */\n") + output.write(f"#endif /* defined(__has_feature) && defined(__has_attribute) */\n") + def AVAILABILITY_MACRO_IMPL(self, output, prefix, dispatcher, **optionals): +- count = len(versions.platforms()) +- for platformString in versions.platforms(): +- platform = versions.platforms()[platformString] ++ count = len(self.versions.platforms()) ++ for platformString in self.versions.platforms(): ++ platform = self.versions.platforms()[platformString] + count = count + len(platform.variants) + platformList = [] + argList = [] +@@ -344,9 +369,9 @@ static const std::array sVersionMap = {{{{ + scoped_availablity = False + if "scoped_availablity" in optionals and optionals["scoped_availablity"] == "TRUE": + scoped_availablity=True +- count = len(versions.platforms()) +- for platformString in versions.platforms(): +- platform = versions.platforms()[platformString] ++ count = len(self.versions.platforms()) ++ for platformString in self.versions.platforms(): ++ platform = self.versions.platforms()[platformString] + count = count + len(platform.variants) + argList = ','.join([f'{macroName}{x}' for x in reversed(range(0, count))]) + if "argCount" in optionals: +@@ -358,8 +383,9 @@ static const std::array sVersionMap = {{{{ + output.write(f" #define {name}(...) {macroName}_GET_MACRO(__VA_ARGS__,{argList},0)(__VA_ARGS__)\n") + + parser = argparse.ArgumentParser() ++parser.add_argument("--threshold", default=False, help='Specifies the maximum version (inclusive) included in pre-processed headers') + group = parser.add_mutually_exclusive_group() +-for (name, platform) in versions.platforms().items(): ++for (name, platform) in VersionSetDSL(dslContent, threshold=None).platforms().items(): + group.add_argument("--{}".format(name), default=False, action='store_true', help="Prints all SDK versions defined for {}".format(name)) + for alias in platform.cmd_aliases: + group.add_argument("--{}".format(alias), dest=name, default=False, action='store_true', help="Alias for --{}".format(name)) +@@ -367,8 +393,10 @@ group.add_argument("--sets", default=False, actio + group.add_argument("--preprocess", nargs=2, help=argparse.SUPPRESS) + args = parser.parse_args() + +-if args.sets: print_sets(); +-elif args.preprocess: Preprocessor(args.preprocess[0], args.preprocess[1]); ++versions = VersionSetDSL(dslContent, threshold=args.threshold) ++ ++if args.sets: print_sets(versions); ++elif args.preprocess: Preprocessor(versions, args.preprocess[0], args.preprocess[1]); + else: + for platform in versions.platforms().keys(): + if getattr(args, platform, None): +-- +2.45.2 + diff --git a/pkgs/os-specific/darwin/apple-source-releases/AvailabilityVersions/default.nix b/pkgs/os-specific/darwin/apple-source-releases/AvailabilityVersions/default.nix new file mode 100644 index 0000000000000..c80dd6235e41a --- /dev/null +++ b/pkgs/os-specific/darwin/apple-source-releases/AvailabilityVersions/default.nix @@ -0,0 +1,99 @@ +{ + lib, + stdenvNoCC, + appleDerivation', + gnused, + python3, + unifdef, +}: + +appleDerivation' stdenvNoCC { + nativeBuildInputs = [ unifdef ]; + + patches = [ ./0001-Support-setting-an-upper-bound-on-versions.patch ]; + + buildPhase = '' + runHook preBuild + + declare -a unifdef_sources=( + os_availability.modulemap + os_availability_private.modulemap + AvailabilityPrivate.modulemap + ) + unifdef -x2 -UBUILD_FOR_DRIVERKIT -m $(for x in "''${unifdef_sources[@]}"; do echo templates/$x; done) + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir -p "$out/bin" "$out/libexec" "$out/share/availability" + + cp -r availability.dsl templates "$out/share/availability/" + + substitute availability "$out/libexec/availability" \ + --replace-fail '/usr/bin/env python3' '${lib.getBin python3}/bin/python3' \ + --replace-fail 'f"{os.path.abspath(os.path.dirname(sys.argv[0]))}/' "\"$out/share/availability/" + chmod a+x "$out/libexec/availability" + + cat <