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