about summary refs log tree commit diff
path: root/pkgs/development/tools/xcbuild/wrapper.nix
blob: 35eddd40f859ad6a378154dfab7e50b0fa210636 (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
{ lib, stdenv, makeWrapper, writeText, writeTextFile, runCommand, callPackage
, CoreServices, ImageIO, CoreGraphics
, xcodePlatform ? stdenv.targetPlatform.xcodePlatform or "MacOSX"
, xcodeVer ? stdenv.targetPlatform.xcodeVer or "9.4.1"
, sdkVer ? stdenv.targetPlatform.darwinSdkVersion or "10.12" }:

let

  toolchainName = "com.apple.dt.toolchain.XcodeDefault";
  sdkName = "${xcodePlatform}${sdkVer}";
  xcrunSdkName = lib.toLower xcodePlatform;

  # TODO: expose MACOSX_DEPLOYMENT_TARGET in nix so we can use it here.
  sdkBuildVersion = "17E189";
  xcodeSelectVersion = "2349";

  xcbuild = callPackage ./default.nix {
    inherit CoreServices ImageIO CoreGraphics stdenv;
  };

  toolchains = callPackage ./toolchains.nix {
    inherit toolchainName stdenv;
  };

  sdks = callPackage ./sdks.nix {
    inherit toolchainName sdkName xcodePlatform;
    version = sdkVer;
  };

  platforms = callPackage ./platforms.nix {
    inherit sdks xcodePlatform stdenv;
  };

  xcconfig = writeText "nix.xcconfig" ''
    SDKROOT=${sdkName}
  '';

  xcode-select = writeText "xcode-select" ''
#!${stdenv.shell}
while [ $# -gt 0 ]; do
   case "$1" in
         -h | --help) ;; # noop
         -s | --switch) shift;; # noop
         -r | --reset) ;; # noop
         -v | --version) echo xcode-select version ${xcodeSelectVersion} ;;
         -p | -print-path | --print-path) echo @DEVELOPER_DIR@ ;;
         --install) ;; # noop
    esac
    shift
done
  '';

  xcrun = writeTextFile {
    name = "xcrun";
    executable = true;
    destination = "/bin/xcrun";
    text = ''
#!${stdenv.shell}
args=( "$@" )

# If an SDK was requested, check that it matches.
for ((i = 0; i < ''${#args[@]}; i++)); do
  case "''${args[i]}" in
    --sdk | -sdk)
      i=$((i + 1))
      if [[ "''${args[i]}" != '${xcrunSdkName}' ]]; then
        echo >&2 "xcodebuild: error: SDK \"''${args[i]}\" cannot be located."
        exit 1
      fi
      ;;
  esac
done

while [ $# -gt 0 ]; do
   case "$1" in
         --sdk | -sdk) shift ;;
         --toolchain | -toolchain) shift ;;
         --find | -find | -f)
           shift
           command -v $1 || exit 1 ;;
         --log | -log) ;; # noop
         --verbose | -verbose) ;; # noop
         --no-cache | -no-cache) ;; # noop
         --kill-cache | -kill-cache) ;; # noop
         --show-sdk-path | -show-sdk-path)
           echo ${sdks}/${sdkName}.sdk ;;
         --show-sdk-platform-path | -show-sdk-platform-path)
           echo ${platforms}/${xcodePlatform}.platform ;;
         --show-sdk-version | -show-sdk-version)
           echo ${sdkVer} ;;
         --show-sdk-build-version | -show-sdk-build-version)
           echo ${sdkBuildVersion} ;;
         *) break ;;
    esac
    shift
done

if ! [[ -z "$@" ]]; then
   exec "$@"
fi
    '';
    checkPhase = ''
      ${stdenv.shellDryRun} "$target"
    '';
  };

in

runCommand "xcodebuild-${xcbuild.version}" {
  nativeBuildInputs = [ makeWrapper ];
  inherit (xcbuild) meta;

  # ensure that the toolchain goes in PATH
  propagatedBuildInputs = [ "${toolchains}/XcodeDefault.xctoolchain" ];

  passthru = {
    inherit xcbuild xcrun;
    toolchain = "${toolchains}/XcodeDefault.xctoolchain";
    sdk = "${sdks}/${sdkName}";
    platform = "${platforms}/${xcodePlatform}.platform";
  };

  preferLocalBuild = true;
} ''
  mkdir -p $out/bin

  ln -s $out $out/usr

  mkdir -p $out/Library/Xcode
  ln -s ${xcbuild}/Library/Xcode/Specifications $out/Library/Xcode/Specifications

  ln -s ${platforms} $out/Platforms
  ln -s ${toolchains} $out/Toolchains

  mkdir -p $out/Applications/Xcode.app/Contents
  ln -s $out $out/Applications/Xcode.app/Contents/Developer

  # The native xcodebuild command supports an invocation like "xcodebuild -version -sdk" without specifying the specific SDK, so we simulate this by
  # detecting this case and simulating the output; printing the header and appending the normal output via appending the sdk version to the positional
  # arguments we pass through to the wrapped xcodebuild.
  makeWrapper ${xcbuild}/bin/xcodebuild $out/bin/xcodebuild \
    --add-flags "-xcconfig ${xcconfig}" \
    --add-flags "DERIVED_DATA_DIR=." \
    --set DEVELOPER_DIR "$out" \
    --set SDKROOT ${sdkName} \
    --run '[ "$#" -eq 2 ] && [ "$1" = "-version" ] && [ "$2" = "-sdk" ] && echo ${sdkName}.sdk - macOS ${sdkVer} \(macosx${sdkVer}\) && set -- "$@" "${sdkName}"' \
    --run '[ "$1" = "-version" ] && [ "$#" -eq 1 ] && (echo Xcode ${xcodeVer}; echo Build version ${sdkBuildVersion}) && exit 0' \
    --run '[ "$1" = "-license" ] && exit 0'

  substitute ${xcode-select} $out/bin/xcode-select \
    --subst-var-by DEVELOPER_DIR $out/Applications/Xcode.app/Contents/Developer
  chmod +x $out/bin/xcode-select

  cp ${xcrun}/bin/xcrun $out/bin/xcrun

  for bin in PlistBuddy actool builtin-copy builtin-copyPlist \
             builtin-copyStrings builtin-copyTiff \
             builtin-embeddedBinaryValidationUtility \
             builtin-infoPlistUtility builtin-lsRegisterURL \
             builtin-productPackagingUtility builtin-validationUtility \
             lsbom plutil; do
    ln -s ${xcbuild}/bin/$bin $out/bin/$bin
  done

  fixupPhase
''