Xcode Run Script Build Phase Tip
The standard way to do a Run Script build phase is to just put the text of the
script in the window that opens up when you double-click the build phase. But,
this provides a pretty meager editing experience: no syntax highlighting, smart
indenting, or anything like that. Furthermore, the contents of the script is
stored directly in the project file (specifically in
MyProject.xcodeproj/project.pbxproj
), which makes it a bummer when it comes
time to do any diffing or merging with your SCM system. Also, if you want to
include the phase in multiple targets, you have to copy/paste the script to each
target, and remember to update them all manually if you make a change to the
script.
My trick is to put the body of the script in a normal file and call it from the Run Script build phase. It’s pretty simple, but can be quite handy.
Here is how I do this. First, make a new directory in your project folder named
“scripts” and in that make a new file named something like
my_build_phase_script.sh
. Drag this whole new folder (“scripts”) to Xcode to
add it project, using the following settings. (Be sure to un-check the “Add To
Targets” boxes, because adding to the target will just copy it to the Resources
folder when building.)
Next, edit the contents of your script. This is left as an exercise for the reader.
Finally, make the build phase. Right-click on your target and select Add > New Build Phase > New Run Script Build Phase. In the window that opens up, just put this for the “Script” field:
script_file="my_build_phase_script.sh"
echo "Running a custom build phase script: $script_file"
${PROJECT_DIR}/scripts/${script_file}
scriptExitStatus=$?
echo "DONE with script: ${script_file} (exitStatus=${scriptExitStatus})\n\n"
exit "${scriptExitStatus}"
Set the rest of the options like this:
Now you can edit this script using nice syntax highlighting, easily diff and merge changes, and call the same script from multiple targets without any error-prone manual updating, etc. Win-win-win.
A note for advanced users
As a build phase script, this only gets run while building (not cleaning).
So, even though there is an ACTION
environment variable that gets set, it
isn’t much use because the script doesn’t even get run when you’re not building.
There are a few fun things you can do to work around this, but I’ll leave that
for another post.