Run a shell script before build in Xcode
Asked Answered
N

2

11

I need to adjust my build and version number for my project before build/archiving.
I tried multiple things, but so far to no avail.

I added a target with the script to update the numbers and added that as first dependency to my main target. But because I have multiple dependencies as I have extensions in my app and all dependencies are executed by Xcode in parallel (or at least in random order) this does not work.

I added a pre-action to my scheme with the same result. Xcode is not waiting for my pre-action to complete before continuing with the build (I added a sleep 100 to test).

As I'm altering build numbers it is crucial that the script can complete before anything else is started, but there is also one more side-effect: The build even stops due to the fact that the plist files have been altered while building the related target.

What makes it more difficult is, that I would like to use agvtools to set my version & build number. This obviously starts background processes that are out of my control to alter the plists.

Disclaimer: I have searched for other answers, didn't help.

Nafis answered 4/4, 2015 at 20:10 Comment(0)
N
9

agvtools just does not work in an Xcode build. It will always stop the build. What works fine is PlistBuddy, although the setup is not as nice and neat.

I added a Pre-Action to the build in my main scheme to call a new target in my project:

xcodebuild -project "${SRCROOT}/MAIN_APP.xcodeproj" -scheme BuildNumberPreProcess

In the target BuildNumberPreProcess I have a Run Script:

VERSION=$(head -n 1 version.txt)
BUILD=`git rev-list $(git rev-parse --abbrev-ref HEAD) | wc -l | awk '{ print $1 }'`

echo "${VERSION} (${BUILD})"

SCRIPT="${SRCROOT}/CLIENT/Supporting Files/set-version-in-plist.sh"

"${SCRIPT}" "${SRCROOT}/MAIN_APP/Supporting Files/Info.plist" ${VERSION} ${BUILD}
"${SCRIPT}" "${SRCROOT}/EXTENSION/Info.plist" ${VERSION} ${BUILD}
...

set-version-in-plist.h:

#!/bin/sh

#  set-version-in-plist.sh
#
# usage:
# set-version-in-plist LIST VERSION BUILD
# LIST:      Info.plist path & name
# VERSION:   version number xxx.xxx.xxx
# BUILD:     build number xxxxx
#

# Location of PlistBuddy
PLISTBUDDY="/usr/libexec/PlistBuddy"

echo "$1: $2 ($3)"

${PLISTBUDDY} -c "Set :CFBundleShortVersionString $2" "$1";
${PLISTBUDDY} -c "Set :CFBundleVersion $3" "$1";
Nafis answered 8/4, 2015 at 13:25 Comment(5)
Nice solution! Only downside is: your Info.plist-files are 'dirty' after running this, which means you´re constantly checking in the updated files to your GIT repo. In the perfect world, it would be better to leave the source files untouched and just modify the plists in the build results.Legate
I'm reverting the change in a post build script ;)Nafis
Now I´m running into another problem: My BuildNumberPreProcess-target doesn´t recognize the Build Configuration which is set by the MAIN_APP-target. When I evaluate $(CONFIGURATION), it is always set to 'Debug'. Did you run into this problem, too?Legate
Yes. As mentioned above I trigger the target from my Scheme in Build > Pre-actions like this: xcodebuild -project "${SRCROOT}/My.xcodeproj" -scheme BuildNumberPreProcess This way all settings are taken from the main target.Nafis
Not exactly, but I got it working. xcodebuild -project "${SRCROOT}/MAIN_APP.xcodeproj" -configuration ${CONFIGURATION} -scheme BuildNumberPreProcess is the way to go. That way ${CONFIGURATION} is taken from the MAIN_APP.Legate
T
2

Xcode has command line tools for build/archiving: https://developer.apple.com/library/ios/technotes/tn2339/_index.html

So, you can write shell script that at first runs your script for adjusting build/version number and then runs xcode build/archive as command line tool.

Tracietracing answered 4/4, 2015 at 20:25 Comment(1)
nice try, but that does break other things (Organizer will not be aware of the new version, I can not see formatted logs, ...)Nafis

© 2022 - 2025 — McMap. All rights reserved.