Incrementing Version and Build Numbers with Xcode

“How can we automate our build number in this project? Perhaps a python or AppleScript?”

I get this question a lot. I contract out my development services to companies who need Mac, iPhone, or iPad software designed and developed. Many of these companies have lots of Windows developers on board full-time and contract out their Mac work so I understand that all-things Mac are new to them.

But this question always comes up. Always.

While they’re already thinking about some elaborate scripts to automate this process, I hold up my hands and say, “It’s already covered.”

I decided to blog about it because most people don’t know the name of the tool and can’t “Google” for it without stumbling across scripts to accomplish this task.

Apple includes a command-line tool called agvtool which handles my versioning needs. It’s not perfect, but it does what it needs to do and when used in a corporate environment with a build system, it’s fantastic.

What is it? In a nut shell, it’s a very focused “Find and Replace in Files” command-line tool. It searches through your program’s Info.plist file as well as the project .pbxproj file and updates them. You can even have it commit it’s changes with version control if you’re using Subversion or CVS.

The real number that needs to be constantly updated is the build number. Normally, the marketing version only changes at the beginning of a new branch or feature set. agvtool will help you out with both tasks. First, let’s tackle getting your project setup so you can display the following string in your iPhone About screen:

Version: 1.0 (Build 1)

The agvtool refers to the “1.0” part as the “marketing version” and “1” in the Build parenthesis as the project version. To update the build number we simply issue the following command from the project’s root directory which contains the .pbxproj and Info.plist files

agvtool bump -all

This command will change all of the build numbers, or project versions in agvtool speak, to:

Version: 1.0 (Build 2)

Want to change the marketing version to 1.1?

agvtool new-marketing-version "1.1"

Now our About box says:

Version: 1.1 (Build 2)

Cool, huh? Okay, so here’s how you setup your project to take advantage of this nifty little tool. First, we have to tell Xcode that we want to use agvtool for our versioning needs. From the Project menu, select Edit Project Settings. Ensure Configuration is set to All Configurations and Show is set to All Settings. Navigate down to the Versioning section and make the following changes:

Project Versioning Settings

Lastly, we need to update the Info.plist file. You need to set two values in, your Marketing Version is the Bundle versions string, short. If you don’t have this option in your plist file, select an item in the list and click on the + off to the far right. You can then select it from the list. The Bundle version is the build number. Set this value to match the one you placed in the Project Settings option for Current Project Version.

Versioning Plist Settings

Now, whenever you’re ready to build an official release, just run:

agvtool -usesvn bump -all

The -usesvn parameter is optional. For an official build, you’ll want to commit the files that were changed by agvtool.

Then call xcodebuild.

Earlier in the article I mentioned that agvtool isn’t perfect. Here’s what I mean by that comment. For an automated build, having a command-line tool is fantastic. However, if you run agvtool while you have the project open in Xcode, you get this:

Project Has Changed. Read From Disk?

Since agvtool went and changed the .pbxproj file while you had it open in Xcode, you get this. Simply click on “Read From Disk” and you’re back in business. More of an annoyance than a show-stopper.

About the author

Terry Blanchard

I'm the Vice President of Engineering at Readdle, ex-Apple, design evangelist, drummer, and gadget junkie extraordinaire.

One thought on “Incrementing Version and Build Numbers with Xcode”

Leave a Reply

Your email address will not be published. Required fields are marked *