6

In our project we derive our release version from git tag etc then write it to the built folder's Info.plist with a shell script like:

GIT_RELEASE_VERSION=$(some git command) defaults write "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH%.*}" "CFBundleShortVersionString" "${GIT_RELEASE_VERSION#*v}"

This has worked well for all past Xcode versions, but in Xcode 10's New Build System this failed to actually update the CFBundleShortVersionString in the info.list file. The value is correctly updated with Xcode 10's Legacy Build System though.

I added some echos to the script and compared the build log on New and Legacy systems and cannot see any difference:

echo "git release version:" ${GIT_RELEASE_VERSION} echo "info path:" ${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH%.*} echo "grv:" "${GIT_RELEASE_VERSION#*v}"

Not sure if anyone out there encountered similar issues with the New Build System?

CodeBrew
  • 6,457
  • 2
  • 43
  • 48
  • I use the code from https://gist.github.com/airdrummingfool/ecfa9827f47c5d02af53 and it works: `/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $version" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"`. The difference being to replace `BUILT_PRODUCTS_DIR` with `TARGET_BUILD_DIR`. And make sure that this script is the last step to run. – Cœur Sep 30 '18 at 06:04
  • thanks @Cœur but changing to `TARGET_BUILD_DIR` doesn't seem to help on my case – CodeBrew Oct 01 '18 at 14:48
  • can anyone post complete runscript for creating universal target? – Satish Mavani Oct 29 '18 at 09:51
  • @SatishMavani your question is not really related to the original question here. Could you post it as a new thread? – CodeBrew Oct 29 '18 at 14:38

4 Answers4

17

It seems like the problem is that sometimes your Run Script Phase will execute before Xcode creates the Info.plist. If you’d like to ensure that your script phase runs after a specific step, you need use the inputs to mark your dependencies.

For instance, adding:

$(TARGET_BUILD_DIR)/$(INFOPLIST_PATH)

As an input to your script phase should enforce the ordering you are looking for: Xcode will create the Info.plist and sometime after, your script will execute and modify the Info.plist.

Edit for Xcode 14 - J Nozzi

Per comment below, the above did not completely work for me, as it kept claiming it would run with every build. Adding $(DERIVED_FILE_DIR)/$(INFOPLIST_PATH) to the Output Files list worked.

Joshua Nozzi
  • 60,946
  • 14
  • 140
  • 135
David G.
  • 186
  • 3
  • This worked for me: I have a pre-compile script which updates the build number according to git commit count since last tag. To avoid affecting the repos I have to reset the build number after the info.plist has been processed. Adding this to the reset made that happen. – Johan Apr 08 '19 at 23:03
  • Perfect I'm using this to dynamically set App Transport Security - Allow Arbitrary Loads based on the configs linked to my schemes. Xcode was running my script before it generated the plist that I was trying to modify. This fixed the order! – Andrew Kirna Jun 03 '20 at 20:00
  • This worked! I initially typoed the parentheses as curly brackets, after correcting it, it works. – Winston Du Jan 05 '21 at 11:06
  • This did not work for me until I added `$(DERIVED_FILE_DIR)/$(INFOPLIST_PATH)` to the *Output Files* section. It kept complaining that it'd run every time otherwise. – Joshua Nozzi Mar 29 '23 at 18:22
4

(Xcode 11.2)

  • In the New Build System, any custom build steps will run before the New Build System's Process .../Info.plist step:

enter image description here

  • To run a shell script after Xcode finishes building, you can add it to your scheme(s) as a build post-action:

Product > Scheme > Edit Scheme... > Build > Post-actions

I stole this image from https://stackoverflow.com/a/54232034/969305

  • If you're going to reference any build system environment variables (e.g. BUILT_PRODUCTS_DIR or INFOPLIST_PATH), make sure you change the Provide build settings from selection.

  • Add your shell script, but remember that if you edit any file in the app bundle (i.e. Info.plist), you'll need to re-sign the app. Add this to your post build step:

export CODESIGN_ALLOCATE=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate
/usr/bin/codesign --force --sign - --entitlements "${TARGET_TEMP_DIR}/${FULL_PRODUCT_NAME}.xcent" --timestamp=none "${CODESIGNING_FOLDER_PATH}"
sam-w
  • 7,478
  • 1
  • 47
  • 77
0

Same issue here... one work-around is to clean and then perform full-build.

The new build system in Xcode 10 runs the Process Info.plist step differently in full and incremental builds:

  • Full-build: after processing assets, before linking storyboards (link step)
  • Incremental: after embedding frameworks, before signing.

The actual problem is the script that runs as a build step & updates the processed Info.plist file needs to always run after the the file is processed but before signing.

Evtim Georgiev
  • 444
  • 4
  • 10
0

Similar to the answers above (can't comment yet) but slightly changed.

Scripts input files:

$(PROJECT_DIR)/$(INFOPLIST_FILE)      
$(TARGET_BUILD_DIR)/$(INFOPLIST_PATH)

Output files:

$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)

I created a gist with a script I use to set the bundle version and some extra info like tag, date, branch.

https://gist.github.com/JoeMatt/aedd459c54a383373231719e508a2a36

Yanga
  • 2,885
  • 1
  • 29
  • 32
  • This didn't work for me. @david G's answer worked. Adding the other two entries suggested here caused an error: "invalid task blahblahblah with mutable output but no other virtual output node" – chetstone Aug 30 '19 at 23:44