36

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.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Cris
  • 1,939
  • 3
  • 23
  • 37
  • 2
    Another reason for leaving the question here is that even the above (imperfect) workaroun doesn't always work. It's fine on the first build, but often [fails to build](https://devforums.apple.com/message/399726#399726) after source changes in the static lib project. – Cris Apr 06 '11 at 03:28
  • 1
    I never quite understood what's the deal with this whole Xcode 4 workspace thing. How exactly is it different from subproject? What's the benefit anyways for all these headaches? – Tony Jan 03 '12 at 21:28
  • So... I'm facing the same problem... it works if I clean and then build the project. But Xcode is not recompiling the lib project after changes in its source code. So, Im forced to clean/build the app project to force xcode to recompile and generate the updated version of my library. Any progress with it, @Cris? – hbobenicio Feb 08 '12 at 16:38
  • This works, but I also had to not parallelize the build – Gary Rudolph Jul 24 '12 at 00:19
  • 1
    @hbobenicio: nothing beyond the workaround mentioned above, sorry. Actually on more recent projects I haven't needed to do anything special--I'm just not getting any 'library not found' errors. Perhaps Apple has improved matters in more recent Xcode's build system? – Cris Jul 26 '12 at 04:24

4 Answers4

41

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).

christoph
  • 1,564
  • 2
  • 17
  • 27
  • This works wonderfully! Can the asker please set this as preferred answer? – Igor Aug 10 '12 at 10:54
  • You, sir, rock. Version 4.3 and this problem still exists?! Clearly people at Apple don't create workspaces with this structure. – Tyler Daniel Sep 07 '12 at 05:48
  • My project is now linked Relative to build path: .../Build/Products/Debug-iphonesimulator/... How do you generalize this to work when you change schemes to build a release and/or device version? Halfway there :P I should also note that I had to follow instructions from this link before I could use this solution to solve my problem: http://www.cocoabuilder.com/archive/cocoa/310430-xcode4-force-relink-when-static-library-change.html. – phoganuci Oct 04 '12 at 14:51
  • Not sure if it works for you, but when I located my lib I used the ../Build/Products/Debug-iphoneos/ directory instead of ../Build/Products/Debug-iphonesimulator/. That way it still gets rebuild, even if the active scheme is a simulator. – christoph Oct 04 '12 at 17:01
  • 2
    Interestingly enough, if you look at the `project.pbxproj` file and locate your lib in the `PBXFileReference` section, the `path` key got resolved directly to `libXXX.a` without any preceding directory. If that's not the case for you, you might want to strip the directory info manually. – christoph Oct 04 '12 at 17:10
  • Well, this solution don’t work for me with a regular framework for a Mac OS app. The OP (and everyone) should definitely add the iOS tag to questions relevant to the iPhone platform! – wdyp Oct 29 '12 at 11:44
  • I discovered this technique with a Mac command line application. It definitely works. (I'm responsible for the devforums post.) – Steven Fisher Mar 23 '13 at 02:09
  • Isn't a problem selecting the lib inside the debug folder? Do I have to change it every time I want my project to be compiled in release? – Valerio Jun 12 '13 at 14:39
8

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.

Jonah
  • 17,918
  • 1
  • 43
  • 70
  • Your post describes the procedure nicely, but it's essentially the same one I describe in the question. Unfortunately as I've mentioned in a new comment above, the workaround doesn't always work. XCode 4's build system is unfortunately unreliable as yet. Out of interest, I don't experience the indexing problem you mention in your post: I get autocompletion of library project source just with a 'user header' build setting. – Cris Apr 06 '11 at 03:35
  • @Jonah your blog might have good information, but the text is way too dark (on a dark background) to read.. and why are the pictures soooo small? – Alex Gray Jul 12 '12 at 19:07
  • @alexgray I'm not sure what you're talking about. That page looks to me like well formatted #555 text on a white background. All of the images link to full size screen shots if you need a closer view. – Jonah Jul 12 '12 at 22:45
2

Try dragging the library project into the main project:

library project reference inside main project

Jeffy
  • 795
  • 5
  • 11
  • 2
    Yes, I realise I can do this (a la XCode 3), but I want to keep the projects as workspace siblings. – Cris Mar 25 '11 at 01:19
  • In XCode 4.2, This seems like the best solution. I created a group called "Workspace Siblings," and dragged the library project inside, then added the .a product to the Link Binary With Libraries. Now, any edits I make to my static library are compiled into my final product. – zkarcher Feb 27 '12 at 22:29
  • Do you know how turn off warning from the Subproject? – Luca Bartoletti Aug 06 '12 at 15:21
0

In my case, the only way i could have that sibling configuration build is by manually adding the path "../MyLibProject/build/Debug-iphoneos" (checking recursive just to make sure) in my Build Settings -> Library Search Paths. Adding the .a file in the Main project alone didn't prevent the "lib not found" error at link time.

Ben G
  • 3,965
  • 3
  • 30
  • 34