Easy, Modular Code Sharing Across iPhone Apps: Static Libraries and Cross-Project References

by Clint on March 30, 2009

Finding an elegant way to reuse and share code (i.e., libraries) across separate iPhone applications can be a bit tricky at first, especially considering Apple’s restrictions on dynamic library linking and custom Frameworks. Most people agree that the best solution is to use static libraries. This tutorial builds on that solution, showing how your Xcode project can reference a second Xcode project–one which is used to build a static library. This allows you to automatically build that static library with the rest of your app, using your current build configuration (e.g., debug, release, etc.) and avoid pre-building several versions of the library separately (where each version was built for a specific environment/configuration).

Problem: What’s the best way to share code across iPhone projects?

If you want to reuse/share code across different iPhone applications, you only have two options (that I’m aware of):

  1. Copy all of the source code from the “shared” library into your own project
  2. Keep the shared library code in a separate Xcode project and use it to build static libraries (e.g., libSomeLibrary.a, also referred to as “archive files”) that can be referenced by your project and used via static linking.
[ad]

The first option, copying the files, should be avoided when possible since it’s inherently redundant and contrary to the goal of keeping “common code” modular and atomic. It’s a much better idea to put the code in a static library since, as mentioned in the introduction, dynamic linking to custom libraries/frameworks isn’t allowed by Apple when it comes to iPhone apps. If you’re not sure how to put your code in a static library, I’d suggest taking a look at this tutorial on the Stormy Productions blog.

So we’ve established that the second option is preferable, but there’s a catch: you’ll need to build and distribute multiple versions of the static library–one for each runtime environment and build configuration. For example, you would need to build both “release” and “debug” versions of the library for the Simulator, as well as other pairs for the iPhone or iPod device itself. How can we avoid manually pre-building and managing separate .a files?

Solution: Static libraries that are built on-demand via Xcode cross-project references

The trick to avoid pre-building static libraries for each environment is to use an Xcode “cross-project reference” so that those libraries are built dynamically (i.e., when you build your own app) using your app’s current build configuration. This allows you to both reuse shared source code and avoid the headache of managing multiple versions of the library. Here’s how it works at a high level:

  1. The shared code lives in its own Xcode project that, when built, results in one or more static libraries.
  2. You create an Xcode environment variable with a path to the directory that contains the static library’s *.xcodeproj file.
  3. All iPhone apps that need the static library will use the aforementioned environment variable to reference the library’s Xcode project, including any static library in that project and the related header files.
  4. Each time you build your project for a specific configuration/runtime environment, the shared project library will also be built for that config/environment–if it hasn’t already–and linked with your executable.

In addition to solving the main problem (reusing code and avoiding management of multiple library versions), there are a couple of nice benefits to this strategy. First, if you make changes to the shared library source code, those changes will immediately be included the next time you build your own project (via the cross-project reference). Second, you can modify the Xcode environment variable to point to different versions of any project. For example, you might have separate directories for “somelibrary-1.0″ and “somelibrary-2.0″; as you’ll see in the detailed solution instructions, it’s easy to modify the environment variable and switch your project to a different version of “somelibrary.”

Other Solutions

zerg-xcode

Victor Costan has developed a slick command-line tool called “zerg-xcode” which helps you copy the source code from one Xcode project (i.e., a static library project) into another Xcode project. In addition to physically copying the files, it inserts the targets from the “library” project into your “app” project. If the library project changes, you simply run zerg-xcode again with the approriate commands to sync the files and targets. Some people may find this tool very useful; my personal preference, however, is to avoid making any copies of the source code files and stick to Xcode’s built-in “cross-project reference” mechanism.

“Fat” Universal Binary

Another approach is to “bundle” two versions of a static library into a single file, referred to as a “fat” universal binary (see this post on the Latenitesoft blog for an example). More specifically, one version of the library would be for the i386 architecture (i.e., the Simulator) and the second for the ARM architecture (i.e., the phone). This may be a perfectly fine solution for you if you really only need two versions, or if the source code for the library is kept private. That said, you’re still left with the task of maintaining pre-built versions of the libraries (plus the extra work of bundling them into the single file). In addition, I’m not sure that you can bundle more than two versions of the library into the binary (e.g., iPhone “release” and Simulator “release”, but not iPhone “debug” and Simulator “debug”).

How to Implement the Cross-Project Reference Solution

The instructions for setting up cross-project references to shared static libraries can be split into two parts:

  • Part 1: Global Xcode Settings
  • Part 2: Project-Specific Settings

Also, I’ll be using an example in the instructions to help illustrate things. A suitable example would be an application that needs to use a shared static library from a separate project. In this case, I’ll use a sample iPhone app called “Game Skeleton” (by Matt Sephton) that depends on a static library called libcocos2d.a (which is part of an open source project called Cocos2d-iphone).

Note: If it wasn’t already clear, cross-project referencing is a standard Xcode feature and is actually suggested by Apple in the official “Xcode Project Management Guide” documentation. You can certainly get some great bits of info from Apple’s guide, but as you’d expect, it’s a high-level document (hence my thinking that this tutorial could be helpful for others).

Part 1: Global Xcode Settings

The first step in getting your Xcode project to use cross-project referencing is to configure a couple of things that aren’t specific to any one project (i.e., global settings).

Set up a shared build output directory that will be shared by all Xcode projects.

Screenshot showing how the Xcode preference dialog and how to configure Xcode to use a global build output directory.

Screenshot showing how the Xcode preference dialog and how to configure Xcode to use a global build output directory.

  1. With Xcode open, select “Xcode > Preferences” from the menubar.
  2. Select the “Building” tab.
  3. Set “Place Build Projects in” to “Customized location” and specify the path to the common build directory you created.
  4. Set “Place Intermediate Build Files in” to “With build products.”

Why is this necessary?

A brief explanation of why this is necessary might be helpful for some people. When you build your app (i.e., Xcode project) Xcode generates one or more “products” (object files, libraries, etc.) in the project’s own build output directory, by default; it will then “look” inside this directory when it comes time to link everything together and make an executable, for example.

Once you start using cross-project references, you’ll essentially be building more than one project. However, Xcode will still only look in the immediate project’s build output directory for libraries. Apple therefore recommends using a shared build output directory for cross-project references (see the last paragraph in the “Referencing Other Projects” section of “Xcode Project Management Guide: Files in Projects”). This ensures that Xcode will always be able to find products from other projects builds.

Will a shared build output directory cause problems?

I’ve had some questions from folks about whether or not using a shared build output directory causes problems. While I’m certainly not an authority on building with Xcode, I can say that in four months of using this technique (with several projects and a few different shared libraries) I’ve not had any problems (such as a “debug” build resulting in a “release” version of your library being overwritten, etc.).

Apple’s Xcode documentations clearly states that “Within the build directory, Xcode maintains separate subdirectories for each build configuration defined by the project” (see the “Build Locations“ section of “Xcode Project Management Guide: Building Products”). For example, I have a custom logging library that is used by multiple iPhone and OS X apps. The OS X versions of the *.a file show up in “Release” and “Debug” sub-directories within the common build output folder, the simulator versions in “Release-iphonesimulator” and “Debug-iphonesimulator”, and finally the device versions in “Release-iphoneos” and “Debug-iphoneos.” In other words, none of the builds seem to be overwriting each other.

Add a “Source Tree” variable that Xcode can use to dynamically find the static library project.

“Source Tree settings” are basically Xcode environment variables that hold paths to directories on the file system; this allows us to make the cross-project references flexible and avoid hard-coded paths.

Screenshot showing the "Source Tree" settings tab within Xcode preferences.

Screenshot showing the "Source Tree" settings tab within Xcode preferences.

  1. Again, open the Xcode preferences.
  2. Select the “Source Trees” tab.
  3. Create a new Source Tree variable by clicking on the “+” button and filling in the columns. The screenshot above shows that we’re using “COCOS2D_SRC” for the cocos2d-iphone variable name and that it points to “/Users/clint/dev/cocos2d-iphone.googlecode.com/release-0.5.3″.Tip: avoid using special characters in the actual file path (i.e., stick to alphanumeric characters, underscores, and hyphens); this path will be used as a “Search Path” and Xcode seems to have problems with search paths that use characters like an ampersand (&).

Part 2: Project-Specific Settings

Once you’ve got Xcode configured to use a global build output directory and have a “Source Tree” variable pointing at your shared project, you’re ready to set up the cross-project reference, dependencies, etc.

Set Up the Cross-Project Reference, Header File Search Paths, and Static Library Linking

  1. Open your project in Xcode.
  2. In the “Groups & Files” pane of Xcode, select your project root and hit Option+Cmd+A (add to project).
  3. Find the Xcode project package for the project that contains the shared library. Using our example, we’ll select the Cocos2d-iphone Xcode project (cocos2d-port.xcodeproj):

    Screenshot showing a second Xcode project file being selected so that we can add a reference to it.

    Screenshot showing a second Xcode project file being selected so that we can add a reference to it.

  4. When the “Add to Project” dialog is displayed, use the same settings displayed in the screenshot below and click the “Add” button.
    Important: do NOT check the “Copy items” box.

    Screenshot showing which "add to project" options are selected when adding a cross-project reference in Xcode.

    Screenshot showing which "add to project" options are selected when adding a cross-project reference in Xcode.

  5. After you click the “Add” button the project will appear as a “sub-project.” In our Cocos2d-iphone example, it looks like this:
    Screenshot showing how the Cocos2d-iphone Xcode project appears as a "sub project" once it has been added to the main "Skeleton" project.

    Screenshot showing how the Cocos2d-iphone Xcode project appears as a "sub project" once it has been added to the main "Skeleton" project.

    Remember that you have not imported a physical copy of the second project–it’s a reference.

  6. When the cross-project reference appears select it and hit Cmd+i. Then change “Path Type” to be relative to the environment variable you set up in Part 1. In the example below, we’re using the COCOS2D_SRC variable:

    Screenshot showing the Xcode "Project Info" dialog for a project added via cross-project reference.

    Screenshot showing the Xcode "Project Info" dialog for a project added via cross-project reference.

Configure the Library Dependencies, Linking, and Header Files

  1. In the “Groups & Files” pane of Xcode, under “Targets”, select your main app target and hit Cmd+i. Then select general tab and add the static library(ies) your app needs from the shared project by clicking the “+” button under “Direct Dependencies”. In our example, we’ve added the “Chipmunk” and “cocos2d” libraries which are both built from the Cocos2d-iphone project:

    Screenshot showing an Xcode executable target being configured to depend on static libraries that are built from a cross-project reference.

    Screenshot showing an Xcode executable target being configured to depend on static libraries that are built from a cross-project reference.

  2. Click on the build tab and scroll down to the “search paths” section
  3. Important: If a hard-coded path to your shared project appears in the “Library Search Paths” field, delete it. This can be done by double-clicking the field and using the “-” button.
  4. Double-click on blank area next to “User header search paths”. Then click on the “+” button, check the recursive checkbox, and type in the Xcode environment variable that points to your shared project directory, surrounded by $(). The example screenshot below shows $(COCOS2D_SRC) being used:

    Screenshot showing how to configure the Xcode "User Header Search Paths" for a library that is being included via cross-project reference.

    Screenshot showing how to configure the Xcode "User Header Search Paths" for a library that is being included via cross-project reference.

  5. When you click OK and go back to the Build tab, the “user header search paths” text field should show an absolute path to your shared project directory. In our example, $(COCOS2D_SRC) expanded to the actual path and ends with “**” to show that the search will be recursive:

    Screenshot showing how an Xcode environment variable will be dynamically expanded to the actual, absolute path once entered using the $() notation.

    Screenshot showing how an Xcode environment variable will be dynamically expanded to the actual, absolute path once entered using the $() notation.

  6. Finally, click and drag the static libraries from underneath the cross-project reference to “Targets > {your target} > Link Binary with Libraries.” This ensures that that the .a files will be passed to the linker when you do the build. Here’s a sample screenshot from our example app:

    Screenshot showing how to link your executable to the static libraries via cross-project reference in Xcode.

    Screenshot showing how to link your executable to the static libraries via cross-project reference in Xcode.

Summary

To recap, if you need to share code across different iPhone projects I suggest 1) putting the shared code in its own “static library” Xcode project and 2) using a cross-project reference so that you can build the library with your own app as needed. The verboseness of this tutorial might give you the impression that setting this up is a lot of work; it’s not, really, especially if you do it more than once (which is likely, considering that the goal here is to share code across multiple projects). I’ve been using this approach for about four months with several projects and it’s definitely saved me a lot of time. Finally, there might be a better strategy that I’m not aware of; feedback and suggestions for alternate solutions are certainly welcome.

Clint Harris is an independent software consultant living in Brooklyn, New York. He can be contacted directly at ten.sirrahtnilc@tnilc.
  • http://galileo-app.com Evgen Bodunov

    There is more simple way to do that:
    1. add reference to xcodeproj file in your project (in Frameworks for example)
    2. double-click on target and open general tab
    3. add library bundle target in direct dependencies list.
    4. drag and drop libLibName.a from xcodeproj reference (in you Frameworks) to “Link Binary with Libraries” folder of your target.

    that’s all.

  • http://galileo-app.com Evgen Bodunov

    oh. i miss step 5.
    5. in project configuration add path to your library headers into variable “user headers path”

  • Pingback: Confluence: Petter Tiilikainen

  • Tony John

    Really helpful.

    Is there any way to set break points in side the static library project so that we can debug it. What happens when the project gets built, first it builds the library and makes .a file out of it. So XCode ignores the break points. How do we debug the cross referenced project?

  • http://blog.costan.us Victor Costan

    I figured out how to build static libraries that package the simulator and device code into a single file. This can come in very handy when distributing your static libraries. Read my blog post for details.

  • http://blog.costan.us Victor Costan

    @Tony: that’s one of the reasons why I include the library source code in my application projects. You can read about my method in this blog post.

  • Pingback: cocos2d Part1 « myCodeStudio

  • http://ghosthandgames.com/ chief

    Just wanted to thank you for this article. I hit a few snags, but worked through them. If your Source Tree’s path includes spaces you have to quote it (“Users/chief/iPhone Projects/test”). Otherwise this worked like a charm. Thanks again for sharing!

  • Martin Kovachev

    We are using pretty much the same type of technique over here to handle a shared part of a mac / iphone application – all in a single static library.

    So far it was running ok, but recently we’ve moved to Snow and the new SDK’s and we found the need to use Universal binaries to ship 32/64 binary in a single package.

    What we did is select universal binary project option in both the static library – and the project that uses it itself.

    Both the project and static library have two profiles – Release / Debug (I am assuming that when i build the project – the static library is somehow – magically switching to the same profile as the project itself, because there are no options to select this within the project – for a specific static library project attached to it).

    The problem is that when building starts – we get that static library blablabla – is of an incompatible architecture.. duh? Wasn’t it supposed to build all necessary linking objects for an universal binary and figure out a way to link them?

    Anyone having the same problem?

    How do you build an universal binary with static libs attached to the project?

  • Pingback: Samuel's Project Nash » Blog Archive » ????? iPhone ?? ??? 1 – Cocos2D for iPhone ??

  • Pingback: iPhone Development and Code Reuse « mattsoftware

  • Pingback: links for 2010-02-02 | Visualrinse | Design and Development by Chad Udell

  • Quentin

    Does anyone have it working with Xcode 3.2 ? ’cause i remember i had it working months ago, but not anymore.

  • http://web.mac.com/dbolli Derek Bolli

    @Quentin
    I updated my linked Xcode project with cocos2d-9.0-beta2 and it compiles using Xcode 3.2.2 with the iPhone 3.2 iPad beta

  • Quentin

    Hello,

    Ok, wrong try from me. I think i had something “broken” in my project paths, because i created a new project and it works now.

    Thank you for your quick reactions guys.

  • http://www.inadaydevelopment.com/ Kenny Wyland

    I want to have your babies. I’ve tried a couple of other tutorials on how to get this working, but they’ve never worked for me. Not only is this one working, but the instructions were far more simple than the other sites!

    Thank you!
    Kenny

  • Pingback: In A Day Development » Blog Archive » Using another XCode Project as a Static Library

  • http://gordonknight.co.uk/wordpress Derek Knight

    Great tutorial. I’ve been using XTool for two weeks now and am having a lot of minor problems (I have used Visual C for 20 years!). Tutorials like your, which are so clear and easy to follow and a god-send.

    Thanks a lot
    Derek

  • http://gordonknight.co.uk/wordpress Derek Knight

    Twit, Derek. You can probably figure out what I meant. “Tutorials like yours, which are so clear and easy to follow are a god-send”. Doh!

  • Pingback: Static libraries in Xcode « I am Tyler

  • http://www.Pixels4Charities.com Pixels 4 Charities

    Hi, I can’t quite seem to figure out how to include and access a function in the static library. I followed the steps perfectly and the application builds fine (without any calls to the library).

    But now I want to actually call something and it says “TestLib.h: No such file or directory”

    I tried #import, #include, , “clsTestLib.h” and every combination. I even added the the -ObjC and -all_load Linker flags to the Project BUILD settings and no luck.

    Any ideas?

  • http://www.Pixels4Charities.com Pixels 4 Charities

    I had a user error. The tutorial is awesome but I guess I did something incorrectly. After no luck, I decided to create a new project and re-follow the steps. This time is worked out great. FYI for others who might not know, this should work with:

    #include “clsStaticLib.h”

    if you followed the steps correctly.

    Thanks again!

  • Dean P

    First off I’d like to join everyone else in commending and thanking Clint for producing a well written and concise article that has helped us all greatly.

    Next I’d like to pose a question, to both Clint and others, regarding the role of headers. From my understanding there are 3 options, Project, Private and Public. The first ‘does as it says on the tin’ making a header only accessible to the project code (that within the static library) therefore omitting it from being copied over in the build process. The result is that the project (our app) that uses the static library won’t have access to them. The second two options both copy over the header(s) and only differentiate by where they are copied to using the build settings PRIVATE_HEADERS_FOLDER_PATH and PUBLIC_HEADERS_FOLDER_PATH respectively. The Apple documentation on the matter seems to suggest this is a way of suggesting those headers ready for end user use and those currently in development that should perhaps be restricted to either ourselves or our direct collaborators.

    Having the followed the tutorial with great success I gather using the Xcode environment variable and the recursive option will provide us access to both ‘types’ of headers unless we pick to place either of them in an obscure location outside of the path covered by the environment variable (bad idea).

    So what, if any, strategies do people use to exploit some of the functionality we could gain from differentiating between the private and public headers of our static library? For instance is it possible to leverage this in such a way that only certain parts of our code using the static library have access to the private headers? Could this be achieved with a more descriptive (but less enforced) paradigm by which including a header requires specifying the final folder of the path. e.g.

    #include “private/foo.h”
    #include “public/bar.h”

    Therefore any file/code/object in our app *could* use a private header, but we would be aware we were doing so at the point of import.

    Thoughts fellow iPhone-ians?

  • Dean P

    As an addendum, it seems that regardless of the role set for a header all headers remain accessible to the code that uses the static library. For instance using the procedure outlined by Clint, try adding to the static library three headers, each with a simple macro, each marked as having one of the three different roles (project,public,private). e.g.:

    myPrivateHeader.h (role is private)
    … containing …
    #define myPrivateMacro(i) (i + 1);

    My understanding was that code outside of the project would only have access to private and public marked headers and only then based on how the header search path aligned with the relevant HEADERS_FOLDER_PATH. Project marked headers remained accessible only to the project in which they’re declared (i.e. the static library project). However from my app, I can quite happily execute the macro declared in the header marked with role ‘project’ in my static library:

    myProjectMacro(10)

    Is this because using a cross-project reference makes the ‘project’ the one using the static library, not the one containing the it?

  • MS

    This is a great guide, thanks. But one problem I noticed after setting up a shared project directory as suggested has to do with my unit testing targets.

    I have a static library project with a unit testing target that is run whenever the project builds.

    I have an application project that has its own unit tests and a cross-project reference to the static library project.

    With a shared build directory, when I build my application project, the static library’s unit testing target actually runs the unit tests from the application project, which results in the application project’s unit tests being run twice, and the static library tests are never run.

    For now I’m using separate build directories and have not seen any problems (though I’m only coding and compiling at this point, not running anything in the simulator yet, or doing any release builds). So I’m curious to know when I’ll have the problem that Xcode won’t “be able to find products from other projects builds.”

  • Mike

    I just wanted to say thanks! I didn’t want to use their template but was having issues using the cocos2d in my existing project and this helped greatly.

  • http://www.learn-cocos2d.com GamingHorror

    I made a cocos2d Xcode Project Template partially based on this article and of course using the latest cocos2d version (0.99+). Then i added a ton of other features (various build configs, IPA building, proper debug stripping, targets for debugging memory crashes, etc). All the things i need for my professional Xcode project work on a daily basis.

    The result is a 100+ page cocos2d Xcode Project setup Tutorial:
    http://www.learn-cocos2d.com/knowledge-base/tutorial-professional-cocos2d-xcode-project-template/

    I hope you don’t mind the shameless plug.

  • Pingback: How to setup Xcode to share code across iPhone projects « Kimptoc

  • B2

    Nice article, and I went through the same issues about the same time you did. Here is the problem I’ve just discovered.

    I am using xcodebuild. My app has PRODUCT_NAME set to a user-defined build setting, MY_NAME.
    Its target has a project reference to the project that builds my static lib ORIG . When xcodebuild is launched with:
    xcodebuild -configuration … MY_NAME=foo
    it looks for libMY_NAME.a instead of libORIG.a, doesn’t find it and rebuilds the static lib as libMY_NAME.a

    This is happening because PRODUCT_NAME is being used by the static lib target to build its output name and it is getting overridden.

    Any idea about how to stop this from happening? I’m losing all the advantages of a static lib just because I want to vary my app name at build time.

  • Michael

    Fantastic article. Thank you so much for taking the time to write and share this information. Until now I’ve never been very aware of what static libraries are and how to properly integrate them.

  • Joe Falo

    Great tutorial, Clint. It worked initially but then I ran into the same problem that Mathieu ran into. This especially became a problem when I have a static library that uses another static library (both of my own making). I read somewhere else about the solution being to change the name of the project directory. This also worked initially but at some point, adding files, etc. it gets stuck… “No such file or directory”. You change the name of the library’s directory and set the Source Trees environment variable to match, it works. Only to break later when adding more files to the project. And curious enough, once it breaks on a directory name, you can’t use it again: you have to pick something new. I know it sounds crazy. I can only think that there is something in the project that gets corrupted. I am following instructions to the letter. I’d love to use this technique instead of copying files around. If anyone has a clue about this, please let me know. P.S. I’m fairly new to Apple computers and iPhone development.

  • http://ivanceras.blogspot.com lee

    Hi,
    I see that the article focus on sharing code between iphone apps, is there a way to do this on projects between iphone apps in which the same source code will also be used in a custom command line project in cocoa OSx?

  • http://www.MarkDonohoe.com MarqueIV

    Ok… I’ve got a tough one. The app compiles just fine and runs just fine… until I try to load a XIB file that references one of the UI classes in the static library. This class exists in the XIB only and doesn’t have any outlets in the code file itself. (Even so, I manually added an outlet just in case to see if perhaps the class was getting optimized out.) However, no matter what I do, the XIB file will not load saying it can’t find the class.

    I’ve tried the -objC linker flag, I’ve tried every other thing I’ve found here in all of the comments, but nothing.

    On a side note, what I ended up doing was just adding (not copying, but adding a reference to) a folder containing all of the static library’s source files themselves (actually, at this point, it’s not technically a project anymore but just a ‘shared code’ folder with .h, .m and .mm files, plus a few resources in it and of course a main ‘someLib.h’ file that pulls in all the other headers), then just setting the target membership for the ones that I’m actually using in the product. That worked first time and also doesn’t create copies of the source files, plus it has the added benefit of not having extra code added to the main application from the static library that isn’t actually used by the application. My static library had an ‘a’ file of 450KB but the compiled app when doing it this way was only 87KB. That’s a huge savings. (Granted I don’t know how ‘bloated’ the .a files are, but that’s still significant if you ask me.)

    Another benefit is you just edit the ‘library’s’ files right in the one project. You don’t need a second instance of an Xcode window open. And finally, there’s only the build path of the executable itself.

    Of course this approach has one major downside of you manually having to select each and every file you *do* want to use while excluding those you don’t, but at least this ‘library’ only has about 30-40 files in it so it isn’t that bad. I do however see the appeal of Clint’s approach for much larger projects.

    Another tip, in the project tree, right-click on the headers and just choose ‘Target Membership’ You’ll get a nice list of checkboxes on the left that make it very easy to select what gets compiled and what doesn’t. It also lets you select target membership for the .a files so you don’t need to drag them to the target’s ‘linker’ phase. It’s automatically added there.

    But back to the original point. Anyone know why my XIB wouldn’t load the class from the static library in the first place?

  • http://www.bestfinance-blog.com Louise22PARKS

    Buildings are not very cheap and not everybody can buy it. Nevertheless, home loans are created to support people in such kind of situations.

  • Pingback: Upgrading cocos2d version | XPerienced Blog

  • Dennis

    I ran into the same thing as MarqueIV. I followed Clint’s directions for a previous external project and it worked fine. However, this time I am user Super Rewards SDK (which I believe has static objects) plugging it into my own project. When I compile I get this error:

    *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘-[UIViewController _loadViewFromNibNamed:bundle:] was unable to load a nib named “SROfferView”‘

    For some reason the project is looking to the Nib locally rather than the externally linked project. I added the Nibs to the local project and they worked – but ran into other issues.

  • Dennis

    FYI – problem was fixed similar to Marque’s. I had to add the nibs & any images in the project. I didn’t copy them over but merely linked them and it worked.

  • Pingback: iPhone Static Libraries « Macgix's Weblog

  • http://appsinmypocket.com John

    Previously, I had my static library set-up in a different way that meant the library was not re-built automatically. I followed the clear steps in this blog and my static library does now get built automatically. I then hit another issue. I use a third-party library as is (just have the .a file, no source). Previously this always worked fine. To get the above to work though I had to leave the Library Search Paths blank, this meant the third-party library could no longer be found by the linker. Eventually I managed to overcome this by editing the “Other linker flags” option to include the full path for the file.

    One other tip would be to remember to select “All configurations” when you start making these changes.

    Many thanks for this blog. It still amazes me that something as basic as having your own library is so complicated in Xcode.

  • bob

    Unfortunately, I had everything setup and building, but for iPhone development there are problems with this approach.

    If you subclass any UIKit types and have them in a referenced project, interface builder will no longer see your subclasses of these types and you will not be able to for example set the files owner in IB to a subclass of UIViewController.

    Also, if you are using classes with rely on notifications, there are problems with those classes being invoked properly in the simulator if they are built in a static library. For example, if you package reachability (a common code found in iPhone apps) into a class which encapsulates its functionality and registration – it will not work from a static lib – I assume that means there are many others that wont work.

    So this is a nice approach and I tried it setup all my shared code in this way and it all built fine. but done expect your iphone app to run if you subclass UIKit types for common code and have them in a shared library. Or you use classes which register themselves for iPhone notifications.

    Im sure there are more problems. I think this really has to do with the funkyness of the build system for iPhone and probably would not affect Mac apps but I cant say for sure.

    Anyway, best approach if you want something to work every time, is to take your common code and put it into a template project (described on other blogs) and when a new project is created that code will be there. You can organize it however you want and you will not have build dependencies. If you change common code merge it back and merge the code from common shared as you need.

    This is incidentally actually a much safer way to share code since you cant really have dependent builds changing underneath you during development anyway.

  • http://appsinmypocket.com John

    I have lots of subclasses of UIKit in my library and it all works fine with IB. However, there is something you need to do in IB that maybe you’re not aware of. You need to get IB to read in the classes you want to use. Under the File menu choose the “Read class files” option. You need to select all the header files you want to use from your library. IB doesn’t seem to keep track of this very well, so sometimes you need to get them to read them in again.

    Hope this helps. This is a guess, but I’d check that you are referencing the header files you need for the notification to work.

  • Pierre

    Just a little word about path names… I am relatively new in XCode and Mac environments and i was struggling with trying to get static libraries working.

    After doing exactly what this tutorial was teaching, it still wasn’t working for me…

    After a couple of hours searching, i found out that:
    - the separator for multiple path names in User Header Search Path (and others) is whitespace
    - somewhere in the many directory names in my path name for the project of my static library, there was a whitespace!!!

    So the effect was that the compiler didn’t find the header files and couldn’t perform compiling at all. I had an error message stating that my class from my static library was not found…

    So, BEWARE of whitespaces !!!

    Is there any way of preventing this when using source trees variables ?

    Thanks and hope this will help someone…

  • http://web.mac.com/dbolli Derek Bolli

    @Pierre

    Putting “quotes” around the path in Xcode->Preferences->Source Trees works

    Also works for paths directly in Target->Build->User Search Paths etc.

    Regards,
    Derek.

  • Pingback: Objective-C Logging with SOSmax at Labs

  • Pingback: Why are static library headers not found? - Question Lounge

  • http://www.tinkerbox.com.sg Jaryl Sim

    This has been working great for me when working with Cocos2D but when I try to use Box2D, I am running into a wall. Just including the header is problematic:

    #import “Box2D.h”

    This is the error that I am getting:

    error: Box2D/Common/b2Settings.h: No such file or directory

    In the static library, it is compiling fine.

  • http://www.logikstate.com Paul Carter

    You need to setup the header search paths of the main project.

    This is programming 101

  • http://www.tinkerbox.com.sg Jaryl Sim

    I already set the search paths up, otherwise Cocos2D will not compile so thanks for response but that is not the problem. If you have no experience working with what is asked in the question then do not answer.

    To get it to work, I had to check the ‘Always Search User Paths’ setting.

  • Pingback: Enlaces iOS | Sináptika

  • Pingback: Confluence: SpiderLogic - Mobile Practice