42

I have a script that I run using osascript from a Run Script Build Phase in Xcode 4. This script does some checks to try and catch any human-error in plists and suchlike.

However, I only really want to run this script when a developer chooses 'Archive' as opposed to running it every time they build.

Is there any way of testing for this situation? Either in Shell Script or Apple Script?

Wex
  • 4,434
  • 3
  • 33
  • 47

4 Answers4

58

In Xcode 4+, you could run this script as a pre- or post-action script on the "Archive" action. However, pre- and post-action scripts are not considered part of the build itself; their output is not part of the build log, and a failing script will not cause the build to fail.

If you want to include this script as a first-class part of the build, such that its failure will cause the build to fail, then you'll want to do something else. Make a new "External Build System" target, and configure it to run your script. The path to your script can be a relative path, relative to the project root.

Finally, open your main project scheme, and in the "Build" tag add the new checker target, and set it to only be included in the "Archive" action. This should cause your checker script to be run as part of the build only when "Archive" is selected, and if the script returns a non-zero value the build will fail.

Here's a step-by-step visual guide to configure a bash script to run only when archiving a target:

  1. File > New > Target > Other > External Build System File > New > Target > Other > External Build System

  2. Name the product accordingly and set /bin/bash as the Build tool Name the product accordingly

  3. Provide the path to the script under Info > Arguments of the newly created target Provide the path to the script under Info > Arguments of the newly created target

  4. Product > Scheme > Edit Scheme…, and edit the scheme of the target where you want this script to run before archiving. Under Build, add the External Build System target you added in step 1. Reorder if needed. Then uncheck everything except Archive. Edit the scheme of the target where you want this script to run before archiving

junjie
  • 7,946
  • 2
  • 26
  • 26
BJ Homer
  • 48,806
  • 11
  • 116
  • 129
  • Lovely. I did find the pre/post actions a few days after posting the question. Never got around to trying it though. Cheers for the details. – Wex May 09 '11 at 15:26
  • 2
    One thing to note: When you set up a new "external build system" target, be sure to go into its dependencies and set it up to depend on your other target -- otherwise it can be run before the other target is done building. – SomeCallMeTim May 02 '12 at 19:35
  • 26
    For those that want a more simplistic approach, you can just check the `${CONFIGURATION}` variable in the script, like such: `config="Release" if [ "$config" = "${CONFIGURATION}" ]; then echo "Running my script" fi` – hwaxxer Oct 01 '12 at 14:17
  • 5
    That's assuming you never run any other actions in a Release mode. Profiling (at least for performance) is usually done in Release mode as well, so you'd be running this script there as well. – BJ Homer Oct 01 '12 at 15:54
  • 2
    My use case was to update the build version number, and Xcode processes the Info.plist file BEFORE running any custom script actions. A dependent build target, however is processed first. This is also much better than the Scheme script actions, because they have hardly any useful environment variables set. – Matt Connolly Apr 22 '13 at 01:03
  • +1 Superb answer; I was able to remove the many hacks from my post-build script! – trojanfoe Oct 01 '13 at 13:55
22
  1. Add a "New Run Script Phase" to your project's "Build Phases"
  2. Move (drag&drop) your script in the right position
  3. Check the "Run script only when installing"

If you don't do 3. the script will run all the time, but if you check that box, it will only run when archiving.

Mike
  • 292
  • 2
  • 8
2

So in latest Xcode (13.3) you can edit your schemes and copy & paste (or drag&drop) your executable script in the run script textfield (see image).

The pre-Action is executed before the Organizer is opened and the post-action is executed after the build landed in the archives list of products. In both cases the build process of archiving will run through beforehand. Editable schemes in Xcode 13.3

FrugalResolution
  • 568
  • 4
  • 18
0

A quick test on my own system shows no difference in the detailed script output between straight "Build" and "Build and Archive".

Also, you can't test for the presence (or absence) of the archive, since it only gets created at the very end of the process, when all scripts have been run.

As far as I can see, there is no current option within Xcode 3 to do this. Maybe file an enhancement request with Apple?

While you wait on Apple, the only solution I can offer is to use xcodebuild and xcrun as part of a command-line shell script, where you would know if you are archiving or not. This is not a stay-in-Xcode solution, but it does have a lot of flexibility.

Xcode "Build and Archive" from command line

Community
  • 1
  • 1
Philippe
  • 905
  • 6
  • 18