I have been using a shell script as part of my Xcode build process to increment the build number within the plist file, however it's making Xcode 4.2.1 crash frequently (with an error about the target not belonging to a project; I'm guessing the changing of the plist file is confusing Xcode in some way).
The shell script did this so that the build number is only incremented by agvtool
when a file is newer than the plist file (so just building didn't increment the value):
if [ -n \"`find ProjDir -newer ProjDir/Project-Info.plist`\" ]; then agvtool -noscm next-version -all; else echo \"Version not incremented\"; fi
Is there a way to increment the build number (in the plist file, or anywhere else) that doesn't break Xcode?
EDIT: Here is my final solution, based on the suggestion of @Monolo. I created the following script in ${PROJECT_DIR}/tools
(sibling to the .xcodeproj
directory):
#!/bin/sh
if [ $# -ne 1 ]; then
echo usage: $0 plist-file
exit 1
fi
plist="$1"
dir="$(dirname "$plist")"
# Only increment the build number if source files have changed
if [ -n "$(find "$dir" \! -path "*xcuserdata*" \! -path "*.git" -newer "$plist")" ]; then
buildnum=$(/usr/libexec/Plistbuddy -c "Print CFBundleVersion" "$plist")
if [ -z "$buildnum" ]; then
echo "No build number in $plist"
exit 2
fi
buildnum=$(expr $buildnum + 1)
/usr/libexec/Plistbuddy -c "Set CFBundleVersion $buildnum" "$plist"
echo "Incremented build number to $buildnum"
else
echo "Not incrementing build number as source files have not changed"
fi
EDIT 2: I have modified the script to incorporate @Milliways suggestion.
I then invoked the script from Xcode target 'Build Phases' section:
EDIT 3: As per @massimobio's answer, you'll need to add quotes around the plist argument if it contains spaces.
EDIT 4: Just to update that my preferred method of invoking this build script is now to create a separate target and make the app target dependant upon this Bump Build Number target. This ensures that it is invoked before the app target does anything with the plist (I've noticed that it likes to process the plist at the start of the build). I've also switched to a purely python-based solution that keeps the version number in a separate file, and writes version source files, as this is more useful for cross-platform products (i.e. Visual Studio under Windows can invoke the script, and obviously cmake/make-type builds can do so also). This has the benefit that the build number is always the same even under different platforms, and it's also possible to update the Visual Studio Resource.rc
file with the current version/build as well.
Here is the python script I currently use to update Info.plist
files within Xcode project.
I tried the modified procedure and it did not work, because:-
Xcode 4.2.1 changes the xcuserdata subdirectory in .xcodeproj
git notes the previous change in Project-Info.plist
The following modification causes these to be ignored and only flags genuine changes:-
I use the last SVN revision for the build number. If you change the Info.plist in the build directory, you won't affect the source Info.plist:
Building on Wil Gieseler's solution, I had just one change I wanted to make. His solution puts the count of git commits into the build number. Useful, but still kind of a pain to find the actual commit that created that build. I didn't care too much whether the build number was monotonically increasing, and so I dropped that requirement so that I could more easily access the commit that generated a given binary.
To that end, I modified his first script to the following:
This converts the short version of the current git SHA into decimal. Hexadecimal characters don't play nicely with Apple's build number requirements, which is why I had to do this. To convert it back, you'd simply run something like this:
in bash, where
<build number>
is the build number you got from a binary. Then, just rungit checkout $SHA
, and there you go.Because this is an adaptation of Wil Gieseler's solution, as mentioned above, you'll also need the following post-build script:
which keeps your git history clean.
Here's my solution. If you're like me: terminal friendly, like ruby, like semantic versioning, try this.
Make a file named
Rakefile
which contains this:Prepare:
gem install xcodeproj versionomy
Run:
rake increment:major
orrake increment:minor
orrake increment:tiny
whenever you want.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:
I update
build number
by following method.$INFO_FILE
is the path of the plist file. And$build_number
is a new build number for this building.Generally, my
$build_number
is composed bymajor
andminor
parts. Theminor
is come from project information. So I describe how to generate themajor
part.I have 2 strategies to decide the
$build_number
.First Strategy
This strategy uses the
git tag
count to decide themajor
ofbuild number
. If there are53
tags of the project, it will return53
by following shell script.Generally, it's increasing. And it will force the developer to put a git tag before publishing.
Second Strategy
Let Jenkins CI system decide the
major
part. It has an environment variableBUILD_NUMBER
. It is increasing automatically when building on the CI system. This information is useful to trace the project history on the CI system.