Use same CFBundleVersion and CFBundleShortVersionString in all targets
My solution is:
For CFBundleShortVersionString:
- Add a user-defined constant in your project settings
- Name it $(CF_BUNDLE_SHORT_VERSION_STRING) and set it to your desired value
- Set your version in your targets to $(CF_BUNDLE_SHORT_VERSION_STRING)
- Repeat for all targets. Done!
CFBundleVersion: you could do the same for CFBundleVersion, but somehow I wanted this value to be computed from my GIT repo commit count. I´ve done it like this:
- Add a Pre-action to your main target. You access the shown dialog via Product > Scheme > Edit Scheme
- Add a Post-action to your main target.
- Add a new Command Line Tool target named BundleVersionUpdate and one named BundleVersionRevert
- Navigate to your new BundleVersionUpdate target and add a new Run Script Build Phase
- Paste the following
\#!/bin/sh INFOPLIST="${SRCROOT}/MyApp/MyApp-Info.plist" INFOPLIST_WKAPP="${SRCROOT}/MyApp-WKApp/Info.plist" INFOPLIST_WKEXT="${SRCROOT}/MyApp-WKExt/Info.plist" PLISTCMD="Set :CFBundleVersion $(git rev-list --all|wc -l)" echo -n "$INFOPLIST" | xargs -0 /usr/libexec/PlistBuddy -c "$PLISTCMD" echo -n "$INFOPLIST_WKAPP" | xargs -0 /usr/libexec/PlistBuddy -c "$PLISTCMD" echo -n "$INFOPLIST_WKEXT" | xargs -0 /usr/libexec/PlistBuddy -c "$PLISTCMD"
- Navigate to your new BundleVersionRevert target and add a new Run Script Build Phase and paste this:
\#!/bin/sh INFOPLIST="${SRCROOT}/MyApp/MyApp-Info.plist" INFOPLIST_WKAPP="${SRCROOT}/MyApp-WKApp/Info.plist" INFOPLIST_WKEXT="${SRCROOT}/MyApp-WKExt/Info.plist" PLISTCMD="Set :CFBundleVersion SCRIPTED" echo -n "$INFOPLIST" | xargs -0 /usr/libexec/PlistBuddy -c "$PLISTCMD" echo -n "$INFOPLIST_WKAPP" | xargs -0 /usr/libexec/PlistBuddy -c "$PLISTCMD" echo -n "$INFOPLIST_WKEXT" | xargs -0 /usr/libexec/PlistBuddy -c "$PLISTCMD"
- Enjoy!
The scheme actions aren't in source control so it's better to add a build phase into your app's target. Syncing the versions across all targets can be solved with a simple script that can be modified for every target you want synced:
- Add "New Run Script Phase" in "Build Phases" for your app's target
Rename the script to something like "Sync Versions" and drag it above "Compile Sources" (NOTE: Xcode has a bug that may prevent the drag-drop to work. If so, you'll need to manually edit the .pbxproj file so the build phase goes in the right spot
Paste the following script into the shell:
INFOPLIST_MYAPP="${SRCROOT}/MyApp/MyApp-Info.plist" myAppVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$INFOPLIST_MYAPP") myAppBuild=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_MYAPP") INFOPLIST_SHAREEXT="${SRCROOT}/ShareExtension/Info.plist" /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $myAppVersion" "$INFOPLIST_SHAREEXT" /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $myAppBuild" "$INFOPLIST_SHAREEXT"
- Build your project as you normally and your share extension's version & build will stay in sync with your main target.