<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Carpé Cocoa &#187; automation</title>
	<atom:link href="http://carpe-cocoa.com/tag/automation/feed/" rel="self" type="application/rss+xml" />
	<link>http://carpe-cocoa.com</link>
	<description>My journey into iPhone development</description>
	<lastBuildDate>Tue, 24 Nov 2009 21:03:31 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>iPhone Application Packaging</title>
		<link>http://carpe-cocoa.com/2009-05-24/iphone-application-packaging/</link>
		<comments>http://carpe-cocoa.com/2009-05-24/iphone-application-packaging/#comments</comments>
		<pubDate>Mon, 25 May 2009 03:33:02 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[iPhone Development]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[XCode]]></category>

		<guid isPermaLink="false">http://carpe-cocoa.com/?p=176</guid>
		<description><![CDATA[When developing for the iPhone it&#8217;s often necessary to build the application in a form that can be easily installed by collaborators and testers. For ease of installation, the app should be distributed as a .ipa (iPhone Application) file. Unfortunately, XCode does not include a way to do this, so I wrote a bash script [...]]]></description>
			<content:encoded><![CDATA[<p>When developing for the iPhone it&#8217;s often necessary to build the application in a form that can be easily installed by collaborators and testers. For ease of installation, the app should be distributed as a .ipa (iPhone Application) file. Unfortunately, XCode does not include a way to do this, so I wrote a bash script to automate the process.</p>
<p>Additionally, in any build that leaves the developer&#8217;s desk it is especially important to include version information so that bug reports can be traced back to the correct version of the source, and to ensure that any distributed version can be located in the version control system. I use <a title="Git - Fast Version Control" href="http://git-scm.com/" target="_blank">git</a> for source control (installed with <a title="The MacPorts Project -- Available Ports" href="http://www.macports.org/ports.php?by=name&amp;substr=git" target="_blank">MacPorts</a>), though the script should be easily adaptible to CVS or SVN.</p>
<p>The goals for this script were:</p>
<ul>
<li>Automatically tag the project with a unique build number before each build.</li>
<li>Build all supported configurations with a single command. Sometimes compiler errors or warnings are only revealed with certain preprocessor flags or optimization settings.</li>
<li>Ensure any build created for distribution is cleanly committed to version control and tagged.</li>
<li>Name tags so that they can be easily correlated to user-visible version information.</li>
</ul>
<p><span id="more-176"></span></p>
<h4>Preliminaries</h4>
<p>Before we get into <a href="#the_script">the script</a>, a bit of groundwork is needed in the XCode project.</p>
<h5>Build Configurations</h5>
<p>By default, XCode includes two configurations in a new project: Debug and Release. I add a third configuration, Distribution, created by copying the Release configuration, but signed with my distributions certificate instead of the development certificate. This allows me to test using the same build settings that will be used for the submitted app.</p>
<p>I also set a couple of preprocessor flags based on the build configuration. The Debug configuration sets <code>DEVELOPMENT_BUILD=1</code> and <code>DEBUG_BUILD=1</code>, while the Release build just sets <code>DEVELOPMENT_BUILD=1</code>. These flags are used for several purposes, including conditional logging, but in the context of this article they are used just for version string generation.</p>
<p>The versioning tool discussed in the next session also requires a build variable. Search for the <code>CURRENT_PROJECT_VERSION</code> key and set its value to <code>1</code>.</p>
<h5>Apple&#8217;s Versioning Tool</h5>
<p>First, we need to take a little side trip into Apple&#8217;s built-in versioning support. XCode includes <code>agvtool</code>, which with a bit of setup can be used to satisfy our versioning requirements. The first step is to separate the &#8220;marketing version&#8221; from the build version. Both components are stored in the Info.plist file, though a new XCode project only includes the build version key.</p>
<table border="0">
<tbody>
<tr>
<th>Field</th>
<th>Key</th>
<th>agvtool use</th>
<th>Description</th>
</tr>
<tr>
<td>Bundle Version</td>
<td><code>CFBundleVersion</code></td>
<td>(Build) Version</td>
<td>Monotonically increasing integer</td>
</tr>
<tr>
<td>Bundle versions string, short</td>
<td><code>CFBundleShortVersionString</code></td>
<td>Marketing Version</td>
<td>Published version number (e.g. 1.1)</td>
</tr>
</tbody>
</table>
<p>I set the marketing version to the version I plan to specify in iTunesConnect when the app is submitted. The build version is simply set to 1 initially and incremented with each build thereafter (this should match the <code>CURRENT_PROJECT_VERSION</code> build variable).</p>
<h5>Displaying the Version</h5>
<p>In the About view controller&#8217;s <code>viewDidLoad</code> method I include the following:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewDidLoad <span style="color: #002200;">&#123;</span>
   <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>versionString <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithFormat<span style="color: #002200;">:</span>
                        NSLocalizedString<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Version: %@%@ (%@)&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Version string format&quot;</span><span style="color: #002200;">&#41;</span>,
                        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSBundle</span> mainBundle<span style="color: #002200;">&#93;</span> objectForInfoDictionaryKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;CFBundleShortVersionString&quot;</span><span style="color: #002200;">&#93;</span>,
<span style="color: #6e371a;">#if DEBUG_BUILD</span>
                        <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot; Debug&quot;</span>,
<span style="color: #6e371a;">#elif DEVELOPMENT_BUILD</span>
                        <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot; Beta&quot;</span>,
<span style="color: #6e371a;">#else</span>
                        <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;&quot;</span>,
<span style="color: #6e371a;">#endif</span>
                        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSBundle</span> mainBundle<span style="color: #002200;">&#93;</span> objectForInfoDictionaryKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>kCFBundleVersionKey<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
   <span style="color: #002200;">&#91;</span>versionLabel setText<span style="color: #002200;">:</span>versionString<span style="color: #002200;">&#93;</span>;
   <span style="color: #11740a; font-style: italic;">// Additional initialization</span>
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>This provides enough information to determine the build and configuration from any copy of the app. Actually, the marketing version isn&#8217;t even needed, but it allows the user to compare with the information in iTunes.<br />
<a name="the_script"></a></p>
<h3><a name="the_script"></a></h3>
<p>The remainder of this article breaks down the script, section by section. You can <a href="/utils/iPhone/build/build-1.1.sh">download the script</a> (<em>updated July 14, 2009</em>) and use or adapt it to your own projects. The script is under a BSD license.</p>
<p>The description below details the <a href="/utils/iPhone/build/build-1.0.sh">1.0 version</a> of the script.</p>
<h4>Helper Functions</h4>
<p>The first section of the script defines a few helper functions.</p>
<p>The <code>die</code> function simply prints its arguments to <code>stderr</code> and exits.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">die<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;$*&quot;</span> <span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>amp;<span style="color: #000000;">2</span>
	<span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></div></div>

<p>The <code>usage</code> function prints its args (if any) followed by a usage message and exits.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">usage<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;$1&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
		<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;$@&quot;</span> <span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>amp;<span style="color: #000000;">2</span>
		<span style="color: #7a0874; font-weight: bold;">printf</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>
	<span style="color: #000000; font-weight: bold;">fi</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;usage: build [-n] [config...]&quot;</span> <span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>amp;<span style="color: #000000;">2</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;    -n : do not update build number or commit to git&quot;</span><span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>amp;<span style="color: #000000;">2</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$xcodeconfigs</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
		<span style="color: #7a0874; font-weight: bold;">printf</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>    Known configs:&quot;</span> <span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>amp;<span style="color: #000000;">2</span>
		<span style="color: #7a0874; font-weight: bold;">printf</span> <span style="color: #ff0000;">&quot; %s&quot;</span> <span style="color: #007800;">$xcodeconfigs</span> <span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>amp;<span style="color: #000000;">2</span>
		<span style="color: #7a0874; font-weight: bold;">printf</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>Default action is to build all configs<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span> <span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>amp;<span style="color: #000000;">2</span>
	<span style="color: #000000; font-weight: bold;">else</span>
		<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;This does not appear to be a valid project directory!&quot;</span> <span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>amp;<span style="color: #000000;">2</span>
	<span style="color: #000000; font-weight: bold;">fi</span>
	<span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">3</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></div></div>

<p>The usage message is:</p>
<pre>usage: build [-n] [config...]
    -n : do not update build number or commit to git

    Known configs: Debug Release Distribute

Default action is to build all configs</pre>
<h4>Defaults and Known Configurations</h4>
<p>By default, the script will run agvtool and the git operations, and build all configs in the project.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">nocommit</span>=<span style="color: #000000;">0</span>
<span style="color: #007800;">configs</span>=</pre></div></div>

<p>The list of known configurations is determined by filtering the output of <code>xcodebuild -list</code> with <code>sed</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># all known configurations</span>
<span style="color: #007800;">xcodeconfigs</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>xcodebuild <span style="color: #660033;">-list</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'
		/Build Configurations:/,/^[[:space:]]*$/	!d
		/Build Configurations/				d
		/^[[:space:]]*$/				d
		s/[[:space:]]*\([^[:space:]]*\).*/\1/
	'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<p>The output of <code>xcodebuild -list</code> looks like:</p>
<pre>$ xcodebuild -list
Information about project "SpinSlide":
    Targets:
        SpinSlide (Active)

    Build Configurations:
        Debug (Active)
        Release
        Distribute

    If no build configuration is specified "Release" is used.</pre>
<p>The four-line <code>sed</code> script first deletes all lines except those between <code>Build Configurations:</code> and the first blank line. The second and third lines delete the <code>Bould Configurations</code> line and the blank line, respectively. Finally, each line is replaced by just the first word on that line.</p>
<p>Next the script checks for an empty list of configurations, which can occur if there is no project bundle in the current directory.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$xcodeconfigs</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #666666; font-style: italic;"># no project bundle?</span>
	usage;
<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<h4>Argument Processing</h4>
<p>Command line arguments are processed in a loop. The only supported flag is &#8216;<code>-n</code>&#8216;, which suppresses <code>avgtool</code> and <code>git</code> operations. All non-flag arguments are assumed to be build configuration names, and are checked against the list of known configurations generated in the last section before being added to the list of configurations to build.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">while</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;$*&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">do</span>
	<span style="color: #000000; font-weight: bold;">case</span> <span style="color: #ff0000;">&quot;$1&quot;</span> <span style="color: #000000; font-weight: bold;">in</span>
		-n<span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #007800;">nocommit</span>=<span style="color: #000000;">1</span> ; <span style="color: #7a0874; font-weight: bold;">shift</span> <span style="color: #000000; font-weight: bold;">;;</span>
		-<span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> usage <span style="color: #000000; font-weight: bold;">;;</span>
		<span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$xcodeconfigs</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-wq</span> <span style="color: #ff0000;">&quot;$1&quot;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
				<span style="color: #007800;">configs</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$configs</span> $1&quot;</span>; <span style="color: #7a0874; font-weight: bold;">shift</span>
			<span style="color: #000000; font-weight: bold;">else</span>
				usage <span style="color: #ff0000;">&quot;Invalid config '$1'&quot;</span>
			<span style="color: #000000; font-weight: bold;">fi</span>
			<span style="color: #000000; font-weight: bold;">;;</span>
	<span style="color: #000000; font-weight: bold;">esac</span>
<span style="color: #000000; font-weight: bold;">done</span></pre></div></div>

<p>If no configurations were specified on the command line, all known configurations are built.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># default to building all configs</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$configs</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #007800;">configs</span>=<span style="color: #007800;">$xcodeconfigs</span>
<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<h4>Check for Modified Files</h4>
<p>The next step is to check for modified files. If modified files exist and <code>-n</code> was not specified, the script will exit with an error. If <code>-n</code> was specified the script continues after setting the <code>isdirty</code> flag.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #000000; font-weight: bold;">!</span> git status <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-q</span> <span style="color: #ff0000;">'nothing to commit (working directory clean)'</span> ; <span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$nocommit</span>&quot;</span> <span style="color: #660033;">-eq</span> <span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
		<span style="color: #666666; font-style: italic;"># if committing the directory must be clean at first</span>
		git status
		die <span style="color: #ff0000;">&quot;directory is dirty&quot;</span>
	<span style="color: #000000; font-weight: bold;">else</span>
		<span style="color: #666666; font-style: italic;"># development build, just remember that it was dirty</span>
		<span style="color: #007800;">isdirty</span>=<span style="color: #000000;">1</span>
	<span style="color: #000000; font-weight: bold;">fi</span>
<span style="color: #000000; font-weight: bold;">else</span>
	<span style="color: #007800;">isdirty</span>=<span style="color: #000000;">0</span>
<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<p>This step is <code>git</code>-specific, and must be adapted if you are using a different VCS.</p>
<h4>Versioning</h4>
<p>The next step handles all of the versioning and source control operations.</p>
<p>The steps required depend on the command line options used.</p>
<h5>Tagged Builds</h5>
<p>First, we handle the case where the <code>-n</code> flag was not specified. The first step is to use <code>agvtool</code> to determine the marketing version. This will not be changed when the build number is incremented. Checking the marketing version first lets us verify that the project is set up properly before making changes.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$nocommit</span>&quot;</span> <span style="color: #660033;">-eq</span> <span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #666666; font-style: italic;"># read out the marketing version</span>
	<span style="color: #666666; font-style: italic;"># do this separate from the cut so we can check the exit code</span>
	<span style="color: #007800;">mvers</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>agvtool mvers -terse<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$?</span> <span style="color: #660033;">-ne</span> <span style="color: #000000;">0</span> <span style="color: #660033;">-o</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$mvers</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
		die <span style="color: #ff0000;">&quot;No marketing version found&quot;</span>
	<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$mvers</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-q</span> = ; <span style="color: #000000; font-weight: bold;">then</span>
		<span style="color: #007800;">mvers</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$mvers</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">cut</span> <span style="color: #660033;">-f</span> <span style="color: #000000;">2</span> <span style="color: #660033;">-d</span> =<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<p>The output of <code>agvtool</code> looks like:</p>
<pre>"SpinSlide.xcodeproj/../Info.plist"=1.0</pre>
<p>The <code>cut</code> command is used to extract the field after the <code>=</code> sign.</p>
<p>After this point, the environment has been fully verified, so we can go ahead and increment the build version.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">	<span style="color: #666666; font-style: italic;"># going to commit, bump the version number</span>
	agvtool bump <span style="color: #660033;">-all</span></pre></div></div>

<p>Now we extract the (newly incremented) build version&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">	<span style="color: #007800;">bvers</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>agvtool vers -terse<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$?</span> <span style="color: #660033;">-ne</span> <span style="color: #000000;">0</span> <span style="color: #660033;">-o</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$bvers</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
		die <span style="color: #ff0000;">&quot;No build version found&quot;</span>
	<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<p>&#8230; and combine the marketing version and build numbers into a human-readable string and a tag identifier, which has the spaces replace by underscores.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">	<span style="color: #666666; font-style: italic;"># read out the build version, must exist if the marketing version does</span>
	<span style="color: #007800;">fullvers</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$mvers</span> build <span style="color: #007800;">$bvers</span>&quot;</span>
	<span style="color: #007800;">tag</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$fullvers</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">tr</span> <span style="color: #ff0000;">' '</span> _<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<p>Finally, we commit the changed .plist and tag the new version.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">	<span style="color: #666666; font-style: italic;"># commit the changed version and tag it</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Committing &quot;</span><span style="color: #007800;">$fullvers</span><span style="color: #ff0000;">&quot; with tag <span style="color: #007800;">$tag</span>&quot;</span>
	git ci <span style="color: #660033;">-a</span> <span style="color: #660033;">-m</span> <span style="color: #ff0000;">&quot;Set build version '<span style="color: #007800;">$fullvers</span>'&quot;</span> <span style="color: #660033;">-n</span> <span style="color: #000000; font-weight: bold;">||</span> die <span style="color: #ff0000;">'commit failed'</span>
	git tag <span style="color: #ff0000;">&quot;<span style="color: #007800;">$tag</span>&quot;</span> <span style="color: #660033;">-m</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$fullvers</span>&quot;</span></pre></div></div>

<h5>Untagged Builds</h5>
<p>Untagged builds are much simpler. The SHA1 of the current version is used as the tag. If the source directory is dirty, the current date and time is added to make a unique identifier.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">else</span>
	<span style="color: #666666; font-style: italic;"># not committing, use the SHA1 as the version</span>
	<span style="color: #007800;">fullvers</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>git rev-parse HEAD <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null<span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># if it's dirty, append the date, time, and timezone</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$isdirty</span>&quot;</span> <span style="color: #660033;">-ne</span> <span style="color: #000000;">0</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
		<span style="color: #007800;">fullvers</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$fullvers</span>+ <span style="color: #007800;">$(date +%F\ %T\ %Z)</span>&quot;</span>
	<span style="color: #000000; font-weight: bold;">fi</span>
<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<h4>Build Prep</h4>
<p>To ensure the build matches the source, we delete the <code>build</code> directory and the <code>Payload</code> directory (the former is used by XCode, the latter by this script).</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># clean up old builds so that everything is built from scratch</span>
<span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #660033;">-rf</span> build
<span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #660033;">-rf</span> Payload
<span style="color: #007800;">all</span>=</pre></div></div>

<h4>Build and Package</h4>
<p>Next we loop over the requested configurations, building and packaging each one.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># build and package each requested config</span>
<span style="color: #000000; font-weight: bold;">for</span> config <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #007800;">$configs</span> ; <span style="color: #000000; font-weight: bold;">do</span></pre></div></div>

<p>The build is performed with the <code>xcodebuild</code> utility, supplied with XCode. A failed build stops the script.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">	xcodebuild <span style="color: #660033;">-alltargets</span> <span style="color: #660033;">-parallelizeTargets</span> <span style="color: #660033;">-configuration</span> <span style="color: #007800;">$config</span> build <span style="color: #000000; font-weight: bold;">||</span> die <span style="color: #ff0000;">&quot;Build failed&quot;</span></pre></div></div>

<p>Build output is stored in a tree named for the build type (tagged or untagged), version, and XCode build configuration:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">	<span style="color: #666666; font-style: italic;"># packaged output goes in Releases if tagged, Development otherwise</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$nocommit</span>&quot;</span> <span style="color: #660033;">-eq</span> <span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
		<span style="color: #007800;">basedir</span>=Releases
	<span style="color: #000000; font-weight: bold;">else</span>
		<span style="color: #007800;">basedir</span>=Development
	<span style="color: #000000; font-weight: bold;">fi</span>
	<span style="color: #007800;">releasedir</span>=<span style="color: #007800;">$basedir</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$config</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #ff0000;">&quot;<span style="color: #007800;">$fullvers</span>&quot;</span>
	<span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #660033;">-p</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$releasedir</span>&quot;</span></pre></div></div>

<p>Each build target is then packaged, one at a time.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">	<span style="color: #666666; font-style: italic;"># Package each app</span>
	<span style="color: #000000; font-weight: bold;">for</span> app <span style="color: #000000; font-weight: bold;">in</span> build<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$config</span>-iphoneos<span style="color: #000000; font-weight: bold;">/*</span>.app ; <span style="color: #000000; font-weight: bold;">do</span>
		<span style="color: #007800;"><span style="color: #c20cb9; font-weight: bold;">basename</span></span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$(basename &quot;$app&quot; .app)</span>&quot;</span></pre></div></div>

<p>The application bundle is copied into a directory called <code>Payload/Payload</code>. The first directory name isn&#8217;t significant, but the second is important to make a working <code>.ipa</code> file.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">		<span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #660033;">-p</span> Payload<span style="color: #000000; font-weight: bold;">/</span>Payload
		<span style="color: #c20cb9; font-weight: bold;">cp</span> <span style="color: #660033;">-Rp</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$app</span>&quot;</span> Payload<span style="color: #000000; font-weight: bold;">/</span>Payload</pre></div></div>

<p>To have an icon in iTunes, the package must include a 512&#215;512 PNG or JPEG named <code>iTunesArtwork</code> at the root. The following code supports per-project default artwork as well as app-specific artwork (if there are multiple apps in a single project).</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">		<span style="color: #666666; font-style: italic;"># Get app-specific iTunes artwork or project-specific artwork</span>
		<span style="color: #666666; font-style: italic;"># if available</span>
		<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$basename</span>&quot;</span>.iTunesArtwork <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
			<span style="color: #c20cb9; font-weight: bold;">cp</span> <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$basename</span>&quot;</span>.iTunesArtwork Payload<span style="color: #000000; font-weight: bold;">/</span>iTunesArtwork
		<span style="color: #000000; font-weight: bold;">elif</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-f</span> iTunesArtwork <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
			<span style="color: #c20cb9; font-weight: bold;">cp</span> <span style="color: #660033;">-f</span> iTunesArtwork Payload<span style="color: #000000; font-weight: bold;">/</span>iTunesArtwork
		<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<p>A <code>.ipa</code> file is just a <code>.zip</code> file with a particular content format. When building for distribution through the AppStore, the <code>.zip</code> extension is required. Otherwise the <code>.ipa</code> extension is used.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">		<span style="color: #666666; font-style: italic;"># Distribution builds have a .zip extension, development</span>
		<span style="color: #666666; font-style: italic;"># builds have a .ipa extension</span>
		<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$config</span>&quot;</span> <span style="color: #660033;">-eq</span> <span style="color: #ff0000;">&quot;Distribute&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
			<span style="color: #007800;">ext</span>=<span style="color: #c20cb9; font-weight: bold;">zip</span>
		<span style="color: #000000; font-weight: bold;">else</span>
			<span style="color: #007800;">ext</span>=ipa
		<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<p>Next we use <code>ditto</code> to zip the contents, then delete the temp directory.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">		<span style="color: #666666; font-style: italic;"># zip the Payload directory then delete it</span>
		<span style="color: #007800;">output</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$releasedir</span>/<span style="color: #007800;">$basename</span>.<span style="color: #007800;">$ext</span>&quot;</span>
		ditto <span style="color: #660033;">-c</span> <span style="color: #660033;">-k</span> Payload <span style="color: #ff0000;">&quot;<span style="color: #007800;">$output</span>&quot;</span> <span style="color: #000000; font-weight: bold;">||</span> die <span style="color: #ff0000;">&quot;Failed to compress&quot;</span>
		<span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #660033;">-rf</span> Payload</pre></div></div>

<p>We remember the name of the generated file to display at the end of the script.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">		<span style="color: #666666; font-style: italic;"># add to the list of output files</span>
		<span style="color: #007800;">all</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${all:+$(printf &quot;%s\n&quot; &quot;$all&quot;)}</span><span style="color: #007800;">$(printf &quot;\t%s&quot; &quot;$output&quot;)</span>&quot;</span></pre></div></div>

<p>XCode supports splitting the debug symbols from the app. If this option is enabled (as it should be for Release and Distribution builds) we save the debug symbols with the app:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">		<span style="color: #666666; font-style: italic;"># save debug symbols (if available) with the app</span>
		<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$app</span>.dSYM&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
			<span style="color: #007800;">output</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$releasedir</span>/<span style="color: #007800;">$basename</span>.dSYM.zip&quot;</span>
			ditto <span style="color: #660033;">-c</span> <span style="color: #660033;">-k</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$app</span>.dSYM&quot;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$output</span>&quot;</span> <span style="color: #000000; font-weight: bold;">||</span> die <span style="color: #ff0000;">&quot;Failed to compress debug info&quot;</span>
			<span style="color: #007800;">all</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$(printf &quot;%s\n&quot; &quot;$all&quot;)</span><span style="color: #007800;">$(printf &quot;\t%s&quot; &quot;$output&quot;)</span>&quot;</span>
		<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<p>Finally, we update a symlink to point to the latest version.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">		<span style="color: #666666; font-style: italic;"># update a symlink to the latest version</span>
		<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #007800;">$basedir</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$config</span> ; <span style="color: #c20cb9; font-weight: bold;">ln</span> <span style="color: #660033;">-sf</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$fullvers</span>/<span style="color: #007800;">$basename</span>.<span style="color: #007800;">$ext</span>&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">done</span>
<span style="color: #000000; font-weight: bold;">done</span></pre></div></div>

<h4>Report Results</h4>
<p>Once all the builds have completed and been packaged, a build summary is displayed to the user.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># report the generated files</span>
<span style="color: #7a0874; font-weight: bold;">printf</span> <span style="color: #ff0000;">&quot;Created: <span style="color: #007800;">$all</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://carpe-cocoa.com/2009-05-24/iphone-application-packaging/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

