views:

1149

answers:

1

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
+3  A: 

Use "External Target":

  1. Select "Project" > "New Target..." from the menu
  2. Select "Mac OS X" > "Other" > "External Target" and add it to your project
  3. Open its settings and fill in your script setup
  4. Open the "General" tab of the main target's settings and add the new target as it's direct dependency

Now the new "External Target" runs before the main target even starts gathering dependency information, so that any changes made during the script execution should be included in the build.

ento
Why ask a question which you just answer yourself a minute later?
Abizern
You can also add a "Run Script" build phase from within a single target, placing that script build phase before the other target build phases.
Barry Wark
@Abizern: From the FAQ, "It's also perfectly fine to ask and answer your own programming question." Also, see this: http://stackoverflow.com/questions/18557/how-does-stackoverflow-work-the-unofficial-faq#119658
htw
@Abizem I wanted to share my findings and as @htw says, it's encouraged in stackoverflow. To clarify things a bit more, I added the tag "selfanswer", though it may be against that encouragement.
ento
@Barry I did place the script build phase on top of the build phase stack, but I still needed to build twice. I'm editing it in to the question. Thanks.
ento