Export .ipa file from Xcode project without ever opening Xcode - ios

We have an API that users can call to create Cordova apps/projects, upload their www directory, and then start compilation and download the executable binary file. This binary file will then go into a private app store.
I'm having trouble with the compile step for iOS. The Cordova build step is no problem, but it doesn't output a binary file, like it does for Android. After reading everything I found on Stackoverflow and elsewhere, the plan was this:
xcodebuild clean -configuration Release -alltargets
xcodebuild -scheme MyApp archive -archivePath build/MyApp
xcodebuild -exportArchive -exportFormat ipa -archivePath "build/MyApp.xcarchive" -exportPath "MyApp.ipa" -exportProvisioningProfile "My Prov Profile"
Given that the signing identity and everything is set up correctly, it almost works. The first command executes fine. The second command just hangs.
However, if I open the project in Xcode, and then execute the commands, it compiles and exports, and I'm left with an .ipa file, which is what I wanted. It seems that Xcode sets up a workspace and some scheme-related things when the project is first opened.
Is there any way I can get xcodebuild (or xcrun, or anything, for that matter) to create this workspace file for me?
Or is there another way to approach this?
Right now, I have a solution where I actually open the Xcode project, wait 15 seconds, and then proceed. But I can think of a thousand ways that will fail at some point, so I would like to change it to something a little more elegant.
I currently have Xcode 6.3 installed, if that is relevant.
Update: Opal's answer below set me on the right path (I think). What I ended up doing, was exporting a shared scheme as per Opal's link, and using that as a template for future apps. The solutions was something like this:
# Copy shared scheme file into directory
mkdir /path/to/project/dir/MyApp.xcodeproj/xcshareddata
mkdir /path/to/project/dir/MyApp.xcodeproj/xcshareddata/xcschemes
cp data/MyScheme.xcscheme /path/to/project/dir/MyApp.xcodeproj/xcshareddata/xcschemes/.
# Use sed to replace app name in scheme file
sed -i '' "s/%app_name%/MyApp/g" MyApp.xcodeproj/xcshareddata/xcschemes/MyScheme.xcscheme
# CD into directory
cd /path/to/project/dir
# Move files from Cordova to our build directory
cp -r CordovaLib/build/* build/.
# Build and export
xcodebuild clean -configuration Release -alltargets
xcodebuild -scheme MyScheme archive -archivePath build/MyApp
xcodebuild -exportArchive -exportFormat ipa -archivePath "build/MyApp.xcarchive" -exportPath "MyApp.ipa" -exportProvisioningProfile "MyProvProfile"

It seems that the application you try to build has no shared schemes. Schemes if not shared, are created when project is loaded to xcode. To create shared schemes see this site.

These are the steps I used to automate ipa generation without opening xcode in my cordova environment. (xcode version: 6.0.1 cordova version: 3.6.0)
Change in cordova/build.xcconfig: CODE_SIGN_IDENTITY=iPhone Distribution (change "Developer" to "Distribution". )
run cordova build ios --device in cordova workspace that generates .app file
Sign using : xcrun -sdk iphoneos PackageApplication -v ${WORKSPACE}/platforms/ios/build/device/${application.name}.app -o ${WORKSPACE}/platforms/ios/build/${application.name}.ipa --embed ${ios.distribution.provisionfile}.mobileprovision --sign ${code.signing.identity}

Related

Producing .xcarchive for target when building for iOS with CMake

I'm trying to automate iOS building through CMake, up to and including authoring .ipas. I have my provisioning profile and certificates set up, build is successful, but when I execute cmake --build I can't get .xcarchives to generate, and my POST_BUILD command (using xcodebuild) to author the .ipa is dependent on that.
I've tried setting some archive options though CMake (setting cmake_archive_output_directory), but there's a flag or option to set that can produce xcarchives during build, I don't know it. Does anyone have experience with this?
Despite many attempts, a post-build command to xcodebuild archive never worked -- I'm still not sure why, either. What I ended up doing to work around this was have CMake generate a script.
So my create executable custom function does this:
It creates a script file if it doesn't already exist, then for each executable target, appends an xcodebuild command if it's not a duplicate:
xcodebuild -workspace ${pathToTargetWorkspace} -scheme ${targetScheme} -configuration ${config} -archivePath ${pathToGeneratedArchive}.xcarchive archive
Then after building is finished, you just run the script with the aggregation of archive commands and it archives all the targets.

Create .ipa using multiple targets

Currently I'm using a bash script to build and archive our iOS application. With the introduction of "Watch" I have found that my script is no longer able to create the necessary .ipa file as it once did.
The build would generate a single .app file which I would use XCRUN to invoke PackageApplication in order to create the .ipa. Now I'm looking to archive 2 .app files along with 1 .appex file.
Has anyone been able to successfully create an .ipa file via command line/script with multiple .app files?
Using Xcode 6.2
Update
Now using Xcode 7 GM along with OSX 10.10.4.
For "TEST" builds I had a difficult time with developers always changing the profiles so I made 2 builds; one from the command line and the other via the IDE (Xcode). I changed the .ipa extension to .zip and compared the 2.
The good build from the IDE had generated a file called "archived-expanded-entitlements.xcent" which had all the signing identities defined correctly.
I copied this file out to a different directory and use it to inject with all other subsequent builds. The builds now are able to be loaded on the phone & watch for testing.
Below is an example of how to do it. A bit of a hack but it works.
security -v unlock-keychain -p "password" "keychainPath"
xcodebuild -configuration Test -scheme YourAppName -archivePath somePath/YourAppName.xcarchive archive
xcodebuild -exportArchive -exportFormat IPA -archivePath somePath/YourAppName.xcarchive -exportPath somePath/YourAppName.ipa
unzip -o somePath/YourAppName.ipa -d somePath
cp somePath/archived-expanded-entitlements.xcent somePath/Payload/YourAppName.app
zip -qr somePath/YourAppName.ipa Payload
I find a solution which is working on the archive file of the project which has watch, app and extension.
xcodebuild -exportArchive -archivePath AppName.xcarchive/ -exportPath AppName.ipa -exportFormat ipa -exportWithOriginalSigningIdentity
This command basically uses same signing identify and provisioning profile to export the ipa from raw xcarchive file.
We have sort of work around to generate .ipa that contains iPhone app and apple watch app.
After the .app is generated using Xcodebuild, in the bash script we do the following
A)
Create Directory with Application Name
Inside Application directory create sub directory named Payload
Copy .app into Payload directory
B)
Inside Application directory create sub directory named WatchKitSupport as a sibling to Payload.
Copy a binary named "WK" from the iOS 8.2 SDK in Xcode to your new WatchKitSupport directory. This binary can be found at: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/Library/Application Support/WatchKit/
Make sure the "WK" binary is not touched/re-signed in any way. This is important for validation on device.
Zip the application folder
Rename .zip to .ipa
When expanded the IPA should contain (at least):
xxx.ipa
|________Payload/
|________WatchKitSupport/
|_____WK
This works for us.

Create IPA with symbols using xcrun

I noticed a different when creating an .ipa file manually using xcrun than exporting it from xcode. The xcrun version doesn't have any symbols included with the .ipa.
I was wondering what's the best way to create an .ipa with symbols (no reason not to send them) manually from the command line, I'm using TeamCity CI to generate our production .ipa files.
I use the following command line to generate the IPA -
/usr/bin/xcrun -sdk iphoneos PackageApplication -v "DerivedData/MyApp/Build/Products/Release-iphoneos/MyApp.app" -o "~/MyApp.ipa" --sign "<HIDDEN>" --embed "<HIDDEN>"
I run it after invoking xcodebuild so the Release-iphoneos folder got the latest release version of my app.
I'll answer myself -
In Xcode 7 Apple added the ability to specify export options plist file to better control the .ipa file creation.
One of the options there is <key>uploadSymbols</key> that does exactly what I need.
http://www.matrixprojects.net/p/xcodebuild-export-options-plist

xcodebuild archive generates malformed xcarchive when adding custom build settings

I'm trying to generate an xcarchive using xcodebuild that I can later export as an .ipa using the new functionality added with Xcode 5.
This works perfectly fine:
xcodebuild -workspace 'MyWorkspace.xcworkspace' -scheme 'MyScheme' -configuration 'Release' -archivePath tmp.xcarchive archive
xcodebuild -exportArchive -exportFormat IPA -archivePath tmp.xcarchive -exportPath app.ipa -exportWithOriginalSigningIdentity
But as soon as I add custom build settings to the archive command:
-derivedDataPath build SYMROOT=build/build.sym DSTROOT=build/build.dst OBJROOT=build/build.obj SHARED_PRECOMPS_DIR=build/build.pch
The .xcarchive generated is empty, but there is no error.
Any ideas?
For me, this had to do with the Installation Directory Deployment Build Setting in Xcode: CMake somehow set this to "", i.e. an empty string, when it should have been "/Applications", the Xcode default. For me, setting it to anything else than "/Applications" caused the resulting archive to be empty and therefore 'malformed'.
So maybe your project somehow did not have Installation Directory set to "/Applications", either because of CMake or something else.
To set this using CMake, add this to your target properties:
set_target_properties(${MODULE} PROPERTIES
...
XCODE_ATTRIBUTE_INSTALL_PATH "/Applications"
...
)
For me this error happened when I had no space left on the drive where I tried to create the archive. But I could not tell that from the errors int he console
In my case, I was missing the .xcarchive extension at the end of my path.
xcodebuild -exportArchive -archivePath /<path_to_archive>/file.xcarchive ...
In my case the 'archivepath' directory/file path was incorrectly set in previous steps, and it was looking into a directory which did not have .xcarchive file. Worth checking manually the paths and if the archive file exists in the directory

Generating ipa from xcode command-line

Whats the best approach for generating an IPA file from command-line?
I'm on xcode 4.2 and generating the archive using:
xcodebuild -scheme AppStore clean archive
This generates the .dSYM and .app files in the build output directory, after codesigning. How should I proceed to generate the .ipa file? In other words, I'm looking for the command-line equivalent of doing the following in GUI
Organizer - Archives
Share
iOS App Store Package
Don't Re-sign
Thanks!
The missing piece is using the PackageApplication utility.
/usr/bin/xcrun -sdk iphoneos PackageApplication -v $FULL_PATH_TO_APP -o $OUTPUT_PATH
You can also pass this script options for resigning, and profile embedding. Using the --sign and --embed flags respectively.
This tool makes it trivial to build (and distribute): https://github.com/nomad/shenzhen
After Archive, you need to "Export" to desired format ie ipa:
xcodebuild -sdk iphoneos7.0 -archivePath "path to archive file" -exportPath "path_for_export" -exportFormat ipa -exportArchive -exportProvisioningProfile "provisioning_profile_to_export_with"

Resources