iOS builds via command line are much more complex as compared to Android.
Note: Builds work only for Mac users. Since Apple requires that all the builds be made on Xcode itself, iOS apps can only be built on a Mac machine.
These are the few pre-requisites to build a release ipa file.
Ideally, every app has three release variants just like a typical backend application:
Hence, we would need three different schemes
for three different variants.
A typical build process in iOS would have the following steps:
~/Library/MobileDevice/Provisioning\ Profiles/
scripts/ios/profile/XYZ.mobileprovision
scripts/ios/certs/ABC.p12
Place an exportOptions file at scripts/ios/exportOptions/exportOptions-dev.plist
Typically, an exportOptions file looks like this :
scripts/ios/exportOptions/exportOptions-dev.plist
<?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>compileBitcode</key>
<false/>
<key>method</key>
<string>enterprise</string>
<key>teamID</key>
<string>ABC1234DA</string>
<key>uploadBitcode</key>
<true/>
<key>uploadSymbols</key>
<true/>
<key>manifest</key>
<dict>
<key>appURL</key>
<string>null</string>
<key>displayImageURL</key>
<string>null</string>
<key>fullSizeImageURL</key>
<string>null</string>
</dict>
</dict>
</plist>
Make sure you put all the above files in the gitignore.
Create the script:
The below script will create a new keychain ios-build
and will store the certificate in the keychain. Also, it will make ios-build
the default keychain so that Xcode picks up the certificate from it. Then it will copy the provisioning profile to the correct directory so that Xcode can pick it up.
scripts/ios/keychain.sh
#!/bin/bash
set -e
cur_dir=`dirname $0`
#Check if ios-build keychain exists
export keychainCount=`security list-keychains | grep -E 'ios-build' -c`
if [ $keychainCount == 0 ] ; then
echo "Create ios-build keychain"
# Create a custom keychain
security create-keychain -p "ios-build-password" ios-build.keychain
fi
# Add it to the list
security list-keychains -d user -s ios-build.keychain
echo "Making the ios-build keychain default, so xcodebuild will use it for signing"
security default-keychain -s ios-build.keychain
echo "Unlocking the ios-build keychain"
security unlock-keychain -p "ios-build-password" ios-build.keychain
# Set keychain timeout to 1 hour for long builds
# see http://www.egeek.me/2013/02/23/jenkins-and-xcode-user-interaction-is-not-allowed/
security set-keychain-settings -t 3600 -l ~/Library/Keychains/ios-build.keychain
echo "Importing $IOS_CERTIFICATE to keychain"
security import $cur_dir/certs/$IOS_CERTIFICATE -k ~/Library/Keychains/ios-build.keychain -P $IOS_CERTIFICATE_KEY -T "/usr/bin/codesign" -A
#Mac OS Sierra https://stackoverflow.com/questions/39868578/security-codesign-in-sierra-keychain-ignores-access-control-settings-and-ui-p
security set-key-partition-list -S apple-tool:,apple: -s -k "ios-build-password" ios-build.keychain
# Put the provisioning profile in place
echo "Copying $IOS_PROVISION_PROFILE in place"
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp "$cur_dir/profile/$IOS_PROVISION_PROFILE" ~/Library/MobileDevice/Provisioning\ Profiles/
Create the script that does the build. This script will run the xcodebuild to first archive the project. Then it will generate the IPA file which can be used for installing the app onto an iPhone.
scripts/ios/builder.sh
#!/bin/bash
set -e
cur_dir=`dirname $0`
WORKING_DIR=`pwd`;
cd $cur_dir/../../ios
echo "Setting version to ${BUILD_NUMBER}, ${BUILD_NAME}"
xcrun agvtool new-version -all ${BUILD_NUMBER}
xcrun agvtool new-marketing-version ${BUILD_NAME}
cd $WORKING_DIR
echo "Archiving the project"
xcodebuild clean archive PRODUCT_BUNDLE_IDENTIFIER=${IOS_APP_ID} -project $cur_dir/../../ios/${PROJECT_NAME}.xcodeproj -scheme $IOS_SCHEME -configuration $IOS_CONFIGURATION -derivedDataPath $cur_dir/../../ios/build -archivePath $cur_dir/../../ios/build/Products/${PROJECT_NAME}.xcarchive
# or if you are not using xcodeproj and are using xcworkspace to build.. use the below code:
# echo "Archiving the project"
# xcodebuild clean archive PRODUCT_BUNDLE_IDENTIFIER=${IOS_APP_ID} -workspace $cur_dir/../../ios/${PROJECT_NAME}.xcworkspace -scheme $IOS_SCHEME -configuration $IOS_CONFIGURATION -derivedDataPath $cur_dir/../../ios/build -archivePath $cur_dir/../../ios/build/Products/${PROJECT_NAME}.xcarchive
#SIGN
# Issue : "No applicable devices found."
# Fix: https://stackoverflow.com/questions/39634404/xcodebuild-exportarchive-no-applicable-devices-found
unset GEM_HOME
unset GEM_PATH
echo "Export archive to create IPA file using $IOS_EXPORT_OPTIONS_PLIST"
xcodebuild -exportArchive -archivePath $cur_dir/../../ios/build/Products/${PROJECT_NAME}.xcarchive -exportOptionsPlist $cur_dir/../../scripts/ios/exportOptions/$IOS_EXPORT_OPTIONS_PLIST -exportPath $cur_dir/../../ios/build/Products/IPA
echo "IPA will be found at $cur_dir/../../ios/build/Products/IPA/$IOS_SCHEME.ipa"
Run the keychain.sh
to setup the certificate and provision profile like this:
IOS_CERTIFICATE='ABC.p12' IOS_CERTIFICATE_KEY='PASSWORD' IOS_PROVISION_PROFILE='ABC.mobileprovision' sh scripts/ios/keychain.sh
Now, run the build script to build the ipa file like this:
PROJECT_NAME='NoteTaker' IOS_APP_ID='com.notetaker.app.ios' BUILD_NUMBER=11 BUILD_NAME=1.1.1 IOS_SCHEME='local' IOS_CONFIGURATION='RELEASE' IOS_EXPORT_OPTIONS_PLIST='exportOptions-dev.plist' sh ./scripts/ios/builder.sh
The build should take a couple of minutes and you can find the final ipa file at
ios/build/Products/IPA/
The code till here can be found on the branch chapter/11/11.2