24

I am trying to figure out how to have the Bundle version number increment automatically in my Xcode 4 project (for ad-hoc and release builds). I found some scripts online that purport to do this but I am unsure of whether to place them in the "Pre-actions" or "Post-actions". I also am unsure what value I should place in the plist; a number that the script will then change or a variable?

All the options that I have tried thus far do not seem to work so any help would be greatly appreciated.

Below is the most recent script I was attempting to use:

conf=${CONFIGURATION}
arch=${ARCHS:0:4}
# Only increase the build number on Device and AdHoc/AppStore build
if [ $conf != "Debug" ] && [ $conf != "Release" ] && [ $arch != "i386" ]
then
buildPlist=${INFOPLIST_FILE}
buildVersion=$(/usr/libexec/PlistBuddy -c "Print CFBuildVersion" $buildPlist)
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBuildNumber" $buildPlist)
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBuildNumber $buildNumber" $buildPlist
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildVersion.$buildNumber" $buildPlist
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $buildVersion.$buildNumber" $buildPlist
fi
markdorison
  • 139,374
  • 27
  • 55
  • 71
  • Xcode environment variables are not available in pre/post-action in Xcode4 (see http://openradar.appspot.com/9111439 or http://openradar.appspot.com/9194286). So you can install latest version of Xcode. – Learner Jun 18 '11 at 08:05
  • Sorry not to mentioned that Pre-actions/Post-actions are not part of the build system. If you want to update the build number every time a new build process is kicked off, run your script from Post-action. You can also have a look into following steps (at best it might be a workaround) 1. cmd + , 2. Select "Behaviors" tab 3. Select "Build succeeds" item from left pane 3.1. Check on "Run" option from right pane and choose your script that will increase build number. This time buildNumber will increase if your build succeed. Note: preferences are applicable for all your Xcode projects. – Learner Jun 18 '11 at 08:25

9 Answers9

11

1, Set CFBundleVersion to 1.0.1 or something like x.x.x

1

2, Add build phases to run shell script autoVersion.sh

2

3, save below script named autoVersion.sh

#!/bin/sh
# Auto Increment Version Script
# set CFBundleVersion to 1.0.1 first!!!
# the perl regex splits out the last part of a build number (ie: 1.1.1) and increments it by one
# if you have a build number that is more than 3 components, add a '\.\d+' into the first part of the regex.
buildPlist=${INFOPLIST_FILE}
newVersion=`/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$buildPlist" | /usr/bin/perl -pe 's/(\d+\.\d+\.)(\d+)/$1.($2+1)/eg'`
#echo $newVersion;
/usr/libexec/PListBuddy -c "Set :CFBundleVersion $newVersion" "$buildPlist"

4, run shell: cp autoVersion.sh ~/Documents/ and chmod 777 ~/Documents/autoVersion.sh

5, Build & Enjoy it. :)

perl code from: https://gist.github.com/1436598

TONy.W
  • 1,948
  • 19
  • 10
  • 2
    thanks for nice utility! , you can actually just put it into root of project and with shell /bin/sh , call it as "$SRCROOT/autoversion.sh" (with quotes) , so the project is portable – PetrV Jul 23 '13 at 09:45
10

You may find the following post helpful:

Auto-Incrementing Build Numbers for Release Builds in Xcodefrom iPhone Development by Jeff LaMarche http://iphonedevelopment.blogspot.com/2011/07/auto-incrementing-build-numbers-for.html

brainjam
  • 18,863
  • 8
  • 57
  • 82
Sierra Alpha
  • 3,707
  • 4
  • 23
  • 36
4

The same idea as Alix's answer, but much simpler:

buildNumber=`/bin/date +%Y%m%d%H%M%S`
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"

Add this as a Run Script item on Build Phases on your Target. This has the advantage of being monotonically increasing as well.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
1

For anyone wanting to integrate version incrementing into a command line build script (perhaps for continuous integration), see the following commands:

    # cd into the project folder containing the plist
    cd /Users/waitea/iOS/E.ON/iOS/trunk/Eon

    # grab the version numbers
    major_version=$(grep -C 2 CFBundleVersion App-Info.plist | grep -o '[0-9]\+.[0-9]\+.[0-9]\+')
    major_version_min=$(echo $major_version | grep -o '[0-9]\+.[0-9]\+\.')
    minor_version=$(echo $major_version | grep -o '[0-9]\+$')

    # increment the minor version
    increment=`expr $minor_version + 1`
    incremented_whole_version="$major_version_min$increment"

    # replace the build number in the plist using perl
    /usr/bin/perl -p -i -e "s/$major_version/$incremented_whole_version/g" App-Info.plist

That will increment the rightmost number in a x.x.x style version number. Tweak the reg-ex's to alter for your convention.

Took me a while so I thought I'd share to give back to the community!

EDIT - I created a continuous integration system that'll do this for you

https://github.com/adamwaite/XcodeProject

Adam Waite
  • 19,175
  • 22
  • 126
  • 148
1

This might help you. I am using it in my projects. https://gist.github.com/alokc83/5207294

#!/bin/sh
# xcode-build-number-generator.sh
# @desc Automaticvally create build number every time using curent day, month and year
# @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. Drag the "Run Script" below "Link Binaries With Libraries"


#Credits 
# sekati@github for intial direction about automatic versioning
# http://www.codinghorror.com/blog/2007/02/whats-in-a-version-number-anyway.html (For unferstanding the Software Versoining)
#Feel free to leave comment or report issues


MONTH=`date | awk '{print $2}'`

case "$MONTH" in
  'Jan' )
         MONTHNUMBER=1
     ;;
    'Feb' )
         MONTHNUMBER=2
    ;;
    'Mar' )
    MONTHNUMBER=3
    echo "Month is $MONTHNUMBER"
    ;;
    'Apr' )
         MONTHNUMBER=4
    ;;
    'May' )
         MONTHNUMBER=5
        ;;
    'Jun' )
         MONTHNUMBER=6
        ;;
    'Jul' )
         MONTHNUMBER=7
        ;;
    'Aug' )
         MONTHNUMBER=8
        ;;
    'Sep' )
         MONTHNUMBER=9
        ;;
    'Oct' )
         MONTHNUMBER=10
        ;;
    'Nov' )
         MONTHNUMBER=11
        ;;
    'Dec' )
         MONTHNUMBER=12
        ;;
esac

DATE=`date | awk '{print $3}'`
echo "Date = $DATE"
YEAR=`date | awk '{print $6}'`
echo "Date = $YEAR"

### only uncomment section below if testing the format in terminal
#echo "BuildNumber1 = $MONTH$DATE$YEAR"
#echo "or BUILD NUMBER = $DATE$MONTH$YEAR"
#echo "or BUILD NUMBER = $MONTHNUMBER$DATE$YEAR Format is |Month Number Date Year|"
#echo "or BUILD NUMBER = $DATE$MONTHNUMBER$YEAR format is |Date MonthNumber Year|"
############################

#### Uncomment only one one style or last one will be in effect
#buildNumber=$MONTH$DATE$YEAR
#buildNumber=$DATE$MONTH$YEAR
buildNumber=$MONTHNUMBER$DATE$YEAR
#buildNumber=$DATE$MONTHNUMBER$YEAR


echo "Final Build number is $buildNumber"
## Below command write buildNumber in the property list
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"
Alok C
  • 2,787
  • 3
  • 25
  • 44
0

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;
Jay
  • 6,572
  • 3
  • 37
  • 65
0

If you're using a version system like "x.x.x" you can add this run script. It'll increase the version number (x.x.x+1) every time a new build is made:

if [ "${CONFIGURATION}" != "Debug" ]; then

VERSIONNUM=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${PROJECT_DIR}/${INFOPLIST_FILE}")

NEWSUBVERSION=`echo $VERSIONNUM | awk -F "." '{print $4}'`

NEWSUBVERSION=$(($NEWSUBVERSION + 1))

NEWVERSIONSTRING=`echo $VERSIONNUM | awk -F "." '{print $1 "." $2 "." $3 ".'$NEWSUBVERSION'" }'`

/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $NEWVERSIONSTRING" "${PROJECT_DIR}/${INFOPLIST_FILE}"

fi
rordulu
  • 412
  • 4
  • 12
0

I haven't found a great solution for Xcode 10.1. I have modified some scripts to reach the goal. And everything now works fine.

version=$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "${INFOPLIST_FILE}")
build=$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "${INFOPLIST_FILE}")
/usr/libexec/PlistBuddy -c "Set :PreferenceSpecifiers:1:DefaultValue ${version}" "${CODESIGNING_FOLDER_PATH}/Settings.bundle/Root.plist"
Sergey V.
  • 61
  • 1
  • 3
0

I've found that using tiered xcconfigs helps this problem.

Working on complex builds with apps, libraries, and SDKs you have to be able to coordinate not merely build numbers per project, but build number compatibility.

You can make a build management header that is effectively a text file with build iteration numbers (or versioning info i.e. beta, dev, rel) and import it through the xcconfig import chain per project.

At that point you can have a target build script step that will embed your build/versioning info. This is also best done by putting holding text in your plist and running PlistBuddy on your derived file/built file sections. (This way your source control changes are minimal)

If you can write a build execution script that does the necessary build number twiddling (or better yet, use a system like bamboo which creates the file for you), you can keep that separate from your code. Granted, if you need to do it and keep track, you may have to check in the changed build number to allow it to increment.

I've been able as a result of this to maintain build numbers along the line of: 2.0.3 b34 (3473) Where we have a build number and an SVN checkout build point. (Please no git hazing, I'm old school)

Pre/Post actions are more for Uber notifications or processes: Email that the build started/failed/ etc Copy the done project to the done project server.

Everything else works better as a Build Script.

(And as always: make the script phase call an external script file. DON'T push your script into the project, it's hell on source controlling the project file)

Hope this helps.

Dru Freeman
  • 1,766
  • 3
  • 19
  • 41