summary refs log tree commit diff
path: root/pkgs/os-specific/darwin/swift-corelibs/corefoundation.nix
blob: 560be0c31ab6159f35aa23bd09da38178ddfd48d (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
{ lib, stdenv, fetchFromGitHub, fetchurl, ninja, python3, curl, libxml2, objc4, ICU }:

let
  # 10.12 adds a new sysdir.h that our version of CF in the main derivation depends on, but
  # isn't available publicly, so instead we grab an older version of the same file that did
  # not use sysdir.h, but provided the same functionality. Luckily it's simple :) hack hack
  sysdir-free-system-directories = fetchurl {
    url    = "https://raw.githubusercontent.com/apple/swift-corelibs-foundation/9a5d8420f7793e63a8d5ec1ede516c4ebec939f0/CoreFoundation/Base.subproj/CFSystemDirectories.c";
    sha256 = "0krfyghj4f096arvvpf884ra5czqlmbrgf8yyc0b3avqmb613pcc";
  };
in

stdenv.mkDerivation {
  name = "swift-corefoundation";

  src = fetchFromGitHub {
    owner  = "apple";
    repo   = "swift-corelibs-foundation";
    rev    = "71aaba20e1450a82c516af1342fe23268e15de0a";
    sha256 = "17kpql0f27xxz4jjw84vpas5f5sn4vdqwv10g151rc3rswbwln1z";
  };

  nativeBuildInputs = [ ninja python3 ];
  buildInputs = [ curl libxml2 objc4 ICU ];

  postPatch = ''
    cd CoreFoundation

    cp ${sysdir-free-system-directories} Base.subproj/CFSystemDirectories.c

    # In order, since I can't comment individual lines:
    # 1. Disable dispatch support for now
    # 2. For the linker too
    # 3. Use the legit CoreFoundation.h, not the one telling you not to use it because of Swift
    substituteInPlace build.py \
      --replace "cf.CFLAGS += '-DDEPLOYMENT" '#' \
      --replace "cf.LDFLAGS += '-ldispatch" '#'

    # Fix sandbox impurities.
    substituteInPlace ../lib/script.py \
      --replace '/bin/cp' cp
    patchShebangs --build ../configure

    # Includes xpc for some initialization routine that they don't define anyway, so no harm here
    substituteInPlace PlugIn.subproj/CFBundlePriv.h \
      --replace '#if (TARGET_OS_MAC' '#if (0'

    # Why do we define __GNU__? Is that normal?
    substituteInPlace Base.subproj/CFAsmMacros.h \
      --replace '#if defined(__GNU__) ||' '#if 0 &&'

    # The MIN macro doesn't seem to be defined sensibly for us. Not sure if our stdenv or their bug
    substituteInPlace Base.subproj/CoreFoundation_Prefix.h \
      --replace '#if DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX' '#if 1'

    # Somehow our ICU doesn't have this, probably because it's too old (we'll update it soon when we update the rest of the SDK)
    substituteInPlace Locale.subproj/CFLocale.c \
      --replace '#if U_ICU_VERSION_MAJOR_NUM' '#if 0 //'
  '';

  BUILD_DIR = "./Build";
  CFLAGS = "-DINCLUDE_OBJC -I${libxml2.dev}/include/libxml2"; # They seem to assume we include objc in some places and not in others, make a PR; also not sure why but libxml2 include path isn't getting picked up from buildInputs

  # I'm guessing at the version here. https://github.com/apple/swift-corelibs-foundation/commit/df3ec55fe6c162d590a7653d89ad669c2b9716b1 imported "high sierra"
  # and this version is a version from there. No idea how accurate it is.
  LDFLAGS = "-current_version 1454.90.0 -compatibility_version 150.0.0 -init ___CFInitialize";

  configurePhase = ''
    ../configure release --sysroot UNUSED
  '';

  enableParallelBuilding = true;

  # FIXME: Workaround for intermittent build failures of CFRuntime.c.
  # Based on testing this issue seems to only occur with clang_7, so
  # please remove this when updating the default llvm versions to 8 or
  # later.
  buildPhase = lib.optionalString true ''
    for i in {1..512}; do
        if ninja -j $NIX_BUILD_CORES; then
            break
        fi

        echo >&2
        echo "[$i/512] retrying build, workaround for #66811" >&2
        echo "  With clang_7 the build of CFRuntime.c fails intermittently." >&2
        echo "  See https://github.com/NixOS/nixpkgs/issues/66811 for more details." >&2
        echo >&2
        continue
    done
  '';

  # TODO: their build system sorta kinda can do this, but it doesn't seem to work right now
  # Also, this includes a bunch of private headers in the framework, which is not what we want
  installPhase = ''
    base="$out/Library/Frameworks/CoreFoundation.framework"
    mkdir -p $base/Versions/A/{Headers,PrivateHeaders,Modules}

    cp ./Build/CoreFoundation/libCoreFoundation.dylib $base/Versions/A/CoreFoundation

    # Note that this could easily live in the ldflags above as `-install_name @rpath/...` but
    # https://github.com/NixOS/nixpkgs/issues/46434 thwarts that, so for now I'm hacking it up
    # after the fact.
    install_name_tool -id '@rpath/CoreFoundation.framework/Versions/A/CoreFoundation' $base/Versions/A/CoreFoundation

    cp ./Build/CoreFoundation/usr/include/CoreFoundation/*.h $base/Versions/A/Headers
    cp ./Build/CoreFoundation/usr/include/CoreFoundation/module.modulemap $base/Versions/A/Modules

    ln -s A $base/Versions/Current

    for i in CoreFoundation Headers Modules; do
      ln -s Versions/Current/$i $base/$i
    done
  '';
}