Using Open Source Static Libraries in Xcode 4

Xcode 4.0.1 allows us to more easily create and use third party libraries in iOS projects. I think the process is still more complicated than it needs to be. Xcode’s documentation suggests that it should automatically detect implicit dependencies and index classes across workspaces but I have not found this to be the case. Here I’ll cover the steps I have found for creating and sharing code between projects and with other developers.

  1. Background
  2. Using a Static Library
  3. Creating a Static Library
  4. Future Improvements

Background

Workspaces:

Xcode 4 introduced the concept of workspaces as containers for multiple projects. There are a couple of key behaviors of workspaces which we want to build on when choosing how to share code across projects.

  • By default, all the Xcode projects in a workspace are built in the same directory, referred to as the workspace build directory.
  • Xcode examines the files in the build directory to discover implicit dependencies.
  • Each project in a workspace continues to have its own independent identity.

Schemes:

Within a workspace or within a project which is a member of a workspace we have schemes. Schemes replace the Active Target, Build Configuration, and Executable settings from Xcode 3 and define which targets to build, the order in which to build them, and what action to take when a build is complete. We’ll want our shared code to easily fit into the scheme of any projects which use it. The Xcode 4 Transition Guide covers this new structure in more detail.

Targets:

Within a scheme we have one or more build targets which define a set of source files to build, the settings used to build those files, and any dependencies on the build products of other targets which must be completed first. Ultimately we would like a consumer of our code to be able to state that their project’s build target depends on our shared code and have Xcode build this shared code and make it available to the active build target. We can achieve that by providing a project containing the code to be shared and a static library build target which packages it into a build product other developers can add as a build target dependency.

Using a static library

  1. Creating a workspace
  2. Adding projects to a workspace
  3. Adding build target dependencies
  4. Adding the static library’s headers
  5. Configuring the project’s scheme
  6. Fixing indexing

Creating a workspace

We can create a new empty workspace from Xcode’s file menu or open an existing project and select “Save As Workspace…” to create a new workspace containing our project. This will create a “.xcworkspace” package in the file system.

An empty Xcode 4 workspace

An empty Xcode 4 workspace


Adding projects to a workspace

Once we have a workspace we can right-click in the workspace’s navigator to create a new project or add an existing “.xcodeproj” package.

Adding a new project to a workspace

Adding a new project to a workspace

Adding an existing project to a workspace

Adding an existing project to a workspace

We want to end up with a single workspace containing our app’s project and the projects for any static libraries we are going to depend on. It is worth noting that these projects are all siblings in the workspace, our static libraries are not added as references within our app’s project.

 

Adding build target dependencies

With all of the projects we need available in our workspace we can select our app’s build target and add a static library to the “Link Binary With Libraries” build phase.

Libraries and frameworks available to add to the "Link Binary With Libraries" build phase

Libraries and frameworks available to add to the "Link Binary With Libraries" build phase

A static library added to the "Link Binary With Libraries" build phase

A static library added to the "Link Binary With Libraries" build phase


Adding the static library’s headers

We also need to make sure that our app’s build target can locate the public headers used in this static library. Open the “Build Settings” tab and locate the “User Header Search Paths” setting. Set this to “$(BUILT_PRODUCTS_DIR)” (or “$(BUILT_PRODUCTS_DIR)/static_library_name” if we want to be more specific but then we’ll have to update this setting every time we add another library) and check the “Recursive” check box. Now our built target will search our workspace’s shared build directory to locate linkable header files.

Setting the User Header Search Paths

Setting the User Header Search Paths

User Header Search Paths set

User Header Search Paths set

The “User Header Search Paths” setting defines the headers available as quoted imports (eg “#import “MyLibraryClass.h”) while the “Header Search Paths” setting defines those headers available as bracketed imports (eg “#import ). I’ve found that Xcode will only autocomplete header names in the quoted form so I always add libraries to the user header search path even though, from my project’s perspective, they might be more appropriate as system level (angle bracketed) libraries.

When using a static library which includes categories we will also have to add the “-ObjC” flag to the “Other Linker Flags” build setting. This will force the linker to load all objective-c classes and categories from the library. If the library contains only categories “-all_load” or “-force_load” may be needed as well. See Technical Q&A QA1490 for a more detailed explanation of these settings.

Configuring the project’s scheme

At this point Xcode should have detected this implicit dependency between our app’s project and the static library’s project and have automatically configured our schemes correctly. Unfortunately I haven’t found this to be the case in practice. Instead we will have to edit our current scheme and add the static library’s build target before our app’s build target.

Setting the scheme's target build order

Setting the scheme's target build order


Fixing indexing

At this point we should be able to include headers from dependent static libraries, use the included classes, and still successfully build our app. Unfortunately Xcode will not show any classes from these linked static libraries in code completion despite the workspace documentation stating that “indexing is done across the entire workspace, extending the scope of content-aware features such as code completion and refactoring.”
As a workaround we can drag the public headers from the static library’s project into our app’s project, adding them as references. These headers do not need to be included in any of our build targets, simply having references to the headers in our project will allow their classes to appear in code completion.

Creating a Static Library

If we plan on releasing some of our own code for reuse as a static library there are several things we should do to make sure that the process described above is as easy and simple as possible for our library’s users.

  1. Namespace classes appropriately
  2. Create a build target
  3. Expose public headers
  4. Set the installation directory
  5. Set the public header path
  6. Exclude user specific files from VCS

Namespace classes appropriately

Use an appropriate prefix for classes, protocols, functions, and constants in the library to prevent collisions with names in the library’s user’s project.

Create a build target

Provide a static library build target in the project for our users to link against. Xcode provides templates for creating projects with static libraries or adding static library build targets to existing projects.

Expose public headers

Determine which header files should be visible to users of the library. Provide a clearly named group containing these headers so that our library’s users can easily locate them as part of the workaround described in “Fixing Indexing” above. This also helps us clarify what the public interface our library provides is and what classes are implementation details which are likely to change as the library evolves.

For each public header file make sure it is set as “public” in the “Target Membership” section of the inspector pane. Only public headers are going to be available for our users to import.

Making a header file public

Making a header file public


Set installation directory

Our static library build target is going to be a member of a user’s workspace and subject to that workspace’s installation rules. Our static library build product could therefore be installed in a location set by Xcode’s preferences, in the derived data path, or in a path specified by our build target. Since we can’t control the user’s settings we should make sure our library is well behaved in all cases. I set the “Installation Directory” build setting to “$(BUILT_PRODUCTS_DIR)” so that the static library build product can be found in a known location and set the “Skip Install” build setting to “Yes” to avoid accidentally installing iOS libraries into “/usr/local/lib”.

Setting the installation directory

Setting the installation directory


Set the public header path

We need to specify a location to copy our static library’s public headers to so that they can be included in our users’ header search paths. Setting the “Public Headers Folder Path” to “$(TARGET_NAME)” will create a folder named after our static library build target in the workspace’s shared build directory and be indexed by the “User Header Search Paths” setting described above.

Setting the public headers path for the static library

Setting the public headers path for the static library


Exclude user specific files from VCS

Our workspace and project include a number of files which contain data relevant only to our user account; window positions, open files, and so on. There’s no need to check these into source control, at least not in our release branch, so let’s set some reasonable ignore rules in git or whatever VCS we are using. Github provides a convenient set of .gitignore files

Future Improvements

Hopefully Xcode 4 will eventually live up to the promise of it’s documentation and consistently auto-detect implicit dependencies and index files across the workspace correctly. There certainly seem to be a number of other developers struggling with this behavior:[1], [2], [3], [4], [5], [6], [7], [8]. Until that indexing improves I find that this process is at least somewhat simpler and cleaner than trying to maintain simulator and device compatible static library builds in Xcode 3.
I’ve found this pattern preferable to copying third party classes directly into my projects as it allows me to easily keep version history and make updates to static library projects in my workspace and avoids coupling my project too closely to the private structure and contents of the static library.
Please let me know if you can see any areas where this pattern could be improved or if you’ve found your own alternative means of sharing code.

This entry was posted in Mobile and tagged , , . Bookmark the permalink.
  • http://www.sparrow-framework.org PrimaryFeather

    Thanks – thanks – thanks!!! I spent hours looking for the correct way to add a static library properly in Xcode4. Obviously, I did not realize that I had to make the header files “public” in the target membership section … so my header files were never found by the main project. Thanks for taking the time to write down this clear guide! I’m sure it will help many developers like me. :-)

  • gope

    Sir, you have ended my current quest. Thank you. I now know how to do what I fucking wanted to do!

  • Martin

    A helpful post., thank you!

    There is a conflict however with advice elsewhere for getting Archive to build a package to include a static library. That recommends that you put the Copy Headers in ‘Project’ to avoid “Multiple Bundle” errors. If I do that then my builds require me to manually copy the static library headers into build folders so the project can build.

    Does anybody have a middle way to avoid both these issues, other than manually copying headers?

    = Martin =

    • Jonah

      Martin, sorry to hear that you’ve been having trouble. I haven’t yet seen the “multiple bundles” error you mentioned while archiving an app but I’ll see if I can find a project which reproduces that behavior and might isolate the problem.

  • Martin

    On my previous Q, I have a work-around (not that I’m proud of it).

    1) To avoid “Multiple Bundle” errors from Submission Validation you’ll need to put the Copy Headers into the ‘Project’ group, not ‘Public’.
    2) To get the Product to compile, you’ll need to set the Product build settings Header Search Path to point explicitly into the Dependency project folders to find the headers.

    Until somebody tells me of a better way…

    = Martin =

  • Jonah

    As an example of this pattern in practice I created an ASIHTTPRequest fork which provides a static library which is then linked against by the iPhone and iPad sample apps. You can find it here: https://github.com/carbonfive/asi-http-request/tree/Xcode_4_static_lib

  • Pingback: xCode 4 – Using Open Source Static Libraries in Xcode 4 | Advanced App Development

  • Martin Goldsmith

    Why anyone would want to program in the Apple environment has me wondering. The tools are backwards, the software is markedly inferior to Microsoft’s and the cost of the machines is way too high.

    There is not even Visual Basic available on OS X!

    • Louis

      Agree on all counts, except that the device and end result are cooler… but i miss Visual Studio badly

    • Not-a-troll

      Unless you’re joking about Visual Basic I don’t think you’re qualified for commenting here.

      Yeah, the IDE sucks compared to Visual Studio, especially when it comes to configuration and debugging, but the APIs are much better, unless you’re doing very basic stuff – in such case MSs offering is okay.

  • GregH

    Can I ask:

    a) what does $(BUILT_PRODUCTS_DIR) actually resolve to? i.e. which directory

    b) if I have a 3rd party library at the same level of my app (i.e. it’s source is not within a subdirectory of my app) then what header path entry should I be using? For example in this case do I still need to use “$(BUILT_PRODUCTS_DIR)” as a starting point and then use multiple “../” entries to back out to a subdirectory above my app, and then back down to the library? Why would I need to use “$(BUILT_PRODUCTS_DIR)” at all in this case? Guess I’m just a bit confused here. If you can clarify that would be great.

    • Jonah

      $(BUILT_PRODUCTS_DIR) can resolve to a number of locations depending on the “Build Location” setting in the Xcode Preferences’ Locations tab and the settings of each build target. Regardless of how you might have configured your system it should give you a path to the target’s build products. It is probably the same as your “$(CONFIGURATION_BUILD_DIR)” which is “$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)”. For example one of my Xcode 4 projects’ target’s has a BUILT_PRODUCTS_DIR that points to “~/Library/Developer/Xcode/DerivedData/Demo-cfkknutzmupdphdsyertfixvluca/Build/Products/Debug-iphonesimulator” or “~/Library/Developer/Xcode/DerivedData/Demo-cfkknutzmupdphdsyertfixvluca/Build/Products/Debug-iphoneos” depending on the architecture I am building for.

      In Xcode 4 all of the projects in a workspace share a common BUILD_DIR which is handy because it means that you can use the BUILT_PRODUCTS_DIR to locate the build products of the third party libraries you included in your project or depend on. Even if those libraries are referenced from somewhere else on disk and not under your application’s directory. That’s why we can use “$(BUILT_PRODUCTS_DIR)/static_library_name” to find the headers and “.a” file for a well structured static library project we depend on.
      In Xcode 3 this was not so easy. By default each project’s BUILD_DIR was a subdirectory of the project’s root so if you had a reference to some third party library project then your target’s search paths needed to know where on disk to find that library was located in order to find its build products, that’s no good and probably won’t work consistently for every developer on a project. Slightly better you can assume that you have a shared build directory to search in, search relative to BUILT_PRODUCTS_DIR, and count on every developer to change their global Xcode settings. If you’re working in Xcode 3 Clint Harris has a great guide on how to set this up correctly: http://www.clintharris.net/2009/iphone-app-shared-libraries/

  • GregH

    thanks Jonah – thats cleared many things up for me

  • http://chriskihon.wordpress.com Chris Hill

    This was *immensely* helpful. I was wracking my head against the lack of docs on what seems like an important feature! Great job on clarifying this!

  • http://chriskihon.wordpress.com Chris Hill

    Just wanted to follow up with some more info. You may notice that the library shows up as red in your app project. This is due to a bug in XCode. This will cause changes to libraries to not relink/recompile. This thread: https://devforums.apple.com/thread/91711?start=25&tstart=0 has a comment by Steven Fisher which explains how to fix this problem by manually fixing the pbxproj.

    • Juan Batovi

      Hi Chris,

      Could you please post the solution? The Apple forums are only accesible by developers enrolled in a program (my company is currently stucked in the process).

      Thanks,
      Juan

      • Jonah

        Juan, you can create a free developer account to get access to Apple’s forums immediately. You can then have your individual account added to your company’s account as a team member once the company account is approved to join the program.

        Steven Fisher’s comment is:

        Here’s one possible cause of this (there’s probably others):

        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, this is your problem.

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

        Honestly, you’re probably better off editing the pbxproj directly. Your patch will look something like this:

        Index: App.xcodeproj/project.pbxproj
        ===================================================================
        --- App.xcodeproj/project.pbxproj (revision 28061)
        +++ App.xcodeproj/project.pbxproj (working copy)
        @@ -28,7 +28,7 @@

        /* Begin PBXFileReference section */
        A7052F8F1358BFCC00178DAC /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; };
        - A74F787413566130000D0AFC /* libLibrary.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libLibrary.a; sourceTree = SOURCE_ROOT; };
        + A74F787413566130000D0AFC /* libLibrary.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libLibrary.a; sourceTree = BUILT_PRODUCTS_DIR; };
        A74F787D135665A3000D0AFC /* Macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Macros.h; path = DslExt/Macros.h; sourceTree = ""; };
        A74F787E135665A3000D0AFC /* Foundation-dsl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "Foundation-dsl.m"; path = "DslExt/Foundation-dsl.m"; sourceTree = ""; };
        A74F787F135665A3000D0AFC /* Foundation-dsl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "Foundation-dsl.h"; path = "DslExt/Foundation-dsl.h"; sourceTree = ""; };

      • Juan Batovi

        Thanks Jonah! :)

    • http://justinkent.com Justin Kent

      Happy to report that this bug has been fixed in Xcode 4.1 / Lion.

  • Jacob Reeves

    Many thanks for this article. It was extremely helpful.

    I was wondering if you’ve found a good way to include other resources along side your static libraries. I’ve got a shell script to do it, but it seems a bit like brute force. Does XCode 4 provide anything new in this regard?

    • Jonah

      Jacob, so far I haven’t seen a better solution to bundling resources with a static library. Similarly there doesn’t seem to be a good way to capture framework or other dynamic library dependencies of your static library code. I’d certainly like to see something as simple as a gem install for objective-c libraries so I’ll keep looking for better solutions or see if I can come up with a tool to handle this problem.

      • Jacob Reeves

        Jonah, thanks for the response. I’ll keep an eye out as well.

  • http://jsh.in Josh Johnson

    Wow, Thanks for this post. After spending hours trying to get this working. You provided the last piece of the puzzle. I owe you a beer.

  • GregH

    thanks – but I’m having a bit of a problem getting the static library build working – put my question here: http://stackoverflow.com/questions/6195455/why-do-i-get-these-errors-building-a-static-library-for-my-iphone-project-using-x

  • http://www.wherecloud.com Morel Sebastien

    Hi guys, this is very helpful thanks a lot.
    Everything is fine I can compile and run the app.
    I still have errors while trying to archive a project depending on a third party static library.
    xcode tells me he cannot find the headers …
    anyone have an idea ?

    • http://twitter.com/brunogama Bruno da Gama Porciuncula

      I am having the same issues to archive my project. It always throws the same build error: Lexical or Preprocessor issue: “File.h” not found.

      • Michael Waterfall

        I’m noticing this error too. The only way I can get the darn “Lexical or Preprocessor Issue” message it to disappear is to add the path to the project to the user header search paths, as the BUILT_PRODUCTS_DIR path doesn’t seem to be working.

        I *think* this resolves it! I’ve been struggling for hours with Xcode 4 and creating a static library to work with workspaces. I think I’m half battling issues/bugs with Xcode 4!

        Have you figured anything out?

        • http://www.wherecloud.com Morel Sebastien

          Hi,
          I took some times to share what I did but finally do not forget to set framework search path in the build settings. The IDE do not use this settings so everything could appear fine in xcode4 but the compiler does’nt know where to find the imported framework. Same for static library header search path …

  • Leonardo

    Hi,
    thanks for this very useful post. I have a question related to it.
    If I add another target to the static library project which build and compile into a bundle, I found it correctly compiled and placed in the built_products_dir by xcode.

    If I go to the main project and click add in the ‘copy bundle resources’, I would expect to see the static library project with its bundle, but instead only the main project is shown. The solution is to go to the derived products and copy/include the bundle. Are there any workaround on this ? Is this the proper solution ?

    thanks…

  • http://mikemanzano.com Mike Manzano

    Hi, two things:

    (1) It doesn’t seem to affect anything, but my products always show up as missing (red) because it’s set to a directory that won’t contain anything anymore. Is there a way to point the Products group at the derived products directory without setting an absolute path to it?

    (2) More importantly, I see that my static library is indeed getting build whenever I modify it and I build the dependent application. However, it seems to be linking against an older version of the library, not the one that was just built. I have to perform a Clean on the dependent application so that subsequent builds use the newest built version of the library. Not sure what’s going on here, do you?

    Thanks!

    • Victor Cottin

      Hey man, I have the same problem.

      Did you ever figure out what was wrong?
      Thanks! :)

  • Pingback: Using Static Libraries (in XCode) is Easy as Pie - OOgtech.org

  • PJC

    Thanks a lot for this information. I had been pulling my hair out and you put a smile of contentment on my face!

  • https://github.com/isaact Isaac Tewolde

    Nicely Done! I’ve used this method for my projects.

    Thank you.

    Isaac.

  • http://www.thealiraza.tk Ali Raza

    hey can we build static library in linux and use it in xcode ??

  • Pingback: The Trials and Tribulations of Leveraging a Custom Static Library in Xcode

  • SirBarrence

    Thanks so much for this tutorial!

    In XCode 4.2 beta 4, I’m finding I have to quit and restart XCode to get it to notice static lib dependencies just added to a project.

    So if anyone has this problem, before you start injuring yourself or your machine, “Have you tried turning it off and on again?”

  • Pingback: Vendor – The best way to manage iOS libraries | Miso Engineering

  • http://fsdev.net/ Chris Miller

    I’ve found that Xcode 4.1 doesn’t actually honor the “recursive” flag for user header search paths. If I drop the recursive flag, and then manually prefix all my header includes with the appropriate project name (eg. “PMSTableView/” or “FSKit/” or whatever) then it indexes fine and code completion works again. A little annoying, but you get used to it.

  • http://nets.ucar.edu/nets/intro/staff/siemsen/ Pete Siemsen

    I’m stuck in the “adding build target dependencies” step. I want to link my project to a 3rd party static library named /opt/local/lib/libcurl.a. I’ve created a workspace, added my existing project, and tried to create another project for the static library. I can create a new project named “curl”, of type “BSD C library”, product name “curl”, type “static”, but then the next step is a file selection window. I can’t select /opt/local/lib/libcurl.a because it’s greyed-out. So I just clicked “Create”. I got a new project named “curl” containing a red “Product” named “libcurl.a”. That thing doesn’t point to /opt/local/lib/libcurl.a, so I know things won’t work. I tried deleting the Product and adding libcurl.a to the curl project, but then libcurl.a doesn’t show up later in the “Link Binary With Libraries” window. Help! This is Mac OS X 10.6.8, XCode 4.0.

  • http://nets.ucar.edu/nets/intro/staff/siemsen/ Pete Siemsen

    With a few more hours of random thrashing, and some help from http://stackoverflow.com/questions/6074576/static-libraries-in-xcode-4
    I’m now in a better state, I think, but still can’t manage to build my project correctly. I have a workspace with “static library projects” that are at the same level as my main project. When I link, the static libraries aren’t found. My statics libraries are libcurl.a and libtar.a. XCode fails in the “ld” command, which has “-ltar -lcurl”, but the .a files don’t exist in the DerivedData directory specified in the “-L” option.

    I assume the .a files should be copied down into the DerivedData directory, so they can be found by the ld command. For this to happen, I assume XCode needs to know that my main project is dependent on the static library “projects”, so that XCode can do the copy. I’ve set up dependencies as described by Jonah in “Configuring the project’s scheme”. I assume this means that XCode will “build” the static library projects before building my main project. If “building” the static library projects had a component that copies the .a files into the DerivedData directory, things might work. Perhaps I’m not thinking about this correctly :-)

  • http://www.stevenhepting.com Steven Hepting

    This was just what I was looking for. Thanks so much for posting this.

  • Pingback: In xcode4 use static libraries and working area

  • Mike

    Thanks for the tutorial man, helped a bunch. Can’t imagine doing all this based simply on Apple Docs.

  • Bojan Endrovski

    Thanks for the tutorial, it has been a life saver. Works very smooth for running and testing the app.

    However, I can’t archive the app. Xcode cannot find the headers. I have done every step except “Fixing indexing” as there was no need. And the GitHub project is not available to check the setup.

    Any suggestions how to solve this?

  • Areal17

    Hi,
    Thanks! It is a real good description an very useful!

  • User

    Can you please share any sample code in which this is implemented?

  • http://twitter.com/puhalski Roman Puhalski

    Nice article, thanks!

  • Phy

    …and how do you do to archive and send to AppStore, with your method? seems it’s not working, right?

  • iOSLover

    I am new to iOS coding and is facing one issue while working with staic linking of a module with the UIAPP.
    I have static libraries compiled with llvm gcc 4.2 compiler. (using make system. I dont have corresponding xcode target for these)
    I added these to the dependency list of the project that needed the services of the static lib.
    Somhow, the application is having some functions with same name as the ones defined in static libs.
    When i compile and link. I do not get any compilation error of duplicate symbol. Can someone please throw some light on it.
    I opened the .o files of the user app and the object code used in the static lib and can see the duplicates.

    Use Case:
    Let us suppose we have UI app named “UIAPP”.
    This app needs to call functions with names A and B defined in the static lib “1.a”.
    1.a furthur needs to call functions defined in “2.a”, “3.a”.
    “2.a” needs to call functions defined in “4.a”
    So dependency goes like –

    UIAPP
    |
    1.a
    |
    ___|__
    | |
    2.a 3.a
    |
    4.a

    Mentioned below are the steps i used for static linking the lib with the user code.
    – Opened the project UIAPP in Xcode
    – Added 1.a, 2.a, 3.a, 4.a as siblings to the UIAPP project.
    – Added the path to above libraries to the “library search path” in the build setting fo the project.
    – Header files for the public interface of 1.a was added to header search path.
    – “1.a, 2.a, 3.a, 4.a” were in the “Linked Framework and Libraries” secton of the UIAPP target .And all were “Required”

    Would like to confirm, if i need to do seomthing extra to ensure i get static linking of 1.a, 2.a, 3.a, 4.a with the UIAPP.

    – I have some functions defined in the 2.a whose names collide with functions defined in UIAPP. I expect to get compilation error.
    But to my surprise, i didnt get any. But when the app was run and duplicated functions in 2.a was called(from some func in 1.a). Function defined in ui app was called instead.

  • Mikael Hellqvist

    Thanks! This was a great post and it have helped me a lot! Thanks again

  • http://profiles.google.com/fmccardoso Francisco Cardoso

    Hi Jonah,

    First of all, let me say your post was really useful to get me in to the static libs in xcode projects. I’ve used you approach and everything worked well until today, when I decided to do the dreaded Archive, that, of course, went wrong (complaining about missing headers and so on…).
    After some hours I’ve come to some conclusions (and solutions) that I would like to share with you (all). You can see them here: https://devforums.apple.com/message/605871#605871

    Cheers,
    Francisco

  • Pingback: Benedict's Soapbox » Managing Large iOS Projects

  • Pingback: app thing | Pearltrees

  • http://twitter.com/fsiaf Fotis Siafarikas

    Thanks for the post!
    Using XCode 4.2 myy project did not detect the changes from the static library.
    I found that this is a bug in XCode and the steps indicated in the following post helped me solve it.
    http://stackoverflow.com/questions/6204364/changing-the-source-of-a-static-library-needs-clean-and-build-in-xcode-4

  • Anonymous

    This article helped heaps. Seriously. Thanks for taking the time to outline the steps to use a static lib inside a workspace.

  • Pingback: [Tip] Xcode 4에서 static library 사용하기 » iOS 앱개발 세미나

  • Mark Johnson

    Thank you.

    Exactly what I needed and in easy to follow and precise steps. Thanks.

  • Pingback: Labs: XCode Static Library Pitfalls | Kihon Games

  • Pingback: Adding static library to existing project in Xcode 4. Unable to import header

  • AAA

    THANK YOU!!!

    This was so helpful!

  • Pingback: Library, Pop Tart, Static - OOgtech.org

  • Collin

    Great tutorial. Like many people in the comments, I haven’t been able to get archiving to work. It can’t find the headers. I found this and followed what it said and still didn’t get it to work: http://stackoverflow.com/questions/5543854/xcode-4-cant-locate-public-header-files-from-static-library-dependancy

    Any ideas?

  • Pingback: 在Xcode 4使用开源静态库 | 开心的舵手

  • http://twitter.com/wnadeau Winfred Nadeau

    +5 million points for being clear and thorough

  • Victor Cottin

    Thank you very much Jonah!

    My project now works but has 1 issue:
    If I change the code in the static library, I need to Clean and then Run the app.
    If I only run, the old static library code is executed…

    Same problem as Mike Manzano?

  • Pingback: How to organize C source file previously compiled by GCC Make and build them into an Xcode bundle? I have a Duplicate Symbol _main Error | PHP Developer Resource

  • Pingback: Basuke's Blog » Blog Archive » Xcode4がstatic libraryの依存関係をうまく扱ってくれない件について

  • 松柏 张

    真牛啊

  • AliGator

    Since Xcode 4.2 / LLVM 3.0 it seems that the linker bug has been fixed, so the use of -all_load / -force_load is no longer needed.

    And more importantly, you wrote that Xcode does not detect implicit dependency. This is partially right, and is due to a bug in Xcode that is really easy to fix : simply ensure that your static library added to your main project is referenced “Relative to Build Products”, and not “Relative to Group” or something simiar, which will prevent Xcode to detect the implicit dependency.

    To do this, simply select your libFoo.a file in the Project Navigator, and choose “Relative to Build Products” in the “Location” dropdown menu from the File Inspector on the right. The relative path should then change to just “libFoo.a” and your implicit dependencies will be detected.

    Note : If the relative path changed to something like “../../../[lots of dot-dot]/[lots of subdirs]/libFoo.a” or is not directly the name of your library, you may try to remove the library from your app project, change the project destination to the Device instead of an iOS Simulator, and add the library again (+ change the location “Relative to Build Products” again), that generally helps working around the bug. If you still have not luck, you can still edit the xcodeproj/project.pbxproj file in a text editor and change the relative path manually.

  • Pingback: iOS Tips : สิ่งที่ต้องทำหลัง Add พวกเครื่องมือต่างๆ | MOETOY.COM

  • Pingback: iOS Tips : สิ่งที่ต้องทำหลัง Add พวกเครื่องมือต่างๆ | MOETOY.COM

  • Pingback: xcode4中使用静态库和工作区 | Apps开发网

  • Pingback: objective-c static library intellij appcode

  • Pingback: iOS开发:xcode4中使用静态库和工作区 - 移动端设计与开发 - 开发者第1461989个问答

  • Pingback: iOS开发中 workspace 与 static lib 工程的联合使用 – easonoutlook | 查问题

  • Pingback: UsingOpenSourceStaticLibrariesinXcode4 - 移动端开发 - 开发者

  • Pingback: Objective-C 프로젝트에서 CocoaPods를 이용한 오픈소스 관리 | 라이브미디어소프트

  • Pingback: IOS - How do I add segments to NSURL? | Technology & Programming