Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Better way of incrementing build number?

I've messed around with a lot of the answers on this question, and none of them quite satisfied me. However, I finally came up with a mixture that I really like!

We simply set the version number for the built product to the number of Git commits. This won't mess with your source control, since the script only mutates the built product.

Add this "Run Script" build phase to the end of your build phases:

if [ "${CONFIGURATION}" = "Release" ]; then
    buildNumber=$(git rev-list --count head)
    /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
fi

Set your Info.plist version in your project to whatever you want, it will never get used when building a release build. I set mine to AUTOMATED or DEVELOPMENT so it's clear when I'm running a development build.

That's it! The built app will have a constantly increasing build number. (As long as you always do your builds off the same branch.)

Why I like this method:

  • Easy
  • Doesn't pollute Git version history
  • CFBundleVersion is totally automatic
  • The pretty version number can be modified whenever I want

Other notes:

  • If you have app extensions in your project, simply set the same build script on those targets too. This will keep all the version numbers automated and in sync. The App Store requires extension versions match your main app.

I have used this glist. It works as expected. https://gist.github.com/sekati/3172554 (all credit goes to the original author)

Scripts that I modified over time.

xcode-versionString-generator.sh,

xcode-build-number-generator.sh

As these gist are helping the dev community, I made GitHub project out of it. So let's develop it well. Here is the GitHub project: https://github.com/alokc83/Xcode-build-and-version-generator

I have updated the code for both script little bit of enhancement. instead of using below grab the latest from GitHub

For Version :

# xcode-version-bump.sh
# @desc Auto-increment the version number (only) when a project is archived for export. 
# @usage
# 1. Select: your Target in Xcode
# 2. Select: Build Phases Tab
# 3. Select: Add Build Phase -> Add Run Script
# 4. Paste code below in to new "Run Script" section
# 5. Check the checkbox "Run script only when installing"
# 6. Drag the "Run Script" below "Link Binaries With Libraries"
# 7. Insure your starting version number is in SemVer format (e.g. 1.0.0)

# This splits a two-decimal version string, such as "0.45.123", allowing us to increment the third position.
VERSIONNUM=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${PROJECT_DIR}/${INFOPLIST_FILE}")
NEWSUBVERSION=`echo $VERSIONNUM | awk -F "." '{print $3}'`
NEWSUBVERSION=$(($NEWSUBVERSION + 1))
NEWVERSIONSTRING=`echo $VERSIONNUM | awk -F "." '{print $1 "." $2 ".'$NEWSUBVERSION'" }'`
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $NEWVERSIONSTRING" "${PROJECT_DIR}/${INFOPLIST_FILE}"

For build:

# xcode-build-bump.sh
# @desc Auto-increment the build number every time the project is run. 
# @usage
# 1. Select: your Target in Xcode
# 2. Select: Build Phases Tab
# 3. Select: Add Build Phase -> Add Run Script
# 4. Paste code below into new "Run Script" section
# 5. Drag the "Run Script" below "Link Binaries With Libraries"
# 6. Ensure that your starting build number is set to a whole integer and not a float (e.g. 1, not 1.0)

buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${PROJECT_DIR}/${INFOPLIST_FILE}")
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"

If I understand your question correctly, you want to modify the Project-Info.plist file, which is a part of the standard project template of Xcode?

The reason I ask this is that Project-Info.plist normally is under version control, and modifying it means that it will be marked as, well, modified.

If that is fine with you, then the following snippet will update the build number and mark the file as modified in the process, where get_build_number is some script (i.e., a placeholder in this example) to get the (possibly incremented) build number that you want to use:

#!/bin/sh

# get_build_number is a placeholder for your script to get the latest build number
build_number = `get_build_number`

/usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${build_number}" ProjDir/Project-Info.plist

PlistBuddy allows you to set any key in a plist file, not just the version number. You can create all the plist files you want, and include them in the resources if needed. They can then be read in from the bundle.

As to your need to show the version in the about pane and other places, you can also look into setting CFBundleGetInfoString and CFBundleShortVersionString.


This whole entry was extremely helpful. I used this trick but set up my script as a post-commit hook in GIT, so CFBundleVersion is incremented after every successful commit. The hook script goes in .git/hooks. A log is left in the project directory.

This meets my most basic criterion. I want to be able to pull a version from GIT and rebuild the exact build I had previously. Any increment done during the build process does not do this.

Here is my script:

#!/bin/sh
#
# post-commit
#
# This script increments the CFBundleVersion for each successful commit
#

plist="./XYZZY/XYZZY-Info.plist"
buildnum=$(/usr/libexec/Plistbuddy -c "Print CFBundleVersion" "$plist")
if [ -z "$buildnum" ]; then
    exit 1
fi
buildnumplus=$(expr $buildnum + 1)
/usr/libexec/Plistbuddy -c "Set CFBundleVersion $buildnumplus" "$plist"

echo $(date) "- Incremented CFBundleVersion to" $buildnumplus >> hookLog.txt

I don't know which way is the best, but I will post Apple's answer just in case anybody is searching for it...

According to this Apple's Q&A post:

Automating Version and Build Numbers Using agvtool

The version and build number keys respectively specify the marketing and internal versions of your application. agvtool is a command-line tool that allows you to automatically increment these numbers to the next highest number or to a specific number.

The build number identifies an unreleased or released version of your application. It is stored in your application’s Info.plist as CFBundleVersion(Bundle version).

You must complete the following steps in your Xcode project:

  1. Enable agvtool

Navigate to the Build Settings pane of your target, then update it for all your build configurations as follows:

  • Set Current Project Version to a value of your choosing.

Your Xcode project data file, project.pbxproj, includes a CURRENT_PROJECT_VERSION (Current Project Version) build setting, which specifies the current version of your project. agvtool searches project.pbxproj for CURRENT_PROJECT_VERSION. It continues running if CURRENT_PROJECT_VERSION exists and stops running, otherwise. Its value is used to update the build number.

  • Set Versioning System to Apple Generic.

By default, Xcode does not use any versioning system. Setting Versioning System to Apple Generic ensures that Xcode will include all agvtool-generated version information in your project.

Set Versioning System to Apple Generic

  1. Set up your version and build numbers

agvtool searches your application’s Info.plist for your version and build numbers. It updates them if they exist and does nothing, otherwise. Make sure that the CFBundleVersion (Bundle version) and CFBundleShortVersionString (Bundle versions string, short) keys exist in your Info.plist as seen in the image below:

Set up your version and build numbers

Quit Xcode, then navigate to the directory containing your .xcodeproj project file in the Terminal application before running any of the following commands. The .xcodeproj project file contains project.pbxproj, which is used by agvtool. (This is the part you can run in a script instead of command line.)

Updating the Version Number

To update the version number to a specific version, run

xcrun agvtool new-marketing-version <your_specific_version>

Ex: Update the version number to 2.0

xcrun agvtool new-marketing-version 2.0

Updating the Build Number

To automatically increment your build number, run

xcrun agvtool next-version -all

To set the build number of your application to a specific version, run

xcrun agvtool new-version -all <your_specific_version>

Ex: Set the build number to 2.6.9

xcrun agvtool new-version -all 2.6.9

Bonus:

To view the current version number, run

xcrun agvtool what-marketing-version

To view the current build number, run

xcrun agvtool what-version

FWIW - this is what I'm currently using to increase the build number only for release builds (which includes archiving). Works fine under Xcode 5.1.

Just copy/paste the snippet into a Run script build phase directly in Xcode:

buildnum=$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "$PRODUCT_SETTINGS_PATH")

if [ "$CONFIGURATION" = "Release" ]; then
buildnum=$((buildnum + 1))
echo "Build number updated to $buildnum"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildnum" "$PRODUCT_SETTINGS_PATH"
fi;