Create .ipa using multiple targets - ios

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.

Related

Build IPA from .APP bundle without xcworkspace

There used to be a way to build an IPA from an .APP bundle using xcrun but Apple, for some reason, has deprecated PackageApplication. I'm left only with xcodebuild, which requires an Xcode workspace file. My .APP wasn't created via xcode. It was made with Visual Studio for Mac with Xamarin. I can make an IPA by exporting an archive from the IDE but what I'm trying to do is build the IPA from the command line and sign it. The signing part is very straightforward but I don't know how to build the IPA without ZIPping it manually, adding in the embedded.mobileprovision, etc.
Is there an alternative to xcbuild PackageApplication that I can use?
I'm trying to do is build the IPA from the command line...
You can use msbuild to build/package an .ipa
/Library/Frameworks/Mono.framework/Commands/msbuild \
AStackOverflowSolution.sln \
/p:Configuration=Ad-Hoc \
/p:Platform=iPhone \
/p:BuildIpa=true
re: Building via the Command Line (On Mac)
For Windows, include the ServerAddress and ServerUser of your macOS build system
/p:ServerAddress="192.168.40.40"
/p:ServerUser="YourmacRemoteSSHuser"
re: IPA Support in Xamarin.iOS

Xamarin: Generate xcarchive from command line

Is there a possibility to directly generate a xcarchive file from the command line? So that you can generate an AppStore build with a CI tool like Jenkins?
With Xcode it seems you can, but I'm using Xamarin Studio on Mac. Anyway is this possible? Or can you manually create an xcarchive file with the app, dsym and plist?
On my build server I use the following commands to create an AppStore signed ipa file from an archive.
/Applications/Xamarin\ Studio.app/Contents/MacOS/mdtool -v build "--configuration:AppStore|iPhone" -p:RssReader.iOS Apps/RssReader.sln || exit 1
# transform the archive into a .ipa package
xcrun -sdk iphoneos PackageApplication -v "${WORKSPACE}/Apps/RssReader/iOS/RssReader.iOS/bin/iPhone/AppStore/RssReader.app" -o "${WORKSPACE}/Apps/RssReader/iOS/RssReader.iOS/bin/iPhone/AppStore/RssReader-${BUILD_NUMBER}-appstore.ipa"

Export .ipa file from Xcode project without ever opening Xcode

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}

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 not copying file from .app

I've created a signed .xcarchive file using the xcodebuild command.
Inside the .xcarchive is a .app file. Inside the .app is a file called archived-expanded-entitlements.xcent. This file is the key to my problem.
I run a different xcodebuild command that creates an .IPA file from the .xcarchive.
Creating the IPA fails because the archived-expanded-entitlements.xcent file is missing. The thing is, xcodebuild is creating a temporary directory where it copies over my .app file, and inside THAT .app file, there is no archived-expanded-entitlements.xcent file.
All the other files are in there except this one.
The commands I run are below:
This creates the xcarchive:
xcodebuild -project diplomat.xcodeproj -scheme schemeName archive -archivePath /Path/To/Archive/name.xcarchive -configuration AppStore CODE_SIGN_IDENTITY="identity" PROVISIONING_PROFILE=provProfile
This creates the IPA:
xcodebuild -exportArchive -exportFormat IPA -archivePath /Path/To/Archive/name.xcarchive -exportPath /Path/To/Archive/name.ipa
Despite specifying the location of the .xcarchive, it creates a temporary directory and doesn't include the important file.
Please note, the archived-expanded-entitlements.xcent file is created during the .xcarchive process (the first command that's run) and fails to copy into the temp directory during the second command run.
This is the exact error. Google and StackOverflow have yielded similar errors, but nothing with this actual problem.
Checking original app
+ /usr/bin/codesign --verify -vvvv /var/folders/sl/_wdkd56d5pb05snr559cmcww0000gn/T/D2133E2C-DC66-427C-A3C5-903A88DD0541- 42128-00007ED35037747A/name.app
Program /usr/bin/codesign returned 1 :
[/var/folders/sl/_wdkd56d5pb05snr559cmcww0000gn/T/D2133E2C-DC66-427C-A3C5-903A88DD0541-42128-00007ED35037747A/name.app: a sealed resource is missing or invalid
file missing:
/private/var/folders/sl/_wdkd56d5pb05snr559cmcww0000gn/T/D2133E2C-DC66-427C-A3C5-903A88DD0541-42128-00007ED35037747A/name.app/archived-expanded-entitlements.xcent
]
Codesign check fails :
/var/folders/sl/_wdkd56d5pb05snr559cmcww0000gn/T/D2133E2C-DC66-427C-A3C5-903A88DD0541-42128-00007ED35037747A/name.app: a sealed resource is missing or invalid
file missing:
/private/var/folders/sl/_wdkd56d5pb05snr559cmcww0000gn/T/D2133E2C-DC66-427C-A3C5-903A88DD0541-42128-00007ED35037747A/name.app/archived-expanded-entitlements.xcent
Done checking the original app
This is indeed a weird behaviour of xcodebuild, but you can still use the exportArchive command and specify the provisioning profile using exportProvisioningProfile:
xcodebuild -exportArchive -exportFormat IPA \
-archivePath /Path/To/Archive/name.xcarchive \
-exportPath /Path/To/Archive/name.ipa \
-exportProvisioningProfile 'PROVISIONING_PROFILE_NAME'
This will reembed the provisioning profile within the app and you won't actually need to speciify the code signing identity again, because the archive should already be signed during the archive process.
My answer would be considered a workaround, but it solved the problem. I do not know why the one file was not being copied over, but I found a way so it wasn't important.
Replace the 2nd xcodebuild command with this, which utilizes xcrun:
/usr/bin/xcrun -sdk iphoneos PackageApplication -v /Path/To/Archive/name.xcarchive/Products/Applications/name.app -o /Path/To/Archive/DiplomatStaples.ipa --sign "identity" - -embed "provProfile"
This creates an IPA using the xcarchive and then re-embeds the identity and the provisioning profile, so even though the same error as above still occurs and is printed out,the "double dip" with the code signing identity and provisioning profile makes it meaningless. I can now install the app on devices.
For inquiring minds: The reason I'm not just using xcrun in the first place is because even if I specify a prov profile and signing identity, xcrun will use the embedded profile and signing identity in the project based on the configuration (Debug, AppStore, Release, etc) that I specify. xcodebuild will actually sign with the certs I provide it.
The goal of this operation was to remove the need for provisioning profile certs that the CI system required from developer machines, enabling testing the "AppStore" configuration to be signed with AdHoc distribution certs, and enabling re-signing of the xcarchive later on with the actual App Store distribution certs.

Resources