Until recently, I was at the point of believing everyone in every programming language was building applications using a shell command and a server that continuously integrated checked in code. I struggled to believe that a lot of people building iOS applications do so on their desktop, using a mouse click from within Xcode to package the application. Even people who I have worked with, who tirelessly strive toward smoother building, testing and deployment cycles, admitted their dark secret of just banging it together in Xcode with no tests. Thankfully, Apple do provide some frameworks and command line tools to help you out, and if you’ve got Xcode, you’ve already got everything you need.
Create an application
First off, let’s try and at least compile our application from the command line. We’ll use a shell script to do most of this, but I’m sure you can adapt this to your chosen build system. So let’s create an application and write our build script.
- Download and install Xcode if you don’t already have it, it’s available in the AppStore on your Lion machine.
- Open Xcode and choose: ‘Create a new Xcode project’ from the left hand menu.
- Choose a ‘Single View Application’. (Although it doesn’t really matter which one you choose).
- Enter a product name of ‘AwesomeApp’, and a company identifier of ‘totallyawesome’, don’t include a class prefix, however you do want to use ARC (automatic reference counting) and ‘Include Unit Tests’. Click next to create the app. (Feel free to change my wonderful names).
- Save it to your project folder (I have a folder called projects in my home directory).
Great, we now have something we can compile. You should be able to hit the big iTunes like Play button and launch the application in a simulator. Marvel at our application which just displays a big blank view… watch out Angry Birds here we come.
How to build it from the command line
Now we can start writing our build script. The main command line tool we’ll use is something called ‘xcodebuild’, it has the following man page:
|
1
2
3
4
5
6
7
8
9
10
11
|
xcodebuild [-project projectname] [-target targetname ...] [-configuration configurationname] [-sdk [sdkfullpath | sdkname]] [buildaction ...] [setting=value ...] [-userdefault=value ...] xcodebuild -workspace workspacename -scheme schemename [-configuration configurationname] [-sdk [sdkfullpath | sdkname]] [buildaction ...] [setting=value ...] [-userdefault=value ...] xcodebuild -version [-sdk [sdkfullpath | sdkname]] [infoitem] xcodebuild -showsdks xcodebuild -list [-project projectname | -workspace workspacename]
|
This is a pretty useful tool that can provide you all sorts of information about the project from the command line. We’ll focus on the first entry, as this is what builds the targets in your project. You can obviously run this directly in a terminal, try typing the following into a terminal:
|
1
2
|
cd <project-root> xcodebuild -target AwesomeApp -sdk iphonesimulator -configuration Debug build;
|
With any luck you should see a ‘BUILD SUCCESSFUL’ message. This has actually compiled your application using the default ‘Debug’ configuration that was set up on project creation, against the iPhoneSimulator sdk. This means the binary output will run on i386 based machines, but won’t run on an arm7 based device. The Debug configuration means the outputted binary will contain more information to allow the debugger to step through the code when it’s running. This is something we want to strip when it comes to building a production or ‘Release’ package. The good news is that by default the Xcode project is set up with another configuration called ‘Release’, this strips all the extra information required by the debugger. So try the following:
|
1
2
|
cd <project-root> xcodebuild -target AwesomeApp -sdk iphonesimulator -configuration Release build;
|
Again you should see a ‘BUILD SUCCESSFUL’ message.
For now, let’s just put this into a build script. Right click the project definition in Xcode, that’s the one with the blue appstore icon on it, and select ‘New File’. Under the other menu, select a ‘Shell Script’, and give it the creative title of ‘build.sh’. You don’t need to add it to any targets, as this will run outside of Xcode. Then put the above code into the file so it looks like this:
|
1
2
3
|
#!/bin/sh xcodebuild -target AwesomeApp -sdk iphonesimulator -configuration Release build;
|
There’s one final thing to do before we can run this as a script, and that’s add the execution flag to the script as Xcode doesn’t do this by default. So open a terminal at the project root and type the following:
Now we can run our simple build just by typing:
Breaking the build
So what happens we accidentally forget to add some code to the project, or miss a semi-colon? Let’s hope our build script will output some sort of failure message. Open the ViewController.m file and remove a semi-colon from the ‘return YES;’ at line 34. Then run the build again. You should see a ‘BUILD FAILED’ message in the terminal, but scrolling up a little, there’s some more useful information. The compiler lets you know where the error occurred and even puts a little hat at the precise point that caused the failure.
We now have the basis for a continuous integration environment, as we have a basic compile that can be run from the command line. We’ll deal with that in the next article, as there’s a whole load of fun and games to be had with that.