One thing I keep coming up against in Xcode projects is that the build settings aren’t quite right. Why is ZERO_LINK enabled when target T2 is built with configuration C4? Unfortunately, you quickly end up with a very large combination of options. Six targets and four configurations means twenty four combinations to think about. Which is madness.
There is an easier way: build settings files (*.xcconfig
). These are text files with the same settings that are normally embedded into your xcodeproj file. For example, on a newly created cocoa application, these are the settings that are present by default in the Debug configuration.
ARCHS=$(ARCHS_STANDARD_32_BIT) GCC_C_LANGUAGE_STANDARD=c99 GCC_OPTIMIZATION_LEVEL=0 GCC_WARN_ABOUT_RETURN_TYPE=YES GCC_WARN_UNUSED_VARIABLE=YES ONLY_ACTIVE_ARCH=YES PREBINDING=NO SDKROOT=macosx10.5
And these are the ones in the Release configuration.
ARCHS=$(ARCHS_STANDARD_32_BIT) GCC_C_LANGUAGE_STANDARD=c99 GCC_WARN_ABOUT_RETURN_TYPE=YES GCC_WARN_UNUSED_VARIABLE=YES PREBINDING=NO SDKROOT=macosx10.5
Hmmm, they look quite similar (run diff(1) to see). We can extract a common file (Choose File → New File… → Other → Configuration Setting File).
// Project-Common.xcconfig ARCHS=$(ARCHS_STANDARD_32_BIT) GCC_C_LANGUAGE_STANDARD=c99 GCC_WARN_ABOUT_RETURN_TYPE=YES GCC_WARN_UNUSED_VARIABLE=YES PREBINDING=NO SDKROOT=macosx10.5 // Project-Debug.xcconfig #include "Project-Common.xcconfig" GCC_OPTIMIZATION_LEVEL=0 ONLY_ACTIVE_ARCH=YES // Project-Release.xcconfig #include "Project-Common.xcconfig"
To apply these, go into the Build tab of the Project Info pane, and select the Debug configuration. Delete all the settings in there (⌘-A, ⌫) and then select “Based On: Project-Debug”. Do the same for the Release configuration, except base it on Project-Release.

Now, you can add a setting to Project-Common.xcconfig
and it will show up in all your configurations. As a nice side effect, it’ll be much easier to see the change in version control.
What about targets? Well, the same principle applies. Except that you want to “push up” as much configuration as possible into your project level xcconfig files.
Let’s take a look at the default Debug configuration for my “Polynomials” target.
INSTALL_PATH = $(HOME)/Applications COPY_PHASE_STRIP = NO INFOPLIST_FILE = Info.plist PRODUCT_NAME = Polynomials ALWAYS_SEARCH_USER_PATHS = NO GCC_ENABLE_FIX_AND_CONTINUE = YES GCC_DYNAMIC_NO_PIC = NO GCC_MODEL_TUNING = G5 GCC_ENABLE_OBJC_GC = required GCC_OPTIMIZATION_LEVEL = 0 GCC_PRECOMPILE_PREFIX_HEADER = YES GCC_PREFIX_HEADER = Polynomials_Prefix.pch
The only really target specific settings are INFOPLIST_FILE and PRODUCT_NAME. The rest can either be deleted (GCC_MODEL_TUNING?!?), or pushed up into the project level settings (GCC_OPTIMIZATION_LEVEL, which is already defined there).
It’s a really worthwhile exercise going through your project in order to clean up your build settings. You’d be surprised at what’s going on in there. Keep a copy of the Xcode Build Settings Reference handy to look things up and see if you really need them. If you want an example, I noticed that Eric Czarny’s lovely XMLRPC library is organised somewhat like this.
You can do a lot more mad things with xcconfig’s, like choosing alternate signing personalities. But extracting your current configuration is a good start.
In order to help the transition, I wrote a bit of applescript to pull out existing settings. It’s pretty nasty because I don’t really get applescript. But it Works For Me™.
set newLine to ASCII character 10 tell application "Xcode" set proj to project 1 -- This is a string of a POSIX path. set dir to project directory of proj repeat with cf in build configurations of proj set str to "" repeat with stg in build settings of cf set str to str & (name of stg) & "=" & (value of stg) & newLine end repeat -- Write the results to a file set filename to "Project-" & (name of cf) & ".xcconfig" set fileno to open for access (dir & "/" & filename) as POSIX file with write permission write str to fileno close access fileno -- Sort the file to make it easier to diff. do shell script "cd " & dir & " && sort " & quoted form of filename & " >" & quoted form of filename & ".tmp && mv " & quoted form of filename & ".tmp " & quoted form of filename end repeat -- Now, iterate through each target. repeat with tgt in targets of proj repeat with cf in build configurations of tgt set str to "" repeat with stg in build settings of build configuration (name of cf) of tgt set str to str & (name of stg) & "=" & (value of stg) & newLine end repeat -- Write the results to a file set filename to "Target-" & (name of tgt) & "-" & (name of cf) & ".xcconfig" set fileno to open for access (dir & "/" & filename) as POSIX file with write permission write str to fileno close access fileno -- Sort the file to make it easier to diff. do shell script "cd " & dir & " && sort " & quoted form of filename & " >" & quoted form of filename & ".tmp && mv " & quoted form of filename & ".tmp " & quoted form of filename end repeat end repeat end tell
And yes — applescript doesn’t have a sort function builtin. WTF?