Mark Struzinski
Mark Struzinski

Reputation: 33481

XCode 4.4 bundle version updates not picked up until subsequent build

I'm probably missing something simple here. I am trying to auto increment my build number in XCode 4.4 only when archiving my application (in preparation for a TestFlight deployment). I have a working shell script that runs on the target and successfully updates the info.plist file for each build. My build configuration for archiving is name 'Ad-Hoc'.

Here is the script:

if [ $CONFIGURATION == Ad-Hoc ]; then
    echo "Ad-Hoc build. Bumping build#..."
    plist=${PROJECT_DIR}/${INFOPLIST_FILE}
    buildnum=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${plist}")

    if [[ "${buildnum}" == "" ]]; then
        echo "No build number in $plist"
        exit 2
    fi

    buildnum=$(expr $buildnum + 1)
    /usr/libexec/Plistbuddy -c "Set CFBundleVersion $buildnum" "${plist}"
    echo "Bumped build number to $buildnum"
else
    echo $CONFIGURATION " build - Not bumping build number."
fi

This script updates the plist file appropriately and is reflected in XCode each time I archive. The problem is that the .ipa file that comes out of the archive process is still showing the previous build number. I have tried the following solutions with no success:

No matter what I do, when I look at the build log, I see that the info.plist file is being processed as one of the very first steps. It is always prior to my script running and updating the build number, which is, I assume, why the build number is never current in the .ipa file.

Is there a way to force the Run Script phase to run before the info.plist file is processed?

Upvotes: 4

Views: 1149

Answers (3)

sheltond
sheltond

Reputation: 1937

The reason that this happens is that by the time your "Run Script" gets run, the XCode build process has already processed the project's plist file to extract the bundle version number, etc.

You can see this (probably in more detail that you want) by going to the Log Navigator in XCode (View/Navigators/Show Log Navigator), and selecting an "Archive" build.

A detailed list of build actions should appear in your main window, and one of the things near the top should be one called Process <projectname>-Info.plist. If you expand this using the icon at the right hand side, you can see the actual build command that was run.

The way that I got around this was to update both the original plist file, and also the processed one. By doing this, you get your updated build version in the current build rather than the next one.

Here's the script that I use to do this (this is Ruby, so you would need to put "/usr/bin/ruby" in the interpreter box to use this, but the concept works the same with a shell script or any other scripting language):

def incrementBundleVersion(file)
    oldVersion = `/usr/libexec/Plistbuddy -c "print :CFBundleVersion" #{file}`.strip
    components = oldVersion.split('.')
    newBuild = components.pop.to_i + 1
    version = components.push(newBuild).join('.')
    print "Updating version: #{oldVersion} -> #{version} : #{file}\n"
    system("/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion #{version}\" #{file}")
end

incrementBundleVersion("#{ENV['PROJECT_DIR']}/#{ENV['INFOPLIST_FILE']}")
incrementBundleVersion("#{ENV['CODESIGNING_FOLDER_PATH']}/Info.plist")

Note that the processed file #{ENV['CODESIGNING_FOLDER_PATH']}/Info.plist is a binary plist file, so you won't be able to process it with simple text tools - using plistbuddy is the easiest way to handle this, and it automatically works with both text and binary plist files.

Upvotes: 1

john.k.doe
john.k.doe

Reputation: 7563

Mark (et al), I believe I've run into the same problem you are facing, and i will try to describe it in one sentence and then explain:

I think /usr/libexec/PlistBuddy, when run from inside Xcode, works on cached versions of the Info.plist data, and thus what gets finally written for execution on device or simulator is not always what you want.

I had tried writing post Copy Resource Bundle "Run Scripts" in order to change this info in a way that wouldn't cause it to change within my local git repo, only to discover that, whereas the information would work properly when the PlistBuddy commands were executed in a terminal.app window beside Xcode, if not done, the cached values would get written.

I finally resigned myself to running the version-info generation scripts prior to the Copy Bundle Resources phase and just auto-committing the changes in another Run Script, using the same tags for the git message and for the git tag that get auto-created. for the Settings.bundle/Root.plist file, rather than commit this every time, i preferred to just run a finalization script that would perform a 'git checkout -- ${PROJECT}/Resources/Settings.bundle/Root.plist' (which is where mine exists, but may not be where everyone puts their own system settings resource file).

between the checking for changes, running parts of it at install and parts of it every time, and having the finalization scripts at the end, there are 6 scripts for some targets and 7 for another …

… but the important thing to me is that it's finally properly automated … and gets around whatever PlistBuddy is doing to my plist files when processed inside of Xcode.

Upvotes: 0

chippcheg
chippcheg

Reputation: 11

in Xcode 4.4.1 I create new target and add to this target build phase "Run custom script", which update main target Plist. And also, you should add this target to dependencies for main target

Upvotes: 1

Related Questions