186 lines
6.3 KiB
Nix
186 lines
6.3 KiB
Nix
{
|
|
stdenv,
|
|
lib,
|
|
composeXcodeWrapper,
|
|
}:
|
|
{
|
|
name,
|
|
src,
|
|
sdkVersion ? "13.1",
|
|
target ? null,
|
|
configuration ? null,
|
|
scheme ? null,
|
|
sdk ? null,
|
|
xcodeFlags ? "",
|
|
release ? false,
|
|
certificateFile ? null,
|
|
certificatePassword ? null,
|
|
provisioningProfile ? null,
|
|
codeSignIdentity ? null,
|
|
signMethod ? null,
|
|
generateIPA ? false,
|
|
generateXCArchive ? false,
|
|
enableWirelessDistribution ? false,
|
|
installURL ? null,
|
|
bundleId ? null,
|
|
appVersion ? null,
|
|
...
|
|
}@args:
|
|
|
|
assert
|
|
release
|
|
->
|
|
certificateFile != null
|
|
&& certificatePassword != null
|
|
&& provisioningProfile != null
|
|
&& signMethod != null
|
|
&& codeSignIdentity != null;
|
|
assert enableWirelessDistribution -> installURL != null && bundleId != null && appVersion != null;
|
|
|
|
let
|
|
# Set some default values here
|
|
|
|
_target = if target == null then name else target;
|
|
|
|
_configuration =
|
|
if configuration == null then if release then "Release" else "Debug" else configuration;
|
|
|
|
_sdk =
|
|
if sdk == null then
|
|
if release then "iphoneos" + sdkVersion else "iphonesimulator" + sdkVersion
|
|
else
|
|
sdk;
|
|
|
|
# The following is to prevent repetition
|
|
deleteKeychain = ''
|
|
security default-keychain -s login.keychain
|
|
security delete-keychain $keychainName
|
|
'';
|
|
|
|
xcodewrapperFormalArgs = builtins.functionArgs composeXcodeWrapper;
|
|
xcodewrapperArgs = builtins.intersectAttrs xcodewrapperFormalArgs args;
|
|
xcodewrapper = composeXcodeWrapper xcodewrapperArgs;
|
|
|
|
extraArgs = removeAttrs args (
|
|
[
|
|
"name"
|
|
"scheme"
|
|
"xcodeFlags"
|
|
"release"
|
|
"certificateFile"
|
|
"certificatePassword"
|
|
"provisioningProfile"
|
|
"signMethod"
|
|
"generateIPA"
|
|
"generateXCArchive"
|
|
"enableWirelessDistribution"
|
|
"installURL"
|
|
"bundleId"
|
|
"version"
|
|
]
|
|
++ builtins.attrNames xcodewrapperFormalArgs
|
|
);
|
|
in
|
|
stdenv.mkDerivation (
|
|
{
|
|
name = lib.replaceStrings [ " " ] [ "" ] name; # iOS app names can contain spaces, but in the Nix store this is not allowed
|
|
buildPhase = ''
|
|
# Be sure that the Xcode wrapper has priority over everything else.
|
|
# When using buildInputs this does not seem to be the case.
|
|
export PATH=${xcodewrapper}/bin:$PATH
|
|
|
|
${lib.optionalString release ''
|
|
export HOME=/Users/$(whoami)
|
|
keychainName="$(basename $out)"
|
|
|
|
# Create a keychain
|
|
security create-keychain -p "" $keychainName
|
|
security default-keychain -s $keychainName
|
|
security unlock-keychain -p "" $keychainName
|
|
|
|
# Import the certificate into the keychain
|
|
security import ${certificateFile} -k $keychainName -P "${certificatePassword}" -A
|
|
|
|
# Grant the codesign utility permissions to read from the keychain
|
|
security set-key-partition-list -S apple-tool:,apple: -s -k "" $keychainName
|
|
|
|
# Determine provisioning ID
|
|
PROVISIONING_PROFILE=$(grep UUID -A1 -a ${provisioningProfile} | grep -o "[-A-Za-z0-9]\{36\}")
|
|
|
|
if [ ! -f "$HOME/Library/MobileDevice/Provisioning Profiles/$PROVISIONING_PROFILE.mobileprovision" ]
|
|
then
|
|
# Copy provisioning profile into the home directory
|
|
mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
|
|
cp ${provisioningProfile} "$HOME/Library/MobileDevice/Provisioning Profiles/$PROVISIONING_PROFILE.mobileprovision"
|
|
fi
|
|
|
|
# Check whether the identity can be found
|
|
security find-identity -p codesigning $keychainName
|
|
''}
|
|
|
|
# Do the building
|
|
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
|
|
|
|
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}
|
|
|
|
${lib.optionalString release ''
|
|
${lib.optionalString generateIPA ''
|
|
# Create export plist file
|
|
cat > "${name}.plist" <<EOF
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
<plist version="1.0">
|
|
<dict>
|
|
<key>signingCertificate</key>
|
|
<string>${codeSignIdentity}</string>
|
|
<key>provisioningProfiles</key>
|
|
<dict>
|
|
<key>${bundleId}</key>
|
|
<string>$PROVISIONING_PROFILE</string>
|
|
</dict>
|
|
<key>signingStyle</key>
|
|
<string>manual</string>
|
|
<key>method</key>
|
|
<string>${signMethod}</string>
|
|
${lib.optionalString (signMethod == "enterprise" || signMethod == "ad-hoc") ''
|
|
<key>compileBitcode</key>
|
|
<false/>
|
|
''}
|
|
</dict>
|
|
</plist>
|
|
EOF
|
|
|
|
# Produce an IPA file
|
|
xcodebuild -exportArchive -archivePath "${name}.xcarchive" -exportOptionsPlist "${name}.plist" -exportPath $out
|
|
|
|
# Add IPA to Hydra build products
|
|
mkdir -p $out/nix-support
|
|
echo "file binary-dist \"$(echo $out/*.ipa)\"" > $out/nix-support/hydra-build-products
|
|
|
|
${lib.optionalString enableWirelessDistribution ''
|
|
# Add another hacky build product that enables wireless adhoc installations
|
|
appname="$(basename "$(echo $out/*.ipa)" .ipa)"
|
|
sed -e "s|@INSTALL_URL@|${installURL}?bundleId=${bundleId}\&version=${appVersion}\&title=$appname|" ${./install.html.template} > $out/''${appname}.html
|
|
echo "doc install \"$out/''${appname}.html\"" >> $out/nix-support/hydra-build-products
|
|
''}
|
|
''}
|
|
${lib.optionalString generateXCArchive ''
|
|
mkdir -p $out
|
|
mv "${name}.xcarchive" $out
|
|
''}
|
|
|
|
# Delete our temp keychain
|
|
${deleteKeychain}
|
|
''}
|
|
'';
|
|
|
|
failureHook = lib.optionalString release deleteKeychain;
|
|
|
|
installPhase = "true";
|
|
}
|
|
// extraArgs
|
|
)
|