Use same CFBundleVersion and CFBundleShortVersionString in all targets Use same CFBundleVersion and CFBundleShortVersionString in all targets xcode xcode

Use same CFBundleVersion and CFBundleShortVersionString in all targets


My solution is:

For CFBundleShortVersionString:

  • Add a user-defined constant in your project settings

Add a user-defined constant in your **project** settings

  • Name it $(CF_BUNDLE_SHORT_VERSION_STRING) and set it to your desired value

enter image description here

  • Set your version in your targets to $(CF_BUNDLE_SHORT_VERSION_STRING)

enter image description here

  • 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

enter image description here

  • Add a Post-action to your main target.

enter image description here

  • Add a new Command Line Tool target named BundleVersionUpdate and one named BundleVersionRevert

enter image description here

  • Navigate to your new BundleVersionUpdate target and add a new Run Script Build Phase

enter image description here

  • Paste the following
\#!/bin/shINFOPLIST="${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/shINFOPLIST="${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:

  1. Add "New Run Script Phase" in "Build Phases" for your app's target

enter image description here

  1. 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

  2. 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"

enter image description here

  1. Build your project as you normally and your share extension's version & build will stay in sync with your main target.


Xcode 12

I was able to achieve keeping the target extension version and build strings in sync with the main app with the following:

  1. Add a Run Script Phase above Compile Sources
  2. Add the following to the content of the newly created Run Script:
WIDGET_EXTENSION="${SRCROOT}/MyWidget/Info.plist"/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${MARKETING_VERSION}" "$WIDGET_EXTENSION"/usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${CURRENT_PROJECT_VERSION}" "$WIDGET_EXTENSION"