nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{
2 lib,
3 stdenv,
4 fetchFromGitHub,
5 buildPackages,
6 ld64,
7 llvm,
8 meson,
9 ninja,
10 openssl,
11 xar,
12 gitUpdater,
13}:
14
15let
16 # The targetPrefix is prepended to binary names to allow multiple binuntils on the PATH to both be usable.
17 targetPrefix = lib.optionalString (
18 stdenv.targetPlatform != stdenv.hostPlatform
19 ) "${stdenv.targetPlatform.config}-";
20
21 # First version with all the required files
22 xnu = fetchFromGitHub {
23 name = "xnu-src";
24 owner = "apple-oss-distributions";
25 repo = "xnu";
26 rev = "xnu-7195.50.7.100.1";
27 hash = "sha256-uHmAOm6k9ZXWfyqHiDSpm+tZqUbERlr6rXSJ4xNACkM=";
28 };
29in
30stdenv.mkDerivation (finalAttrs: {
31 pname = "${targetPrefix}cctools";
32 version = "1010.6";
33
34 outputs = [
35 "out"
36 "dev"
37 "man"
38 "gas"
39 "libtool"
40 ];
41
42 src = fetchFromGitHub {
43 owner = "apple-oss-distributions";
44 repo = "cctools";
45 rev = "cctools-${finalAttrs.version}";
46 hash = "sha256-JiKCP6U+xxR4mk4TXWv/mEo9Idg+QQqUYmB/EeRksCE=";
47 };
48
49 xcodeHash = "sha256-5RBbGrz1UKV0wt2Uk7RIHdfgWH8sgw/jy7hfTVrtVuM=";
50
51 postUnpack = ''
52 unpackFile '${xnu}'
53
54 # Verify that the Xcode project has not changed unexpectedly.
55 hashType=$(echo $xcodeHash | cut -d- -f1)
56 expectedHash=$(echo $xcodeHash | cut -d- -f2)
57 hash=$(openssl "$hashType" -binary "$sourceRoot/cctools.xcodeproj/project.pbxproj" | base64)
58
59 if [ "$hash" != "$expectedHash" ]; then
60 echo 'error: hash mismatch in cctools.xcodeproj/project.pbxproj'
61 echo " specified: $xcodeHash"
62 echo " got: $hashType-$hash"
63 echo
64 echo 'Upstream Xcode project has changed. Update `meson.build` with any changes, then update `xcodeHash`.'
65 echo 'Use `nix-hash --flat --sri --type sha256 cctools.xcodeproj/project.pbxproj` to regenerate it.'
66 exit 1
67 fi
68 '';
69
70 patches = [
71 # Fix compile errors in redo_prebinding.c
72 ./0001-Fix-build-issues-with-misc-redo_prebinding.c.patch
73 # Use libcd_is_blob_a_linker_signature as defined in the libcodedirectory.h header
74 ./0002-Rely-on-libcd_is_blob_a_linker_signature.patch
75 # Use the nixpkgs clang’s path as the prefix.
76 ./0004-Use-nixpkgs-clang-with-the-assembler-driver.patch
77 # Make sure cctools can find ld64 in the store
78 ./0005-Find-ld64-in-the-store.patch
79 # `ranlib` is a symlink to `libtool`. Make sure its detection works when it is used in cross-compilation.
80 ./0006-Support-target-prefixes-in-ranlib-detection.patch
81 ];
82
83 postPatch = ''
84 substitute ${./meson.build} meson.build \
85 --subst-var version
86 cp ${./meson.options} meson.options
87
88 # Make sure as’s clang driver uses clang from nixpkgs and finds the drivers in the store.
89 substituteInPlace as/driver.c \
90 --subst-var-by clang-unwrapped '${lib.getBin buildPackages.clang.cc}' \
91 --subst-var-by gas '${placeholder "gas"}'
92
93 # Need to set the path to make sure cctools can find ld64 in the store.
94 substituteInPlace libstuff/execute.c \
95 --subst-var-by ld64_path '${lib.getBin ld64}/bin/ld'
96
97 # Set the target prefix for `ranlib`
98 substituteInPlace misc/libtool.c \
99 --subst-var-by targetPrefix '${targetPrefix}'
100
101 # Use libxar from nixpkgs
102 for cctool_src in misc/nm.c otool/print_bitcode.c; do
103 substituteInPlace $cctool_src \
104 --replace-fail 'makestr(prefix, "../lib/libxar.dylib", NULL)' '"${lib.getLib xar}/lib/libxar.dylib"' \
105 --replace-fail '/usr/lib/libxar.dylib' '${lib.getLib xar}/lib/libxar.dylib'
106 done
107
108 # Use libLTO.dylib from nixpkgs LLVM
109 substituteInPlace libstuff/llvm.c \
110 --replace-fail 'getenv("LIBLTO_PATH")' '"${lib.getLib llvm}/lib/libLTO.dylib"'
111
112 cp ../xnu-src/EXTERNAL_HEADERS/mach-o/fixup-chains.h include/mach-o/fixup-chains.h
113 '';
114
115 strictDeps = true;
116
117 nativeBuildInputs = [
118 meson
119 ninja
120 openssl
121 ];
122
123 buildInputs = [
124 ld64
125 llvm
126 ];
127
128 mesonBuildType = "release";
129
130 mesonFlags = [
131 (lib.mesonOption "b_ndebug" "if-release")
132 ]
133 ++ lib.optionals (targetPrefix != "") [ (lib.mesonOption "target_prefix" targetPrefix) ];
134
135 postInstall = ''
136 ln -s ${targetPrefix}libtool "$out/bin/${targetPrefix}ranlib"
137 ln -s nm-classic.1 "''${!outputMan}/share/man/man1/nm.1"
138 ln -s otool-classic.1 "''${!outputMan}/share/man/man1/otool.1"
139 ln -s size-classic.1 "''${!outputMan}/share/man/man1/size.1"
140
141 # Move GNU as to its own output to prevent it from being used accidentally.
142 moveToOutput bin/gas "$gas"
143 moveToOutput libexec "$gas"
144 for arch in arm i386 x86_64; do
145 mv "$gas/libexec/as/$arch/as-$arch" "$gas/libexec/as/$arch/as"
146 done
147
148 # Move libtool to its own output to allow packages to add it without pulling in all of cctools
149 moveToOutput bin/${targetPrefix}libtool "$libtool"
150 ln -s "$libtool/bin/${targetPrefix}libtool" "$out/bin/${targetPrefix}libtool"
151 '';
152
153 __structuredAttrs = true;
154
155 passthru = {
156 inherit targetPrefix;
157 updateScript = gitUpdater { rev-prefix = "cctools-"; };
158 };
159
160 meta = {
161 description = "Classic linker for Darwin";
162 homepage = "https://opensource.apple.com/releases/";
163 license = with lib.licenses; [
164 apple-psl20
165 gpl2 # GNU as
166 ];
167 teams = [ lib.teams.darwin ];
168 platforms = lib.platforms.darwin;
169 };
170})