Replace xcodeenv with new implementation

This commit is contained in:
Sander van der Burg 2018-11-17 21:55:49 +01:00
parent 74750dc67d
commit 907216a57d
5 changed files with 97 additions and 81 deletions

View File

@ -1,14 +1,13 @@
{stdenv, xcodewrapper}: {stdenv, composeXcodeWrapper}:
{ name { name
, src , src
, sdkVersion ? "11.2" , sdkVersion ? "11.3"
, target ? null , target ? null
, configuration ? null , configuration ? null
, scheme ? null , scheme ? null
, sdk ? null , sdk ? null
, xcodeFlags ? "" , xcodeFlags ? ""
, release ? false , release ? false
, codeSignIdentity ? null
, certificateFile ? null , certificateFile ? null
, certificatePassword ? null , certificatePassword ? null
, provisioningProfile ? null , provisioningProfile ? null
@ -18,24 +17,23 @@
, enableWirelessDistribution ? false , enableWirelessDistribution ? false
, installURL ? null , installURL ? null
, bundleId ? null , bundleId ? null
, version ? null , appVersion ? null
, title ? null , ...
, meta ? {} }@args:
}:
assert release -> codeSignIdentity != null && certificateFile != null && certificatePassword != null && provisioningProfile != null && signMethod != null; assert release -> certificateFile != null && certificatePassword != null && provisioningProfile != null && signMethod != null;
assert enableWirelessDistribution -> installURL != null && bundleId != null && version != null && title != null; assert enableWirelessDistribution -> installURL != null && bundleId != null && appVersion != null;
let let
# Set some default values here # Set some default values here
_target = if target == null then name else target; _target = if target == null then name else target;
_configuration = if configuration == null _configuration = if configuration == null
then then
if release then "Release" else "Debug" if release then "Release" else "Debug"
else configuration; else configuration;
_sdk = if sdk == null _sdk = if sdk == null
then then
if release then "iphoneos" + sdkVersion else "iphonesimulator" + sdkVersion if release then "iphoneos" + sdkVersion else "iphonesimulator" + sdkVersion
@ -46,41 +44,45 @@ let
security default-keychain -s login.keychain security default-keychain -s login.keychain
security delete-keychain $keychainName 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 in
stdenv.mkDerivation { stdenv.mkDerivation ({
name = stdenv.lib.replaceChars [" "] [""] name; name = stdenv.lib.replaceChars [" "] [""] name; # iOS app names can contain spaces, but in the Nix store this is not allowed
inherit src;
inherit meta;
buildInputs = [ xcodewrapper ]; buildInputs = [ xcodewrapper ];
buildPhase = '' buildPhase = ''
${stdenv.lib.optionalString release '' ${stdenv.lib.optionalString release ''
export HOME=/Users/$(whoami) export HOME=/Users/$(whoami)
keychainName="$(basename $out)" 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 # Create a keychain
security set-key-partition-list -S apple-tool:,apple: -s -k "" $keychainName security create-keychain -p "" $keychainName
security default-keychain -s $keychainName
# Determine provisioning ID security unlock-keychain -p "" $keychainName
PROVISIONING_PROFILE=$(grep UUID -A1 -a ${provisioningProfile} | grep -o "[-A-Za-z0-9]\{36\}")
if [ ! -f "$HOME/Library/MobileDevice/Provisioning Profiles/$PROVISIONING_PROFILE.mobileprovision" ] # Import the certificate into the keychain
then security import ${certificateFile} -k $keychainName -P "${certificatePassword}" -A
# Copy provisioning profile into the home directory
mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles" # Grant the codesign utility permissions to read from the keychain
cp ${provisioningProfile} "$HOME/Library/MobileDevice/Provisioning Profiles/$PROVISIONING_PROFILE.mobileprovision" security set-key-partition-list -S apple-tool:,apple: -s -k "" $keychainName
fi
# Determine provisioning ID
# Check whether the identity can be found PROVISIONING_PROFILE=$(grep UUID -A1 -a ${provisioningProfile} | grep -o "[-A-Za-z0-9]\{36\}")
security find-identity -p codesigning $keychainName
''} 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 # Do the building
export LD=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 export LD=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
@ -116,10 +118,11 @@ stdenv.mkDerivation {
# Add IPA to Hydra build products # Add IPA to Hydra build products
mkdir -p $out/nix-support mkdir -p $out/nix-support
echo "file binary-dist \"$(echo $out/*.ipa)\"" > $out/nix-support/hydra-build-products echo "file binary-dist \"$(echo $out/*.ipa)\"" > $out/nix-support/hydra-build-products
${stdenv.lib.optionalString enableWirelessDistribution '' ${stdenv.lib.optionalString enableWirelessDistribution ''
appname=$(basename $out/*.ipa .ipa) # Add another hacky build product that enables wireless adhoc installations
sed -e "s|@INSTALL_URL@|${installURL}?bundleId=${bundleId}\&version=${version}\&title=$appname|" ${./install.html.template} > $out/$appname.html appname="$(basename "$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 echo "doc install \"$out/$appname.html\"" >> $out/nix-support/hydra-build-products
''} ''}
''} ''}
@ -127,13 +130,13 @@ stdenv.mkDerivation {
mkdir -p $out mkdir -p $out
mv "${name}.xcarchive" $out mv "${name}.xcarchive" $out
''} ''}
# Delete our temp keychain # Delete our temp keychain
${deleteKeychain} ${deleteKeychain}
''} ''}
''; '';
failureHook = stdenv.lib.optionalString release deleteKeychain; failureHook = stdenv.lib.optionalString release deleteKeychain;
installPhase = "true"; installPhase = "true";
} } // extraArgs)

View File

@ -1,4 +1,7 @@
{stdenv, version, xcodeBaseDir}: {stdenv}:
{version ? "9.3", xcodeBaseDir ? "/Applications/Xcode.app"}:
assert stdenv.isDarwin;
stdenv.mkDerivation { stdenv.mkDerivation {
name = "xcode-wrapper-"+version; name = "xcode-wrapper-"+version;
@ -9,6 +12,7 @@ stdenv.mkDerivation {
ln -s /usr/bin/security ln -s /usr/bin/security
ln -s /usr/bin/codesign ln -s /usr/bin/codesign
ln -s /usr/bin/xcrun ln -s /usr/bin/xcrun
ln -s /usr/bin/plutil
ln -s "${xcodeBaseDir}/Contents/Developer/usr/bin/xcodebuild" ln -s "${xcodeBaseDir}/Contents/Developer/usr/bin/xcodebuild"
ln -s "${xcodeBaseDir}/Contents/Developer/Applications/Simulator.app/Contents/MacOS/Simulator" ln -s "${xcodeBaseDir}/Contents/Developer/Applications/Simulator.app/Contents/MacOS/Simulator"

View File

@ -1,15 +1,15 @@
{stdenv, version ? "9.2", xcodeBaseDir ? "/Applications/Xcode.app"}: {stdenv}:
rec { rec {
xcodewrapper = import ./xcodewrapper.nix { composeXcodeWrapper = import ./compose-xcodewrapper.nix {
inherit stdenv version xcodeBaseDir; inherit stdenv;
}; };
buildApp = import ./build-app.nix { buildApp = import ./build-app.nix {
inherit stdenv xcodewrapper; inherit stdenv composeXcodeWrapper;
}; };
simulateApp = import ./simulate-app.nix { simulateApp = import ./simulate-app.nix {
inherit stdenv xcodewrapper; inherit stdenv composeXcodeWrapper;
}; };
} }

View File

@ -4,14 +4,14 @@
<head> <head>
<title>Install IPA</title> <title>Install IPA</title>
</head> </head>
<body> <body>
<a id="forwardlink" href="@INSTALL_URL@">Go to the install page or wait a second</a> <a id="forwardlink" href="@INSTALL_URL@">Go to the install page or wait a second</a>
<script type="text/javascript"> <script type="text/javascript">
setTimeout(function() { setTimeout(function() {
var link = document.getElementById('forwardlink'); var link = document.getElementById('forwardlink');
if(document.createEvent) { if(document.createEvent) {
var eventObj = document.createEvent('MouseEvents'); var eventObj = document.createEvent('MouseEvents');
eventObj.initEvent('click', true, false); eventObj.initEvent('click', true, false);

View File

@ -1,47 +1,56 @@
{stdenv, xcodewrapper}: {stdenv, composeXcodeWrapper}:
{name, bundleId, app}: {name, app ? null, bundleId ? null, ...}@args:
assert app != null -> bundleId != null;
let
xcodewrapperArgs = builtins.intersectAttrs (builtins.functionArgs composeXcodeWrapper) args;
xcodewrapper = composeXcodeWrapper xcodewrapperArgs;
in
stdenv.mkDerivation { stdenv.mkDerivation {
name = stdenv.lib.replaceChars [" "] [""] name; name = stdenv.lib.replaceChars [" "] [""] name;
buildCommand = '' buildCommand = ''
mkdir -p $out/bin mkdir -p $out/bin
cat > $out/bin/run-test-simulator << "EOF" cat > $out/bin/run-test-simulator << "EOF"
#! ${stdenv.shell} -e #! ${stdenv.shell} -e
if [ "$1" = "" ] if [ "$1" = "" ]
then then
# Show the user the possibile UDIDs and let him pick one, if none is provided as a command-line parameter # Show the user the possibile UDIDs and let him pick one, if none is provided as a command-line parameter
xcrun simctl list xcrun simctl list
echo "Please provide a UDID of a simulator:" echo "Please provide a UDID of a simulator:"
read udid read udid
else else
# If a parameter has been provided, consider that a device UDID and use that # If a parameter has been provided, consider that a device UDID and use that
udid="$1" udid="$1"
fi fi
# Open the simulator instance # Open the simulator instance
open -a "$(readlink "${xcodewrapper}/bin/Simulator")" --args -CurrentDeviceUDID $udid open -a "$(readlink "${xcodewrapper}/bin/Simulator")" --args -CurrentDeviceUDID $udid
# Copy the app and restore the write permissions
appTmpDir=$(mktemp -d -t appTmpDir)
cp -r "$(echo ${app}/*.app)" "$appTmpDir"
chmod -R 755 "$(echo $appTmpDir/*.app)"
# Wait for the simulator to start
echo "Press enter when the simulator is started..."
read
# Install the app
xcrun simctl install "$udid" "$(echo $appTmpDir/*.app)"
# Remove the app tempdir
rm -Rf $appTmpDir
# Launch the app in the simulator
xcrun simctl launch $udid "${bundleId}"
EOF
chmod +x $out/bin/run-test-simulator ${stdenv.lib.optionalString (app != null) ''
# Copy the app and restore the write permissions
appTmpDir=$(mktemp -d -t appTmpDir)
cp -r "$(echo ${app}/*.app)" "$appTmpDir"
chmod -R 755 "$(echo $appTmpDir/*.app)"
# Wait for the simulator to start
echo "Press enter when the simulator is started..."
read
# Install the app
xcrun simctl install "$udid" "$(echo $appTmpDir/*.app)"
# Remove the app tempdir
rm -Rf $appTmpDir
# Launch the app in the simulator
xcrun simctl launch $udid "${bundleId}"
EOF
chmod +x $out/bin/run-test-simulator
''}
''; '';
} }