
Launch iOS applications from the console on the device and simulator
The article will briefly describe how to assemble the application with console commands and run it on a real device and simulator without any need to open xcode for this.
In general, it’s worth starting with the fact that my company has an ios development department of> 10 people who work on a bundle of applications. To automate the routine work, we had to deploy a CI server (so far self-written, due to special historical reasons (well, like everyone else), we plan to migrate to jenkins). I consider routine things - assembling projects, running tests (if, of course, you write them), creating ipashka for testers and for laying out in the app store. In general, I wanted all this to work by pressing a button or hook in a gita. While everything works for us at the click of a button by the developer, the prog is so far only in plans. In this article, I will only touch on the topic of compiling a project and packing it into an ipa file. The functionality for launching projects on devices on the CI server side is still under development,
What are we planning:
We have:
For the frequency of the experiment, we will use a third-party application so that dear readers can repeat what is described in the article. We use a test application for the open source Apple-based ResearchKit framework.
Before compiling the project, you must install the apple doc generator github.com/tomaz/appledoc (there is a description of how to install it).
We pass to the downloaded project. The root project is the ResearchKit framework itself, the test application itself is in a different place, we go there:
We are trying to compile the application. We collect for the simulator, since to build a project for the simulator, certificates are not needed / files are provided.
We

get the error: The build crashes because there is no ORKCatalog scheme. Since the scheme in the original project was not marked as shared, then after the “drain” from the git, xcode still does not know anything about this scheme, so that it snows it, you just need to open the project. So just open the project:
And immediately close, after our scheme appears, you can check the scheme through xcodebuild -list . We try to collect again:
After we see the long-awaited ** BUILD SUCCEEDED ** . Great, everything works.
We compile under the simulator, architectures can be i386 / x86_64. Using SYMROOT, set the path of the build result:
(Thoughts aloud: when I wrote the article, the compilation in Release mode worked, before publishing the article I checked all the steps again and the compilation stopped working in this mode, so we are collecting it in Debug, some of the last commits broke this.)
After the successful assembly, we got ORKCatalog.app file in build / Debug-iphonesimulator / . It remains to run this on the simulator. To do this, we will use the ios-sim utility github.com/phonegap/ios-sim . Using it is quite simple.
We get a list of available simulators:

From the list I selected, 'iPhone-6-Plus'. Run the application on it:
If everything is done correctly, then the simulator with the application should start (use ctrl + C to enter the input mode in the console).

Here it’s a bit more complicated, we need a mobileprovision file for development (developer) and a certificate on the machine (p12 file), and you don’t need an account in xcode. When signing / packaging applications from the console, there is no need to add an account in xcode, this helps a lot, for example, on the CI server you can only store p12 files.
We will assume that your machine has an appropriate certificate. After we generate the developer mobileprovision through developer.apple.com in your account and download it to the machine (give it the name test.mobileprovision, and the bundle id will be ru.habrahabr.test). After copying it to a directory where xcode can pick it up:
We collect the archive for the device (this is the architecture of arm64 / armv7):
Compilation will fail, since we have not yet registered our bundle id in the application and have not linked mobileprovision, the error will look like this:

We will pass the bundle id from the console + we need to register it in the Info.plist file. Also through the console we will transfer the link to our mobileprovision. We find the Plist file along the path ORKCatalog / Supporting Files / Info.plist, in which we set the value for the CFBundleIdentifier key to ru.habrahabr.test. Bundle id is passed through the key with the value of our id PRODUCT_BUNDLE_IDENTIFIER = en.habrahabr.test. We pass the link to mobileprovision through the PROVISIONIG_PROFILE key, with the UUIDs, which is registered in mobileprovision.
Get the UUID:
The value will be like 87b0df89-793a-4a0f-92bf-c5f9c35f1405 . We collect again:
As a result, we get the build / archive.xcarchive archive , which remains to be packaged in ipa. Xcode 7 introduced a new packaging method, and we will use it. Before that, create the config file options.plist with the following contents:
Trying to build ipa:
The assembly crashes, by the logs you can understand that there is something with entitlements:

By mistake it is clear that the application is signing entitlements, the values in which do not correspond to the values in our mobileprovision, namely com.apple.developer.healthkit . We are looking for a reason. We look at what entitlements the application is signed:
We get:
We see that everything is ok, except for this:
We do not have this option in mobileprovision, we need to find out where it came from:
The search gave us ORKCatalog / Supporitng Files / ORKCatalog.entitlements . We look inside:
There is only one value:
Logically, we need to reassign mobileprovision to which we need to add this value, but we are lazy and for the test it is not necessary, we just need to re-sign the application with entitlements without this value.
We have at least two options:
1. Just edit the existing entitlements (ORKCatalog / Supporitng Files / ORKCatalog.entitlements) and rebuild again (via archive).
2. Without rebuilding, we ourselves will re-sign ORKCatalog.app with the necessary entitlements.
We choose the first option as simpler. Therefore, we simply delete the lines from the file ORKCatalog / Supporitng Files / ORKCatalog.entitlements :
and rebuild the archive again:
After we create ipa:
We see the long-awaited message ** EXPORT SUCCEEDED ** . Under build / dev-ipa / an ipa file will appear, which we will install on the device. We will install on the device using ios-deploy github.com/phonegap/ios-deploy . We cling the device to the car, we get the device id through:
Deploy on the device:
Everything is the same as for the develop version, just change the link to the release mobileprovision, in the options.plist we put the app-store instead of development (for other options you can add see the xcodebuild -help help).
Without using xcode, they were able to collect ipa files for tests and for laying out in the app store. All this can be easily automated on the CI server to make life easier for developers.
PS: It is worth noting that for the process of compiling / signing applications with a complex structure, when several targets and each requires its own separate mobileprovision file (applications with extension, clocks, embedded frameworks), the above process will not work without a file.
In general, it’s worth starting with the fact that my company has an ios development department of> 10 people who work on a bundle of applications. To automate the routine work, we had to deploy a CI server (so far self-written, due to special historical reasons (well, like everyone else), we plan to migrate to jenkins). I consider routine things - assembling projects, running tests (if, of course, you write them), creating ipashka for testers and for laying out in the app store. In general, I wanted all this to work by pressing a button or hook in a gita. While everything works for us at the click of a button by the developer, the prog is so far only in plans. In this article, I will only touch on the topic of compiling a project and packing it into an ipa file. The functionality for launching projects on devices on the CI server side is still under development,
What are we planning:
- assemble the application and run on the simulator
- let's collect ipa and run it on a real device
- let's collect ipa for upload to the market
- a little bit of assembly errors
We have:
- OS X 10.10.5
- Xcode 7.1
For the frequency of the experiment, we will use a third-party application so that dear readers can repeat what is described in the article. We use a test application for the open source Apple-based ResearchKit framework.
git clone https://github.com/ResearchKit/ResearchKit.git ~/Downloads/researchkit
cd ~/Downloads/researchkit
Before compiling the project, you must install the apple doc generator github.com/tomaz/appledoc (there is a description of how to install it).
We pass to the downloaded project. The root project is the ResearchKit framework itself, the test application itself is in a different place, we go there:
cd samples/ORKCatalog/
We are trying to compile the application. We collect for the simulator, since to build a project for the simulator, certificates are not needed / files are provided.
xcodebuild -project ORKCatalog.xcodeproj -scheme ORKCatalog -arch x86_64 VALID_ARCHS=x86_64 -sdk iphonesimulator
We

get the error: The build crashes because there is no ORKCatalog scheme. Since the scheme in the original project was not marked as shared, then after the “drain” from the git, xcode still does not know anything about this scheme, so that it snows it, you just need to open the project. So just open the project:
open ORKCatalog.xcodeproj
And immediately close, after our scheme appears, you can check the scheme through xcodebuild -list . We try to collect again:
xcodebuild -project ORKCatalog.xcodeproj -scheme ORKCatalog -arch x86_64 VALID_ARCHS=x86_64 -sdk iphonesimulator
After we see the long-awaited ** BUILD SUCCEEDED ** . Great, everything works.
Run the project on the simulator
We compile under the simulator, architectures can be i386 / x86_64. Using SYMROOT, set the path of the build result:
xcodebuild -project ORKCatalog.xcodeproj -scheme ORKCatalog ARCHS='x86_64 i386' VALID_ARCHS='x86_64 i386' -sdk iphonesimulator -configuration Debug SYMROOT=$(pwd)/build build
(Thoughts aloud: when I wrote the article, the compilation in Release mode worked, before publishing the article I checked all the steps again and the compilation stopped working in this mode, so we are collecting it in Debug, some of the last commits broke this.)
After the successful assembly, we got ORKCatalog.app file in build / Debug-iphonesimulator / . It remains to run this on the simulator. To do this, we will use the ios-sim utility github.com/phonegap/ios-sim . Using it is quite simple.
We get a list of available simulators:
ios-sim showdevicetypes

From the list I selected, 'iPhone-6-Plus'. Run the application on it:
ios-sim --devicetypeid iPhone-6-Plus launch build/Debug-iphonesimulator/ORKCatalog.app
If everything is done correctly, then the simulator with the application should start (use ctrl + C to enter the input mode in the console).

Creating an ipa file and launching on a real device
Here it’s a bit more complicated, we need a mobileprovision file for development (developer) and a certificate on the machine (p12 file), and you don’t need an account in xcode. When signing / packaging applications from the console, there is no need to add an account in xcode, this helps a lot, for example, on the CI server you can only store p12 files.
We will assume that your machine has an appropriate certificate. After we generate the developer mobileprovision through developer.apple.com in your account and download it to the machine (give it the name test.mobileprovision, and the bundle id will be ru.habrahabr.test). After copying it to a directory where xcode can pick it up:
cp test.mobileprovision ~/Library/MobileDevice/Provisioning Profiles/
We collect the archive for the device (this is the architecture of arm64 / armv7):
xcodebuild -project ORKCatalog.xcodeproj -scheme ORKCatalog ARCHS='arm64 armv7' VALID_ARCHS='arm64 armv7' -sdk iphoneos -configuration Debug archive -archivePath build/archive
Compilation will fail, since we have not yet registered our bundle id in the application and have not linked mobileprovision, the error will look like this:

We will pass the bundle id from the console + we need to register it in the Info.plist file. Also through the console we will transfer the link to our mobileprovision. We find the Plist file along the path ORKCatalog / Supporting Files / Info.plist, in which we set the value for the CFBundleIdentifier key to ru.habrahabr.test. Bundle id is passed through the key with the value of our id PRODUCT_BUNDLE_IDENTIFIER = en.habrahabr.test. We pass the link to mobileprovision through the PROVISIONIG_PROFILE key, with the UUIDs, which is registered in mobileprovision.
Get the UUID:
security cms -D -i test.mobileprovision | grep -o "\w\{8\}-\w\{4\}-\w\{4\}-\w\{4\}-\w\{12\}"
The value will be like 87b0df89-793a-4a0f-92bf-c5f9c35f1405 . We collect again:
xcodebuild -project ORKCatalog.xcodeproj -scheme ORKCatalog ARCHS='arm64 armv7' VALID_ARCHS='arm64 armv7' -sdk iphoneos -configuration Debug archive -archivePath build/archive PRODUCT_BUNDLE_IDENTIFIER=ru.habrahabr.test PROVISIONING_PROFILE=87b0df89-793a-4a0f-92bf-c5f9c35f1405
As a result, we get the build / archive.xcarchive archive , which remains to be packaged in ipa. Xcode 7 introduced a new packaging method, and we will use it. Before that, create the config file options.plist with the following contents:
method development uploadSymbols
Trying to build ipa:
xcodebuild -exportArchive -exportOptionsPlist options.plist -archivePath build/archive.xcarchive -exportPath build/dev-ipa/
The assembly crashes, by the logs you can understand that there is something with entitlements:

By mistake it is clear that the application is signing entitlements, the values in which do not correspond to the values in our mobileprovision, namely com.apple.developer.healthkit . We are looking for a reason. We look at what entitlements the application is signed:
codesign -d --entitlements - build/archive.xcarchive/Products/Applications/ORKCatalog.app
We get:
application-identifier XXXXX.ru.habrahabr.test beta-reports-active com.apple.developer.healthkit com.apple.developer.team-identifier XXXXX get-task-allow
We see that everything is ok, except for this:
com.apple.developer.healthkit
We do not have this option in mobileprovision, we need to find out where it came from:
find ORKCatalog/ -name "*.entitlements" -type f
The search gave us ORKCatalog / Supporitng Files / ORKCatalog.entitlements . We look inside:
cat ORKCatalog/Supporting Files/ORKCatalog.entitlements
There is only one value:
com.apple.developer.healthkit
Logically, we need to reassign mobileprovision to which we need to add this value, but we are lazy and for the test it is not necessary, we just need to re-sign the application with entitlements without this value.
We have at least two options:
1. Just edit the existing entitlements (ORKCatalog / Supporitng Files / ORKCatalog.entitlements) and rebuild again (via archive).
2. Without rebuilding, we ourselves will re-sign ORKCatalog.app with the necessary entitlements.
We choose the first option as simpler. Therefore, we simply delete the lines from the file ORKCatalog / Supporitng Files / ORKCatalog.entitlements :
com.apple.developer.healthkit
and rebuild the archive again:
xcodebuild -project ORKCatalog.xcodeproj -scheme ORKCatalog ARCHS='arm64 armv7' VALID_ARCHS='arm64 armv7' -sdk iphoneos -configuration Debug archive -archivePath build/archive PRODUCT_BUNDLE_IDENTIFIER=ru.habrahabr.test PROVISIONING_PROFILE=87b0df89-793a-4a0f-92bf-c5f9c35f1405
After we create ipa:
xcodebuild -exportArchive -exportOptionsPlist options.plist -archivePath build/archive.xcarchive -exportPath build/dev-ipa/
We see the long-awaited message ** EXPORT SUCCEEDED ** . Under build / dev-ipa / an ipa file will appear, which we will install on the device. We will install on the device using ios-deploy github.com/phonegap/ios-deploy . We cling the device to the car, we get the device id through:
ios-deploy -c
Deploy on the device:
ios-deploy -i -b build/dev-ipa/ORKCatalog.ipa
We collect the ipa file for the market
Everything is the same as for the develop version, just change the link to the release mobileprovision, in the options.plist we put the app-store instead of development (for other options you can add see the xcodebuild -help help).
Total
Without using xcode, they were able to collect ipa files for tests and for laying out in the app store. All this can be easily automated on the CI server to make life easier for developers.
PS: It is worth noting that for the process of compiling / signing applications with a complex structure, when several targets and each requires its own separate mobileprovision file (applications with extension, clocks, embedded frameworks), the above process will not work without a file.