about summary refs log tree commit diff
path: root/pkgs/by-name/cc/cctools/package.nix
blob: 2ab074def67401cdf3749bd7492ddcd78c02415f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
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;
  };
})