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 would recommend the use of autorevision.
Xcode allows for a header file (which can be auto generated at build time and not in the vcs its self) to provide values that will be expanded in the info.plist at build time. You can find a walkthrough for setting this up on the autorevision website.
Autorevision has an output type geared towards these types header files to help in exactly these situations.
Heres an updated version. This works as of Xcode 9.3.1, iOS 11.
Click on 'Build Phases' from your application target, click the + icon to add a new run script, and in the box, paste this code.
Go into the Info.plist file and set the 'Bundle version' to 1, and the 'Bundle versions string, short' to 1, you should be set.
Build the project with Info.plist in view, and you should see the Bundle version (Build number) change.
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:
Navigate to the Build Settings pane of your target, then update it for all your build configurations as follows:
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 forCURRENT_PROJECT_VERSION
. It continues running ifCURRENT_PROJECT_VERSION
exists and stops running, otherwise. Its value is used to update the build number.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.
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) andCFBundleShortVersionString
(Bundle versions string, short) keys exist in your Info.plist as seen in the image below: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
Ex: Update the version number to 2.0
Updating the Build Number
To automatically increment your build number, run
To set the build number of your application to a specific version, run
Ex: Set the build number to 2.6.9
Bonus:
To view the current version number, run
To view the current build number, run
You could use Apple's generic versioning. Basically all you have to do is call
agvtool next-version -all
from within the directory that hosts your .xcproj file. For more details check out the url above.One issue with some of these solutions is that Launch Services only recognizes
fourfive major digits in the bundle version. I have a project with a build number that's in the thousands, so I wanted to use some of the less significant digits.This Perl script increments all Info.plists in the project, not just the one for the current target, so the build numbers all stay in lockstep. It also uses one patch digit and two minor digits, so build 1234 is given version 1.23.4. I use it as a pre-build behavior, so it applies to all projects I build.
The script is pretty brute-force, but it does work for me.
You may want to do this only when you archive (and upload to TF for example). Otherwise your version number might go up really quick..
In the scheme (Product / Edit Scheme / Archive / Pre-Actions) you can add a script that will be executed only when you archive.
Also, you might want to reset build number each time you increment the app version.
Last thing, if you use archive instead, you can safely disable:
As the build number will be incremented only when you archive...
EDIT: Correct what I said, pre-actions in archive happen after build (but before archiving), so build number will be increment for next archive... But you can create a new scheme and add this action in the build (pre-actions) section of this new scheme. and use this scheme when you want to create a new build