Copying Private Frameworks using Xcode 4.x

• Chris Liscio

I've been moving more development over to Xcode 4, which I've been enjoying quite a bit since I started using it shortly after it was introduced last year.

Believe it or not, Capo for iOS was almost exclusively developed in Xcode 4. Unfortunately, Apple did not allow app submissions with the beta tools, so I was forced to bounce back and forth between Xcode 3 and 4 for Capo version 1.0. But I digress.

I've finally got around to moving the Capo project to Xcode 4 just the other day, but I hit some bumps in the process. I created a workspace containing the projects for Capo, and its companion frameworks, but couldn't get a solid 'Copy Files' build phase to work properly.

You see, when you drag a framework from the project navigator into your 'Copy Files' build phase, it appears to use a pre-baked relative reference to the framework's path. Unfortunately, that means the following things are baked into the path:

Both of those items are moving targets, depending on what scheme/action you're building for, and where you're building your workspace. The derived data location for a workspace is based on a hash of the location of the workspace itself, so that could theoretically change on a separate machine, or even on the same machine between two different folders!

Ideally, the framework targets would be specified for the Copy Files build phase in a way that makes sense no matter what scheme you're building, or where you're building it on your machine. Furthermore, it'd be nice to get Debug versions of your frameworks when debugging your app, wouldn't it?!

Of course, I've filed a bug to document this issue: rdar://9722234.

So, my solution to the problem in the meantime is to use a script build phase. I created a script in Capo's project directory called copyFrameworks.sh, and it looks like this:

Be sure that you run chmod+x on that file in the terminal, so it executes.

Now, for my new Run Script build phase, I use this:

That handles both the copy step, and also the subsequent removal of the frameworks' headers. Note that I don't use the "Input Files" list in the script to specify the list of frameworks. I know it could be done, but I've just not gotten around to it.

Hope this helps!