Ios – Static libraries in Xcode 4

iosstatic-librariesxcode3to4xcode4

(My question has been asked here before but with no working answers that I can see. E.g. Xcode4 Workspace with Static library project & application project)

I'm trying to use a library provided by a 3rd party. They provide the XCode project which builds a libLibraryName.a file. They recommend adding the project as a subproject to my own, then adding the product libLibraryName.a file to the set of libraries described in my project settings "Link Binary with Libraries".

The library does build correctly: the .a file is generated. But the project shows a red libLibraryName.a file under the Products group. I can't get it to turn black. And the parent project says it cant find LibraryName for linking.

As a test I created a new static library project using the XCode 4 static-library template. This project exhibits the same behavior – the product never shows up 'black' even though the .a file is built. (Edit: it does turn black if you build for device, not simulator).

I know that XCode 4 places intermediate and product files in a shared location by default. I've tried this setting, and I've changed the setting to place the product files in the folders described in the build settings. Neither setting works.

Folks have also suggested building for a device rather than simulator. I've tried this to no avail.

What gives? How do I get a static library project to recognize where it built the product, and subsequently reference this product in another project?

Best Answer

Lots of hoop jumping, but here are my notes now that it I got it working.

  • If you create a new stock XCode4 iOS "Cocoa Touch Static Library" project (and add some code to it) the project will build fine out of the box. But the Product file libLibraryName.a only turns black (from red, denoting the file doesn't exist) when you do a device build. A simulator build does not show that the target was built when in fact it was.

  • In the project target build-settings, the "Per-Configuration Build Products Path" defaults to $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) If you change this to something else (or if you upgraded the project from XCode3.x which used $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)$(IPHONEOS_DEPLOYMENT_TARGET) as the default, I believe), then the Product file libLibraryName.a wont ever turn black. To me this says there's a bug in XCode somewhere.

  • I can live without the Product file turning black after a build (it is a nice indicator, but hey, whatever.) But I do need my consuming project to be able to find the correct build of the library, be it for simulator or device. In an ideal world there would be a single .a file with i386/arm6/arm7 bits in it, but again, this isn't my library / library project.

  • The XCode4 Transition Guide is what showed me the light. It prescribes creating a workspace that hosts both of the projects, and they will both build into the same shared build directory. I was not using a workspace previously, so I used the File/Save As Workspace command to create the new workspace file. Then, I added the library project, taking care to ensure it was placed as a peer to my primary project and not as a child.

  • I had to make sure the workspace was configured to place build output into a common folder. In the Workspace Settings dialog, set the Build Location setting to "Place Build Products in Derived Data Location"

  • I also had to make sure to check the "shared" checkbox for each project in the Manage Schemes dialog.

  • Finally, to specify the library dependency for my main project, I simply went to the target Build Phases tab, Link Binaries with Libraries section, and clicked the '+', then selected the libLibraryName.a file from beneath the Workspace folder. Note that I'd tried this before when there was no workspace and no common build dir, and the result was that XCode couldn't find the .a file during link.

All said and done, it works like a charm. I can't help but think it should be a lot easier - as I believe it was in XCode3.

I'd be happy to read about anyone else's experience with all this, or any feedback about other (simpler?) ways to make linking static libs work well.