Reputation: 119108
Until Xcode 11, I used a script that reads the current app version (for the AppStore) and help me change the LaunchScreen since we can't use swift for that.
sourceFilePath="$PROJECT_DIR/$PROJECT_NAME/App/Base.lproj/LaunchScreen.storyboard"
versionNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$INFOPLIST_FILE")
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
sed -i .bak -e "/userLabel=\"APP_VERSION_LABEL\"/s/text=\"[^\"]*\"/text=\"v$versionNumber\"/" "$PROJECT_DIR/$PROJECT_NAME/App/Base.lproj/LaunchScreen.storyboard"
But in Xcode 11 there is a new section inside the project's build settings called Versioning
And CFBundleShortVersionString
automatically changed to $(MARKETING_VERSION)
. Xcode automatically handles that and I don't want to change it manually to an static number and let Xcode do it's work.
So the question is how can I access this new MARKETING_VERSION
and set it to my launchScreen label using run script?
Upvotes: 54
Views: 30952
Reputation: 2960
Xcode 11-15
In terminal or bash script in your project you can use:
App version
xcodebuild -showBuildSettings | grep MARKETING_VERSION | tr -d 'MARKETING_VERSION =' // will be displayed 1.1.6
Build version
xcodebuild -showBuildSettings | grep CURRENT_PROJECT_VERSION | tr -d 'CURRENT_PROJECT_VERSION =' // will be displayed 7
Or (don't forget to change YouProjectName to your project name):
App version
cat YouProjectName.xcodeproj/project.pbxproj | grep -m1 'MARKETING_VERSION' | cut -d'=' -f2 | tr -d ';' | tr -d ' '
Build version
cat YouProjectName.xcodeproj/project.pbxproj | grep -m1 'CURRENT_PROJECT_VERSION' | cut -d'=' -f2 | tr -d ';' | tr -d ' '
Or slower method (Thx Joshua Kaden):
App version
xcodebuild -project YouProjectName.xcodeproj -showBuildSettings | grep "MARKETING_VERSION" | sed 's/[ ]*MARKETING_VERSION = //'
Build version
xcodebuild -project YouProjectName.xcodeproj -showBuildSettings | grep "CURRENT_PROJECT_VERSION" | sed 's/[ ]*CURRENT_PROJECT_VERSION = //'
Upvotes: 53
Reputation: 626
You can use jq
because xcodebuild
has -json
option.
❯ xcodebuild -showBuildSettings -json 2>/dev/null | jq '.[0].buildSettings.MARKETING_VERSION'
"0.1.0"
❯ xcodebuild -showBuildSettings -json 2>/dev/null | jq '.[0].buildSettings.CURRENT_PROJECT_VERSION'
"1"
jq -r
prints raw value:
❯ xcodebuild -showBuildSettings -json 2>/dev/null | jq -r '.[0].buildSettings.MARKETING_VERSION'
0.1.0
❯ xcodebuild -showBuildSettings -json 2>/dev/null | jq -r '.[0].buildSettings.CURRENT_PROJECT_VERSION'
1
Upvotes: 0
Reputation: 12695
Most voted answers by now show how to extract the value through sed
and further tools in the chain. Thought to provide a (simpler?) solution just through awk
.
Just to give a little bit of context, following one-liner shows the culprit row:
xcodebuild -project MyProj/MyProj.xcodeproj -showBuildSettings | awk '/MARKETING_VERSION/ { print }'
# output
MARKETING_VERSION = 0.0.1
Default awk field separator should be the space, and so it's just a matter of extracting the third field (MARKETING_VERSION is first, the equal sign is second):
xcodebuild -project MyProj/MyProj.xcodeproj -showBuildSettings | awk '/MARKETING_VERSION/ { print $3 }'
# output
0.0.1
HTH
Upvotes: 3
Reputation: 451
If your project is set up to use Apple Generic Versioning then you may use this command:
agvtool what-marketing-version -terse1
More info on how to set up AGV can be found here.
Upvotes: 1
Reputation: 1805
I miss here a solution for multiple targets and configurations:
xcodebuild -target <target> -configuration <configuaration> -showBuildSettings | grep -i 'MARKETING_VERSION' | sed 's/[ ]*MARKETING_VERSION = //'
Upvotes: 6
Reputation: 565
How about saving a value to CURRENT_PROJECT_VERSION ? did anyone managed to do this?
I can get the value like
buildNumber=$CURRENT_PROJECT_VERSION
but this doesn't work:
CURRENT_PROJECT_VERSION="" or $CURRENT_PROJECT_VERSION=""
In my case I'm trying to set it to ""
This line doesn't set the CURRENT_PROJECT_VERSION field too
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$appInfoPlist"
Upvotes: 1
Reputation: 49
If you use Bitrise then the following script will save you:
envman add --key=APP_VERSION_NO --value=`sed -n '/MARKETING_VERSION/{s/MARKETING_VERSION = //;s/;//;s/^[[:space:]]*//;p;q;}' ./${PATH_TO_YOUR_PROJECT_XCODEPROJ_FILE}/project.pbxproj`
Extract the Build Number from xcodeproj file only if you use Apple Generic versioning system otherwise extract the Build Number from the XCode project info.plist file.
Note: The following script extracts the Build Number from the xcodeproj file.
envman add --key=APP_BUILD_NO --value=`sed -n '/CURRENT_PROJECT_VERSION/{s/CURRENT_PROJECT_VERSION = //;s/;//;s/^[[:space:]]*//;p;q;}' ./${PATH_TO_YOUR_PROJECT_XCODEPROJ_FILE}/project.pbxproj`
envman run bash -c 'echo "App Version: $APP_VERSION_NO"'
envman run bash -c 'echo "App Build No: $APP_BUILD_NO"'
Thanks to the answer by @babac
Upvotes: 3
Reputation: 1625
I'm developing a framework with this scenario:
The key is that in XCode 11 the aggregate framework script doesn't get run environment variables for other workspace targets so it's impossible to read the $MARKETING_VERSION from my framework target.
So the solution that works for me has been use PlistBuddy specifying the Info.plist result of the framework target build in this way:
FAT_FRAMEWORK="${SRCROOT}/build/${FRAMEWORK_NAME}.framework"
BUILD_NUMBER=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${FAT_FRAMEWORK}/Info.plist")
VERSION_NUMBER=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${FAT_FRAMEWORK}/Info.plist")
Upvotes: 0
Reputation: 931
Couldn't find right answer on the internet, so I started digging.
Version and build numbers are displayed in ./PROJECTNAME.xcodeproj/project.pbxproj
as MARKETING VERSION (MV) and CURRENT PROJECT VERSION (CPV).
I used sed to get the numbers. It finds first occurrence of MV or CPV, removes everything except the number, and returns result. In order for this to work, you need to do 2 things:
Commands:
version_number=`sed -n '/MARKETING_VERSION/{s/MARKETING_VERSION = //;s/;//;s/^[[:space:]]*//;p;q;}' ./PROJECTNAME.xcodeproj/project.pbxproj`
build_number=`sed -n '/CURRENT_PROJECT_VERSION/{s/CURRENT_PROJECT_VERSION = //;s/;//;s/^[[:space:]]*//;p;q;}' ./PROJECTNAME.xcodeproj/project.pbxproj`
Result:
Note: If you have more targets in your workspace with different version and build numbers, this might or might not work for you, because it stops on first occurrence. In that case, good luck :)
Upvotes: 20
Reputation: 6867
I had similar issue and made it work by displaying MARKETING_VERSION itself:
version="$MARKETING_VERSION"
version+=" ("
version+=`/usr/libexec/PlistBuddy -c "Print CFBundleVersion" $SRCROOT/MyApp/Info.plist`
version+=")"
/usr/libexec/PlistBuddy "$SRCROOT/MyApp/Settings.bundle/Root.plist" -c "set PreferenceSpecifiers:1:DefaultValue $version"
Upvotes: 0
Reputation: 1201
For Node.js: there is xcode package. Example of usage:
const xcode = require('xcode');
const project = xcode.project('ios/PROJECT_NAME.xcodeproj/project.pbxproj').parse(() => {
const config = project.pbxXCBuildConfigurationSection();
const releaseScheme = Object.keys(config).find(key => config[key].name === 'Release');
const version = config[releaseScheme].buildSettings.MARKETING_VERSION;
});
Previously I used the plist
package, but with latest xCode changes it became outdated, since I'm not able to extract a version from Info.plist
for React Native projects.
Upvotes: 0
Reputation: 320
You can use it like any other project variable:
sourceFilePath="$PROJECT_DIR/$PROJECT_NAME/App/Base.lproj/LaunchScreen.storyboard"
versionNumber="$MARKETING_VERSION"
buildNumber="$CURRENT_PROJECT_VERSION"
sed -i .bak -e "/userLabel=\"APP_VERSION_LABEL\"/s/text=\"[^\"]*\"/text=\"v$versionNumber\"/" "$PROJECT_DIR/$PROJECT_NAME/App/Base.lproj/LaunchScreen.storyboard"
Upvotes: 19