Xcode: Running a script before every build that modifies source code directly

builddependenciesscriptingxcode

What I did:

I have a script that

  1. Read some configuration files to generate source code snippets
  2. Find relevant Objective-C source files and
  3. Replace some portions of the source code with the generated code in step 1.

and a Makefile that has a special timestamp file as a make target and the configuration files as target sources:

SRC = $(shell find ../config -iname "*.txt")
STAMP = $(PROJECT_TEMP_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME).stamp
$(STAMP): $(SRC)
    python inject.py
    touch $(STAMP)

I added this Makefile as a "Run Script Build Phase" on top of the stack of build phases for the project target.

What happened:

The script build phase was run before compiling the source.

However, since the script modifies source code during its execution, I needed to build twice to get the most recent version of the build product. Here is what I imagine to be happening:

  1. 1st run: Xcode collects dependency information —> no changes
  2. 1st run: Xcode runs "Run Script Build Phase" —> source is changed behind Xcode's back
  3. 1st run: Xcode finishes build, thinking nothing needs to be updated
  4. 2nd run: Xcode collects dependency information —> source has changed, needs rebuild!
  5. 2nd run: Xcode runs Run Script Build Phase" —> everything is up-to-date
  6. 2nd run: Xcode proceeds to compilation

After reading Xcode documentation on Build Phases, I tried adding a source file which is known to be updated every time the script is run as the output of "Run Script Build Phases", but nothing changed. Since the number of configuration files may vary in my project, I don't want to specify every input and output file.

Question:

How do I make Xcode aware of source file changes made during "Run Script Build Phase"?

Edit:

  • Added that I placed the script build phase before the other build phases

Best Solution

Every technique mentioned so far is an overkill. Reproducing steve kim's comment for visibility:

In the build phases tab, simply drag the "Run Script" step to a higher location (e.g. before "Compile Sources").

Tested on Xcode 6

Related Question