Automatic Build Versioning in Xcode with Subversion

For awhile, I had wanted to include the svn revision number in my iOS app, and when I came across a blog post by Daniel Jalkut from a few years ago, I thought I had found an answer. No sooner than I implemented his script, though, did I discover that Apple doesn’t allow build numbers in iOS app packages.

I still really wanted this information in my dev builds so it would be easier to keep track of what version I was working with, so wound up I made a number of modifications to the script to make it suit my needs:

* When building, if the current build style is Debug, do nothing.
* Use the INFOPLIST_PATH environment variable to dynamically generate the path to the Info.plist (so it works on iOS as well as Mac OS apps).
* Dynamically insert the revision information into the plist, rather than requiring a marker.
* Read and write out the plist to the binary format iOS apps want.

This code is free to use. Enjoy!

Installation Instructions

You’ll need to add this as a new build phase in Xcode. For your target, you’ll want to create a new “Run Script” build phase, and copy and paste the code in. You’ll want to set the shell to your perl interpreter; I use /usr/bin/perl -w.

The Code

# Xcode auto-versioning script for Subversion
# Original version by Axel Andersson
# Modifications by Daniel Jalkut <http://www.red-sweater.com/blog/23/automatic-build-sub-versioning-in-xcode>
# Further improvements by John Bafford <http://bafford.com>

use strict;

die "$0: Must be run from Xcode" unless $ENV{"BUILT_PRODUCTS_DIR"};

# Do nothing in a Debug build.
exit(0) if($ENV{'BUILD_STYLE'} ne 'Debug');

# Get the current subversion revision number and use it to set the CFBundleVersion value
my $version;
my $REV = `/usr/bin/svnversion -n ./`;
my $INFO = "$ENV{BUILT_PRODUCTS_DIR}/$ENV{INFOPLIST_PATH}";

# (Match the last group of digits and optional letter M/S); regex via Kevin "Regex Nerd" Ballard
($REV =~ m/\d+[MS]*$/) && ($version = $&);

die "$0: No Subversion revision found" unless $version;

my $match = "(<key>CFBundleVersion</key>\n\t<string>)((.*?)( \(.*\))?)(</string>)";

my $info = `plutil -convert xml1 $INFO -o -`;
$info =~ s/$match/$1$3 ($version)$6/;

open(FH, "|plutil -convert binary1 -o $INFO -") or die "$0: $INFO: $!";
print FH $info;
close(FH);

Tags: , ,

Comments are closed.