1 { lib, stdenv, makeWrapper, writeText, writeTextFile, runCommand, callPackage
2 , CoreServices, ImageIO, CoreGraphics
3 , xcodePlatform ? stdenv.targetPlatform.xcodePlatform or "MacOSX"
4 , xcodeVer ? stdenv.targetPlatform.xcodeVer or "9.4.1"
5 , sdkVer ? stdenv.targetPlatform.darwinSdkVersion or "10.12"
6 , productBuildVer ? null
11 toolchainName = "com.apple.dt.toolchain.XcodeDefault";
12 sdkName = "${xcodePlatform}${sdkVer}";
13 xcrunSdkName = lib.toLower xcodePlatform;
15 # TODO: expose MACOSX_DEPLOYMENT_TARGET in nix so we can use it here.
16 sdkBuildVersion = "17E189";
17 xcodeSelectVersion = "2349";
19 xcbuild = callPackage ./default.nix {
20 inherit CoreServices ImageIO CoreGraphics stdenv;
23 toolchains = callPackage ./toolchains.nix {
24 inherit toolchainName stdenv;
27 sdks = callPackage ./sdks.nix {
28 inherit toolchainName sdkName xcodePlatform sdkVer productBuildVer;
31 platforms = callPackage ./platforms.nix {
32 inherit sdks xcodePlatform stdenv;
35 xcconfig = writeText "nix.xcconfig" ''
39 xcode-select = writeText "xcode-select" ''
41 while [ $# -gt 0 ]; do
43 -h | --help) ;; # noop
44 -s | --switch) shift;; # noop
45 -r | --reset) ;; # noop
46 -v | --version) echo xcode-select version ${xcodeSelectVersion} ;;
47 -p | -print-path | --print-path) echo @DEVELOPER_DIR@ ;;
54 xcrun = writeTextFile {
57 destination = "/bin/xcrun";
62 # If an SDK was requested, check that it matches.
63 for ((i = 0; i < ''${#args[@]}; i++)); do
64 case "''${args[i]}" in
67 if [[ "''${args[i]}" != '${xcrunSdkName}' ]]; then
68 echo >&2 "xcodebuild: error: SDK \"''${args[i]}\" cannot be located."
75 while [ $# -gt 0 ]; do
77 --sdk | -sdk) shift ;;
78 --toolchain | -toolchain) shift ;;
81 command -v $1 || exit 1 ;;
82 --log | -log) ;; # noop
83 --verbose | -verbose) ;; # noop
84 --no-cache | -no-cache) ;; # noop
85 --kill-cache | -kill-cache) ;; # noop
86 --show-sdk-path | -show-sdk-path)
87 echo ${sdks}/${sdkName}.sdk ;;
88 --show-sdk-platform-path | -show-sdk-platform-path)
89 echo ${platforms}/${xcodePlatform}.platform ;;
90 --show-sdk-version | -show-sdk-version)
92 --show-sdk-build-version | -show-sdk-build-version)
93 echo ${sdkBuildVersion} ;;
99 if ! [[ -z "$@" ]]; then
104 ${stdenv.shellDryRun} "$target"
110 runCommand "xcodebuild-${xcbuild.version}" {
111 nativeBuildInputs = [ makeWrapper ];
112 inherit (xcbuild) meta;
114 # ensure that the toolchain goes in PATH
115 propagatedBuildInputs = [ "${toolchains}/XcodeDefault.xctoolchain" ];
118 inherit xcbuild xcrun;
119 toolchain = "${toolchains}/XcodeDefault.xctoolchain";
120 sdk = "${sdks}/${sdkName}";
121 platform = "${platforms}/${xcodePlatform}.platform";
124 preferLocalBuild = true;
130 mkdir -p $out/Library/Xcode
131 ln -s ${xcbuild}/Library/Xcode/Specifications $out/Library/Xcode/Specifications
133 ln -s ${platforms} $out/Platforms
134 ln -s ${toolchains} $out/Toolchains
136 mkdir -p $out/Applications/Xcode.app/Contents
137 ln -s $out $out/Applications/Xcode.app/Contents/Developer
139 # The native xcodebuild command supports an invocation like "xcodebuild -version -sdk" without specifying the specific SDK, so we simulate this by
140 # detecting this case and simulating the output; printing the header and appending the normal output via appending the sdk version to the positional
141 # arguments we pass through to the wrapped xcodebuild.
142 makeWrapper ${xcbuild}/bin/xcodebuild $out/bin/xcodebuild \
143 --add-flags "-xcconfig ${xcconfig}" \
144 --add-flags "DERIVED_DATA_DIR=." \
145 --set DEVELOPER_DIR "$out" \
146 --set SDKROOT ${sdkName} \
147 --run '[ "$#" -eq 2 ] && [ "$1" = "-version" ] && [ "$2" = "-sdk" ] && echo ${sdkName}.sdk - macOS ${sdkVer} \(macosx${sdkVer}\) && set -- "$@" "${sdkName}"' \
148 --run '[ "$1" = "-version" ] && [ "$#" -eq 1 ] && (echo Xcode ${xcodeVer}; echo Build version ${sdkBuildVersion}) && exit 0' \
149 --run '[ "$1" = "-license" ] && exit 0'
151 substitute ${xcode-select} $out/bin/xcode-select \
152 --subst-var-by DEVELOPER_DIR $out/Applications/Xcode.app/Contents/Developer
153 chmod +x $out/bin/xcode-select
155 cp ${xcrun}/bin/xcrun $out/bin/xcrun
157 for bin in PlistBuddy actool builtin-copy builtin-copyPlist \
158 builtin-copyStrings builtin-copyTiff \
159 builtin-embeddedBinaryValidationUtility \
160 builtin-infoPlistUtility builtin-lsRegisterURL \
161 builtin-productPackagingUtility builtin-validationUtility \
163 ln -s ${xcbuild}/bin/$bin $out/bin/$bin