Automated build numbering in Xcode
Posted on May 15, 2008 at 7:52 pm by Late Night Coder
One thing I like to do in any development project is generate a build number, and I want it to be an automated process. This number represents the version of the source code that was used for the build. Coupled with source code control, this enables you track the version of the source code that corresponds to a customer’s installation of the product. In a large team with centralized builds, you typically increment the build number on every centralized build, whether they are kicked off on a time basis, or a check-in basis. For a single developer project, it’s nice to be able to increment the build number for every build you make locally. Here’s a simple way to enable automated build numbering in Xcode for a single developer project.
First, you need to create a file in the project that contains the build number. Create a file in the project called buildnumber.xcconfig with the following single line in it:
BUILD_NUMBER = 1
It’s convenient to use an .xcconfig file for this purpose, as the build number will then be available as a variable that you can use directly in the Info.plist file. In order to include this .xcconfig file in your build, go to Project > Edit Project Settings and go to the Build tab. In the bottom right corner change Based On to buildnumber, as shown below.

Next you need to add a shell script to the build process that will update this file incrementing the build number every time it is run. Find your target executable in Xcode, as shown below.

Right click on the target (ExampleBuildNumber in the example shown above) and choose Add » New Build Phase » New Run Script Build Phase. We are going to use a simple inline Perl statement to increment the build number. Fill in the dialog as follows:

Note that Output Files includes the modified file buildnumber.xcconfig and the Info.plist file. This ensures that build dependencies work correctly. For ease of copy/paste, here’s the shell script:
/usr/bin/perl -pe 's/(BUILD_NUMBER = )(\d+)/$1.($2+1)/eg' -i buildnumber.xcconfig
After you close this dialog, make sure that the new Run Script entry under your target is the first item in the build process. If it isn’t, simply drag it to the first position. Your target build phases should look something like this:

Now edit the Info.plist file in your project setting the following key values:
<key>CFBundleVersion</key>
<string>${BUILD_NUMBER}</string>
<key>CFShortVersionString</key>
<string>Version 1.0</string>
As you can see, CFBundleVersion will now contain your build number, and CFShortVersionString should contain your actual application version number.
To make use of these values you’ll want to create a method that returns a complete version string, constructed from the Info.plist file contents. For example:
- (NSString*) version
{
return [NSString stringWithFormat:@"%@ (Build %@)",
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFShortVersionString"],
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]];
}
You can either use this method directly, or place the method in a controller, and bind an NSTextField directly from your user interface to it.
Matthew Schinckel wrote:
To do it with the Mercurial revision number:
sed -E ’s/(BUILD_NUMBER = )[0-9]+[\+]?/\1′`/usr/local/bin/hg id -n`’/’ tmp_build_no
mv tmp_build_no buildnumber.xcconfig
Posted on 04-Aug-08 at 5:34 am
Matthew Schinckel wrote:
Whoops, forgot to escape my bits:
sed -E ’s/(BUILD_NUMBER = )[0-9]+[\+]?/\1′`/usr/local/bin/hg id -n`’/’ <buildnumber.xcconfig > tmp_build_no
mv tmp_build_no buildnumber.xcconfig
Posted on 04-Aug-08 at 5:35 am