What's the correct way to configure Xcode 4 workspaces to build dependencies when needed?

My case is simple, a workspace with two sibling projects: one main (iOS) app and a project that builds several static library targets used by the app.

Here's how I have configured the build:

  • pointed a 'user header search path' in the main app's build settings to the library project location (via a source tree)
  • in my app's main target's editor -> build phases -> "Link Binary With Libraries" section, added the library products I want to use.
  • in the scheme, ticked 'Find Implicit Dependencies'

After a clean (and deletion of the derived data), a build nets me this error during the build of the main project:

ld: library not found for -lChipmunk
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Command /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/clang failed with exit code 1

Sure enough, if I look in the newly-created derived data, the only object files to be found are for the main app, not the libraries. A widespread 'find' for *.o files doesn't reveal anything relevant, so the libraries aren't getting lost, they're definitely not being built.

Some supplementary points:

  • when I've asked about this on the Apple dev forums, it's been suggested that I should add explicit deps in the main target's Build Phases->Target Dependencies editor. But you can only add deps here to targets in the same project or subprojects; in my case I have the app and library projects as workplace siblings.
  • if I build each library manually before the main build, all is fine.

Update:

I've just figured out a workaround, which is to add all the deps' targets into the 'build' part of the main app's scheme. I had tried this before without success, but hadn't realised that I could drag the targets around in the list to get the right build order. Builds now happen in the correct order, both after a clean, and after changes in either library or main app source.

I'm leaving the question here, because manually sorting out a build order surely shouldn't be necessary. There has to be something wrong with how I have things set up.


Solution 1:

Editing the scheme (swapping around build targets, un-/check "Parallelize Build" and/or "Find Implicit Dependencies") didn't work for me. I still had to clean build the project, after any code change in the static lib. Searching the dev forums, I finally found this answer, which worked wonders.

Make sure the Identity and Type inspector is showing and select the libWhatever.a file in your application's project (not the library). If you see Location: Relative to Project [or Relative to Group], this is your problem.

  1. Click Relative to Project and change it to Relative to Build Products.
  2. This will change the type of the link, but it will still be broken.
  3. Click the locate button and find the output file.

Adding a static lib to an existing project via Build Phases -> Link Binary with Libraries automatically makes it "Relative to Group" (if both are siblings in the same workspace). Changing its location the way described above resolves the build dependency problem and in the project navigator your .a file should appear in black letters (instead of red).

Solution 2:

I described the way I've been setting up multiple projets in a workspace here: http://blog.carbonfive.com/2011/04/04/using-open-source-static-libraries-in-xcode-4/

I agree that manually adjusting the build target order in the scheme should be unnecessary, based on Xcode's documentation, but that's the best solution I've found so far.


Edit: Whenever possible I recommend using https://github.com/CocoaPods/CocoaPods to manage project dependencies at this point.