I'm writing a bash script to archive and export my project so I can send it to iTunes Connect. However, the documentation from the command line is a little confusing. I'm trying to figure out if there's a way to pass a parameter to the xcodebuild command that would set the version number and build number for that archive (similar to how you pass -scheme MyScheme when calling xcodebuild). Anyone done something like this before?
Thanks!
You can use this:
/usr/libexec/Plistbuddy -c "Set CFBundleVersion $SBUILD_NUMBER" "$PLIST"
/usr/libexec/Plistbuddy -c "Set CFBundleShortVersionString $BUNDLE_SHORT_VERSION" "$PLIST"
with PLIST is the path to your Info.plist
Related
I need to automate the build number and version for both iOS and Android.
For iOS there is agvtool and fastlane too.
Is there an alternate tool which will work seamlessly across iOS, Android
So, I've been using a script in my build phases to increment the build number, but it only works if the value is specified in the Info.plist file, and not referenced in the Info.plist file. Given this was part of the 0.5x.x -> 0.6x.x change for React Native, it does mean I'm running in an old way.
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${PROJECT_DIR}/${INFOPLIST_FILE}" | sed -E 's/^([0-9]+).*/\1/')
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"
Since Xcode 11 had change Version to $(MARKETING_VERSION) & Build to $(CURRENT_PROJECT_VERSION)
there are new field in build setting
How can I change this value with script due to
xcrun agvtool new-version
xcrun agvtool new-marketing-version
not work perfectly as it on Xcode 10
I tried this one https://stackoverflow.com/a/58164679/7332815 but not working
I can only get correct value from
echo $versionNumber
echo $buildNumber
but how can I set new value to it?
update 2022/08/19
if using fastlane to bumping version
desc "Bump version and build nubmer"
lane :bump_version_and_build_number do |options|
version_number = options[:version]
puts version_number
sh("sed -i '' -e 's/MARKETING_VERSION \\= [^\\;]*\\;/MARKETING_VERSION = #{version_number};/' ../${YOUR_PROJECT_NAME}.xcodeproj/project.pbxproj")
increment_build_number
end
and just type in commend line
bundle exec fastlane bump_version_and_build_number version:1.0.1
okey I find a solution for myself, and thanks to an friend from meetup.
for Version number
I used
sed -i '' -e 's/MARKETING_VERSION \= [^\;]*\;/MARKETING_VERSION = 3.4.5;/' ${YOUR_PROJECT_NAME}.xcodeproj/project.pbxproj
e.g. sed -i '' -e 's/MARKETING_VERSION \= [^\;]*\;/MARKETING_VERSION = 3.4.5;/' DemoProject.xcodeproj/project.pbxproj
note that this can't work in pre-action of scheme setting
As for Build version
I used xcrun agvtool new-version xxx
e.g. xcrun agvtool new-version 3.4.5b
you can write these command in Build Phases
the reason I don't use xcrun agvtool new-marketing-version 3.4.5b is because it will write solid number into plist.
And I agree with Manuel's answer in Post
With these I can manage multi-targets' versioning
p.s. If you want to do that to, for example, notificationService target, remember to change version and build number manual at first to make Xcode 11 change the corresponding value to an variable like this
or you can make that by edit plist in source code of course.
That's the closest method I achieve to manage multi-target versioning so far.
I've read several tutorials and guides on how to have XCode create a universal library. Basically you add an aggregate target with a bash script build phase to build the separate targets and lipo them together.
I have my own small script (which works because of how I named my targets) but for some reason lipo can't find the files;
fatal error:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo:
can't open input file:
/Users/username/Projects/project/plugins/build/Release-iphoneos/libproject-plugins.a
/Users/username/Projects/project/plugins/build/Release-macos/libproject-plugins.a
(No such file or directory)
However when I
Run the exact same lipo command right after the failed build, everything works and the files are found.
Add bash logic in my script to wait for the file creation the issue persists.
Replace the lipo in my script with a simple ls, the files are there.
So I'm not sure what goes wrong, it doesn't seem like xcodebuild only creates the files after lipo is called (as I first thought).
The script;
targets=$(xcodebuild -list | sed -n '/Targets/,/^$/p' | grep -v -e 'Targets:\|all\|^$')
target_results=""
for target in $targets; do
xcodebuild ${ACTION} -target $target -configuration ${CONFIGURATION}
target_results="$target_results ${PROJECT_DIR}/build/${CONFIGURATION}-$target/libproject-plugins.a"
done
xcrun lipo -create "$target_results" -o "${PROJECT_DIR}/plugins-universal.a"
This is a bash problem/mistake.
You're passing all the file names as a single argument to lipo, so it's gonna look for a single file named /Users/username/Projects/project/plugins/build/Release-iphoneos/libproject-plugins.a /Users/username/Projects/project/plugins/build/Release-macos/libproject-plugins.a.
You should use an array for the file names instead.
Initialise it with () instead of "".
Add elements with +=(...) instead of ="$var ...".
Pass every element separately to lipo with "${var[#]}" instead of "$var".
Applied to your script:
targets=$(xcodebuild -list | sed -n '/Targets/,/^$/p' | grep -v -e 'Targets:\|all\|^$');
target_results=();
for target in $targets; do
xcodebuild ${ACTION} -target $target -configuration ${CONFIGURATION};
target_results+=("${PROJECT_DIR}/build/${CONFIGURATION}-$target/libproject-plugins.a");
done;
xcrun lipo -create "${target_results[#]}" -o "${PROJECT_DIR}/plugins-universal.a";
Technically this is not an answer to your question. But I would like to recommend that you choose a different option to what you are doing unless you really need to do it.
Building universal static libraries in this fashion is a very old way of doing things and as you are finding out, complicated and quite problematic to get working well.
A more current and much simpler approach (IMHO) is to build a framework. XCode has templates for frameworks. Frameworks are easier to work with and do not require you to do any of the messing around with multiple targets, bash and lipo as you are.
Further, you can then employ Carthage to manage them as dependencies for other projects with very little effort.
How can I determine what will be the arguments of the ld command in the build process from inside a script running as "run script build phase"?
I was looking at xcodebuild -dry-run as an option, but then I need to understand what should be the arguments I supply it.
Any idea for a robust solution?
EDIT:
It seems that xcodebuild doesn't support LD and LDPLUSPLUS when the project includes swift source code. So the solution that #fpotter offered doesn't work on project with swift.
Any thoughts?
Xcode doesn't expose a nice way to do this. In a Run Script build phase, all you have to work with are the Xcode build settings provided to you in the environment.
If you really need the entire argument list to ld, there's a hack you can use. With the LD and LDPLUSPLUS build settings, you can make Xcode call a script of your own instead of the real ld. From that script, you could capture the args, call through to the real linker, and then do whatever post processing you like there rather than in a Run Script build phase.
Here's how you could do that:
Create an .xcconfig for your target.
It should look like this:
LD = $(SRCROOT)/ld-wrapper/clang
LDPLUSPLUS = $(SRCROOT)/ld-wrapper/clang++
SRCROOT points to your project's directory. The LDPLUSPLUS line is only required if your app has C++ or ObjC++ code. If you don't want to create an xcconfig, you can also add these as User-Defined build settings via the Xcode UI.
Create wrapper scripts for Xcode to call.
Install a script like this at <your project root>/ld-wrapper/wrapper.sh:
#!/bin/bash
set -o errexit
# Choose which clang to run (clang or clang++) depending on how we're invoked.
# If we're invoked via the 'clang' link, we'll run 'clang'. If we're invoked
# via the 'clang++' link, we'll run 'clang++'.
CLANG_PATH="$DEVELOPER_DIR"/Toolchains/XcodeDefault.xctoolchain/usr/bin/$(basename "$0")
"$CLANG_PATH" "$#"
echo "clang args: $#"
echo "do any post processing here."
Create symlinks for the wrapper script for clang and clang++:
cd <project root>/ld-wrapper
ln -s wrapper.sh clang
ln -s wrapper.sh clang++
That's it. It's ugly, but it works.
I'm trying to modify a system plist in an Platypus script-based app (Mac), though I have a feeling my question may have a more general answer.
The question is: What is the correct Terminal syntax for targeting and modifying the boolean child of a Dictionary key in a plist file?
I tried:
sudo defaults write /private/var/db/launchd.db/com.apple.launchd.peruser.501/overrides.plist com.github.norio-nomura.SIMBL-Agent Disabled -bool false
but it doesn't like -bool with Disabled there..
I managed to solve it by using PlistBuddy instead. PlistBuddy is built into MacOS X 10.5 and above.
I could have used:
/usr/libexec/PlistBuddy -c "set :com.github.norio-nomura.SIMBL-Agent:Disabled bool" /private/var/db/launchd.db/com.apple.launchd.peruser.501/overrides.plist
But it caused an error in the .pkg installer, so I used:
/usr/libexec/PlistBuddy -c "Delete :com.github.norio-nomura.SIMBL-Agent" /private/var/db/launchd.db/com.apple.launchd.peruser.501/overrides.plist
.. and then:
/usr/libexec/PlistBuddy -c "Add :com.github.norio-nomura.SIMBL-Agent:Disabled bool" /private/var/db/launchd.db/com.apple.launchd.peruser.501/overrides.plist
.. right after that which appears to be working.
PlistBuddy doesn't require the Type when SET a value
/usr/libexec/PlistBuddy -c "set :com.github.norio-nomura.SIMBL-Agent:Disabled true" /private/var/db/launchd.db/com.apple.launchd.peruser.501/overrides.plist