Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1{stdenv, lib, composeXcodeWrapper}:
2{ name
3, src
4, sdkVersion ? "13.1"
5, target ? null
6, configuration ? null
7, scheme ? null
8, sdk ? null
9, xcodeFlags ? ""
10, release ? false
11, certificateFile ? null
12, certificatePassword ? null
13, provisioningProfile ? null
14, codeSignIdentity ? null
15, signMethod ? null
16, generateIPA ? false
17, generateXCArchive ? false
18, enableWirelessDistribution ? false
19, installURL ? null
20, bundleId ? null
21, appVersion ? null
22, ...
23}@args:
24
25assert release -> certificateFile != null && certificatePassword != null && provisioningProfile != null && signMethod != null && codeSignIdentity != null;
26assert enableWirelessDistribution -> installURL != null && bundleId != null && appVersion != null;
27
28let
29 # Set some default values here
30
31 _target = if target == null then name else target;
32
33 _configuration = if configuration == null
34 then
35 if release then "Release" else "Debug"
36 else configuration;
37
38 _sdk = if sdk == null
39 then
40 if release then "iphoneos" + sdkVersion else "iphonesimulator" + sdkVersion
41 else sdk;
42
43 # The following is to prevent repetition
44 deleteKeychain = ''
45 security default-keychain -s login.keychain
46 security delete-keychain $keychainName
47 '';
48
49 xcodewrapperFormalArgs = builtins.functionArgs composeXcodeWrapper;
50 xcodewrapperArgs = builtins.intersectAttrs xcodewrapperFormalArgs args;
51 xcodewrapper = composeXcodeWrapper xcodewrapperArgs;
52
53 extraArgs = removeAttrs args ([ "name" "scheme" "xcodeFlags" "release" "certificateFile" "certificatePassword" "provisioningProfile" "signMethod" "generateIPA" "generateXCArchive" "enableWirelessDistribution" "installURL" "bundleId" "version" ] ++ builtins.attrNames xcodewrapperFormalArgs);
54in
55stdenv.mkDerivation ({
56 name = lib.replaceStrings [" "] [""] name; # iOS app names can contain spaces, but in the Nix store this is not allowed
57 buildPhase = ''
58 # Be sure that the Xcode wrapper has priority over everything else.
59 # When using buildInputs this does not seem to be the case.
60 export PATH=${xcodewrapper}/bin:$PATH
61
62 ${lib.optionalString release ''
63 export HOME=/Users/$(whoami)
64 keychainName="$(basename $out)"
65
66 # Create a keychain
67 security create-keychain -p "" $keychainName
68 security default-keychain -s $keychainName
69 security unlock-keychain -p "" $keychainName
70
71 # Import the certificate into the keychain
72 security import ${certificateFile} -k $keychainName -P "${certificatePassword}" -A
73
74 # Grant the codesign utility permissions to read from the keychain
75 security set-key-partition-list -S apple-tool:,apple: -s -k "" $keychainName
76
77 # Determine provisioning ID
78 PROVISIONING_PROFILE=$(grep UUID -A1 -a ${provisioningProfile} | grep -o "[-A-Za-z0-9]\{36\}")
79
80 if [ ! -f "$HOME/Library/MobileDevice/Provisioning Profiles/$PROVISIONING_PROFILE.mobileprovision" ]
81 then
82 # Copy provisioning profile into the home directory
83 mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
84 cp ${provisioningProfile} "$HOME/Library/MobileDevice/Provisioning Profiles/$PROVISIONING_PROFILE.mobileprovision"
85 fi
86
87 # Check whether the identity can be found
88 security find-identity -p codesigning $keychainName
89 ''}
90
91 # Do the building
92 export LD=/usr/bin/clang # To avoid problem with -isysroot parameter that is unrecognized by the stock ld. Comparison with an impure build shows that it uses clang instead. Ugly, but it works
93
94 xcodebuild -target ${_target} -configuration ${_configuration} ${lib.optionalString (scheme != null) "-scheme ${scheme}"} -sdk ${_sdk} TARGETED_DEVICE_FAMILY="1, 2" ONLY_ACTIVE_ARCH=NO CONFIGURATION_TEMP_DIR=$TMPDIR CONFIGURATION_BUILD_DIR=$out ${lib.optionalString (generateIPA || generateXCArchive) "-archivePath \"${name}.xcarchive\" archive"} ${lib.optionalString release '' PROVISIONING_PROFILE=$PROVISIONING_PROFILE OTHER_CODE_SIGN_FLAGS="--keychain $HOME/Library/Keychains/$keychainName-db"''} ${xcodeFlags}
95
96 ${lib.optionalString release ''
97 ${lib.optionalString generateIPA ''
98 # Create export plist file
99 cat > "${name}.plist" <<EOF
100 <?xml version="1.0" encoding="UTF-8"?>
101 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
102 <plist version="1.0">
103 <dict>
104 <key>signingCertificate</key>
105 <string>${codeSignIdentity}</string>
106 <key>provisioningProfiles</key>
107 <dict>
108 <key>${bundleId}</key>
109 <string>$PROVISIONING_PROFILE</string>
110 </dict>
111 <key>signingStyle</key>
112 <string>manual</string>
113 <key>method</key>
114 <string>${signMethod}</string>
115 ${lib.optionalString (signMethod == "enterprise" || signMethod == "ad-hoc") ''
116 <key>compileBitcode</key>
117 <false/>
118 ''}
119 </dict>
120 </plist>
121 EOF
122
123 # Produce an IPA file
124 xcodebuild -exportArchive -archivePath "${name}.xcarchive" -exportOptionsPlist "${name}.plist" -exportPath $out
125
126 # Add IPA to Hydra build products
127 mkdir -p $out/nix-support
128 echo "file binary-dist \"$(echo $out/*.ipa)\"" > $out/nix-support/hydra-build-products
129
130 ${lib.optionalString enableWirelessDistribution ''
131 # Add another hacky build product that enables wireless adhoc installations
132 appname="$(basename "$(echo $out/*.ipa)" .ipa)"
133 sed -e "s|@INSTALL_URL@|${installURL}?bundleId=${bundleId}\&version=${appVersion}\&title=$appname|" ${./install.html.template} > $out/''${appname}.html
134 echo "doc install \"$out/''${appname}.html\"" >> $out/nix-support/hydra-build-products
135 ''}
136 ''}
137 ${lib.optionalString generateXCArchive ''
138 mkdir -p $out
139 mv "${name}.xcarchive" $out
140 ''}
141
142 # Delete our temp keychain
143 ${deleteKeychain}
144 ''}
145 '';
146
147 failureHook = lib.optionalString release deleteKeychain;
148
149 installPhase = "true";
150} // extraArgs)