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://blog.costan.us Victor Costan

    Dear Chris,

    Thank you so much for your post!

    I wasn’t completely happy myself with copying files between projects, and I was researching using hardlinks or symlinks instead of copies.

    That aside, I’m wondering how you would advise to apply your method in an environment where source code is under version control, and developers can check out the code at arbitrary locations on their filesystem.

    Thanks!
    Victor

  • https://clintharris.net Clint

    @Victor Costan: Thanks for the feedback! Good question regarding using this method in a team environment with source control. In a nutshell, it seems to work just fine–I’ve personally used this strategy on projects with more than one developer, where each developer checks out the code to an arbitrary filesystem location. Neither the “shared build output directory” nor “environment variable” settings (as described in “Part 1. Global Xcode Settings”) are stored in the *.xcodeproj package that usually goes into source control. Each developer will configure these settings for his/her own instance of Xcode.

    In the example I use in the tutorial, the project.pbxproj file (i.e, the main Xcode project meta-data file inside the *.xcodeproj package) only contains references to the COCOS2D_SRC variable; the actual path to the directory where I’m keeping the cocos2d project doesn’t show up in the file. Similarly, my shared build output directory doesn’t appear in the project.pbxproj file, either. Those global settings are only stored on my machine and don’t go into source control.

  • Steve Johnson

    Hi Clint – thanks for the article. I also have a question relating to multiple developers with different checkout structures.

    In our case, our common library root folder will always be a sibling of our parent folder. So:

    Developer/svnroot/trunk/common/mylib is where the library project will be.
    Developer/svnroot/trunk/apps/myapp is where the app project will be.

    Couldn’t I specify “relative to project” for all of my path settings and not need to use the Source Paths or Environental Setting? This way, once a project is set up, the other developer only needs to check out at “trunk” and all is well??

    I haven’t tried any of this, just trying to sort it out ahead of time.

    Thanks,
    Steve

  • https://clintharris.net Clint

    @Steve Johnson: I totally agree with you. In a scenario where the relative path between the “project A” and “project B” is constant on everyone’s machine (e.g., both projects are part of the same version control checkout) you should be fine with using the “relative to project” setting for the project reference (i.e., as opposed to “relative to SOMELIB_SRC”).

    Thanks for pointing this out–could be really helpful to some folks.

  • Sean

    Perfect, Worked like a charm. I don’t have to keep flipping back and forth between builds it automatically builds the right library for my target. You are going to save me a lot of time.

  • http://www.paulsolt.com Paul Solt

    Thank you, I’ve mostly worked with Visual Studio and was looking to do something like this in Xcode for the iPhone. Your guide is a good reference.

    I’m using the setup with multiple targets that use different versions of a library and it’s nice to have everything build and link properly.

  • http://www.spy.org Scott D. Yelich

    Working my way through this… I’d also like to get to the point where just adding the libX.a to a project is as simple as shown in the facebook connect demo video. I understand here that we’re building the lib each time… so this is good for when that is needed.

    Step 5:
    When you click OK and go back to the general tab, the “use …
    perhaps:
    When you click OK and go back to the *build* tab, the “use …

    ok, yup… build > clean all targets on the static shared lib xcode project and build clean on test project … build and go on test project built the static library (although I had to update the static lib xcode before the libX.a went from red to black) — I just switched from device to simulator — it seems both get built (even when just building the test app for the simulator).

    Thanks!

  • https://clintharris.net Clint

    @Scott D. Yelich: Thanks for the feedback! I’ve updated the post with your proposed edit for Step #5 (good catch!).

  • http://www.notionforge.com Santthosh

    Thank you very much, I was also not happy replicating code and this approach came in very handy. I actually used Keremk’s iPhone Static Library project template to build the static library, this reduced the trouble in setting up the common library.

  • ramzez

    Hi, is there a way to share Macros across the project as well?

  • Pingback: warpedvisions.org :: Link: XCode Static Libraries and Cross-Project References

  • https://clintharris.net Clint

    @ramzez: Yes–you can share macros the same way you would in any other situation (e.g., by putting something like “#import file_with_macros.h” in your code). For example, I have an Xcode project for a custom logging tool I made; the project is built into a static library and there are also a few macros defined in some of the header files. All of my apps which reference the logging project (using the steps in the tutorial) can use those macros as long as I #import the correct header file. In my case, I use the logging macros everywhere so I #import the logging header in each project’s .pch file (i.e., every file in the project has access to the logging header and the macros it defines).

    In other words, if you just want to share C macros there’s really no need to go use the approach described in the tutorial.

  • ramzez

    @Clint, hmm, we thought about it however our code base is about 20 years old and modifying thousands of files to just include a header file with macros is not really a solution for us.

  • Max MacLeod

    Thank you so much Clint. This has saved me days of frustration and pain without a doubt. You are the man!

  • http://www.letstalkiphone.com Kyle Davis

    Wow, this is unbelievably useful. Thanks for this!

  • http://www.mozartbrain.com frankmail007

    Great article. But I have problems. Here is my description:

    My project structure:

    Projects—CompanyName—externalLib
    —lib
    —project 1
    —project 2

    First of all, I didn’t set source tree because I’m using relative path and I didn’t set the shared output path because I’ll set the build path to different companyName’s lib. I followed every other things in your article.

    My problem is I still get the link error to link to my externalLib. The dependency check works and external lib is built inside the lib directory. But the funny thing is the library for example libexternal.a is always shown in red color. It looks like it has never been built. I think that’s why I got the linkage errors. But I don’t know what happen? Do you have any clue.

    Thanks very much,

    Frank

  • Pingback: Let’s Talk iPhone » Tic Tac Toe in Cocos2D

  • ramzez

    My biggest problem with Xcode is freezing and slowness. what i have is a project which has 39 static libraries defined as targets from on big source tree. I build for iphone. Each time i start Xcode or change between Simulator or Device it takes ages on Checking Dependencies stage and then starts to recompile all the libraries, although they are all built already.

    If anyone knows a solution to this, i would be really grateful.

  • ramzez

    @frankmail007

    try hitting Cmd+I and see what the path it things the red coloured library should be…

  • Max

    Hi Clint,
    got a question for you. Assume I have three static libraries, A, B, and C.

    A depends on B, and B on C.

    In xcode, assume I have project A open.

    It seems I also need to have B and C as subprojects.

    I would have hoped that I just need B. That it would know that B has a dependency on C.

    Any thoughts?

    Cheers,
    Max

  • Max

    OK I think I have figured this out. I need to point to both B and C.

    By the way I have encountered a bizarre problem. When I mark the static library to include “recursive” in the user header search path, sometimes it doesn’t find it.

    I mark that entry non-recursive, and it finds it ok.

    Only seems to happen with one library.

    Quite strange. Must be a good reason for it…

  • http://www.silicon-studios.com Nonnus

    hi,

    awesome piece of info you got here !
    i got lost for a while until i remembered i had spaces in some folder names on the shared build path so all worked seamlessly as soon as i unescaped them, i hope this tip is helpful for anyone in same situation

    i am just missing having the header files available on the target app using the library,
    what is the best way to have them available like the sdk framworks do ?

    abraços

    nonnus

  • Alexei

    I have tried this approach and while it builds just fine, I am running into a weird problem with some of my methods optimized out when the library is compiled. So, when I run the app, it throws an unrecognized selector exception.

    Any ideas?

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

    @Alexei: try adding -ObjC to “Other Linker Flags” in the Build options for the binary (not necessary for the library).

  • Alexei

    Yes, -ObjC worked. Thanks a lot!

  • http://www.creativeclasssoftware.com David Roach

    I love this article, great job!

    I have two such libraries that I have developed and this method is similar to that of Visual Studio.

    My question to you is, is there a way that if you are doing adhoc development of a library at the same time you are developing an application, can you have both source trees appear in Xcode. Right now all you get is the lib reference.

    Kind regards

    David

  • Max

    Hi David,
    I reckon you could just import the other source. Then set up two different targets in your workspace. One to generate your static library and the other to generate your executable.

  • http://www.iphonearch.com Iphone Architect

    nice tutorial, thanks
    i’ll try to implement Victor’s solution with zerg-xcode

  • Paul

    Thanks for the great tutorial!

    One note from my own experience was that to use some of the Dynamic Binding capabilities of Objective-C (in particular the NSClassFromString method) it was necessary for me to include the -ObjC compile flag in the build settings of both targets.

    I also had two questions: 1) What is the best way to share a CoreData project as a library between multiple projects?

    2) Is there any way to share NIB’s between multiple iPhone projects?

    Thanks again,

    Paul

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

    This is fantastic!

    I would never have figured out how to do this without this tutorial.

    Many many thanks

    Paul.

  • Pingback: LB Technology Services Blog » Blog Archive » Sharing code in iPhone applications

  • Mathieu

    Hi Clint! That’s an awesome tutorial, thanks an lot.
    I’m just a beginner at iPhone / Xcode programming and I managed to implement all what you described.

    However, I still have a problem I can’t figure out. It’s about headers importing… Well I try to import cocos2d.h in a .m file, but then the project won’t build (“no such file or directory”).
    It seems that Xcode refuses to actually search into my user header path.

    I tried #import and #include, and “cocos2d.h”.
    I used the source tree variable (recursive) for “User header search path” and “Header search path” in project and target preferences, for all debug and release configurations…

    Not working…

    I tried to address the complete absolute path directly in the import and then it works, but all subsequent headers are then not found.

    If I copy the header file in my classes path, it is found, but same error, all other subsequent headers are not found.

    I verified the path I entered for COCOS2D_SRC and it fits with the actual path so I’m running out of solutions…

    Well I’m becoming crazy now, so if someone can help!

    Regards,

    Mathieu

  • Pingback: Cocos2D Game Engine

  • Pingback: 11 Cocos2D iPhone Game Engine Resources | iPhone Development Tutorials and Tips

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

    Hi Clint,

    Thanks for the great article, I have successfully repeated the steps above with the latest cocos2d-iphone-0.8-rc2. I didn’t need the shared build output directory step as I am happy to re-build the cocos2d project from time to time but the above will save me a great deal of time when updating my cocos2d-iphone projects when new releases are updated (which is often thanks to the pace at which cocos2d-iphone team is developing the product).

    With regard to Mathieu’s question above, I had the same problem and it was due to spaces in the path in the COCOS2D_SRC source tree xcode preferences setting (as mentioned in the article in the source tree variable tip) which I solved by adding a relative path i.e. ../cocos2d-iphone-0.8-rc2 rather than /Path/to/my/dev/dir with spaces/cocos2d-iphone-0.8-rc2. Have a look in the build commands transcript area of xcode project Build Results and you’ll probably see a mangled path e.g. -iquote /Path/to/my/dev/dir -iquote with -iquote spaces/cocos2d-iphone-0.8-rc2. If your xcode project folder is in the same dir as cocos2d-iphone-0.8-rc2, you can use a relative path as above.

    Thanks again for the great article :)

    Regards,

    Derek Bolli, Head Hacker,
    Bolli World HQ Computing Facility,
    North Sydney NSW 2060
    Sydney, Australia email: dbolli at bigpond.net.au (home)

  • Pingback: Confluence: AKQA Mobile

  • Pingback: Confluence: AKQA Mobile

  • tonton

    that ‘s a great job , thanks for all your job
    fyi i had some problems with the intermediate build path (xcode global settings) then i put the same absolute path (= build product location )

    when using that config i dont need step 6 (Finally, click and drag the static libraries)

    is it a better way or i missed sthg?

  • Pingback: Running the Cocos2D examples

  • Pingback: Confluence: Brad Brooks

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

    Hi Clint, just an update to say that your tutorial saved me more than an hour today updating my cocos2d xcode projects from v0.8-rc2 to v0.8. All I had to do (after I’d downloaded and expanded cocos2d v0.8 into the same parent folder as my xcode project folders) is:
    Edit Xcode->Preferences->Source Trees->Path from ../cocos2d-iphone-0.8-rc2 to ../cocos2d-iphone-0.8
    Delete linked project cocos2d-iphone-0.8-rc2.xcodeproj
    Project->Add to Project cocos2d-iphone-0.8.xcodeproj from ../cocos2d-iphone-0.8
    Add cocos2d Direct dependencies in Target->General tab
    Drag static libs from under cocos2d-iphone-0.8-rc2.xcodeproj to Target->Link binary with Library
    Clean All
    Build and Go

    Great work, thanks again :)

    Derek Bolli, Head Hacker,
    Bolli World HQ Computing Facility,
    North Sydney NSW 2060
    Sydney, Australia email: dbolli at bigpond.net.au (home)

  • Jayant

    Wondering if anyone has had success getting Categories to work. So I have ‘MyStaticLib’ (Cocoa Touch Static Library) project which is referenced in ‘UsingMyStaticLib’ (View-based application) project, using the steps in this post.

    MyStaticLib: TestClass & NSObject+MyCategory with (void)time & (void)printTime respectively.

    In ‘UsingMyStaticLib’ I reference ‘MyStaticLib’ and reference the 2 header files. My test code:

    TestClass *test = [[TestClass alloc] init];

    if ([test respondsToSelector:@selector(printTime)]) {
    NSLog(@"ok we're in business!");
    [test printTime];
    }
    else {
    NSLog(@"sorry, no go!");
    [test time];
    }

    [test release];

    The code above always goes to the ‘else’ block and prints the time using the TestClass’s own selector. If I remove the conditional block and call the printTime method anyways, the app crashes.


    UsingMyStaticLib[959:20b] *** -[TestClass printTime]: unrecognized selector sent to instance 0xd17570
    UsingMyStaticLib[959:20b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[TestClass printTime]: unrecognized selector sent to instance 0xd17570'

    Any ideas on what I might be doing wrong? Please help!

  • Jayant

    The -ObjC option in ‘other linker flags’ solved the issue, thanks to ‘Victor Costan’ for that. And thanks to Chris for this awesome article. Cheers.

  • Pingback: Let's Talk iPhone » Tic Tac Toe in Cocos2D

  • http://www.seqoy.com SEQOY

    One nice tip: If when you import the .xcode project to your own project.

    All the links are broked (red). Probably you forget to build all the libraries on the project your are importing.

    Work for us. All the best.

  • Brad Parks

    For anyone who’s interested in implementing this with Cocos2d, a user on the cocos2d forums (thanks tjweir!) put together a nice project template with this already integrated

    http://github.com/tjweir/cocos2d-application/tree/master

    Brad

    PS: The thread I found it in is here:

    http://www.cocos2d-iphone.org/forum/topic/213#post-1155

  • ramzez

    how to share pre-processor definitions (macros) across different projects? i.e. if i want to setup pre-processors only in root project but so that they are picked up by static libraries projects?

  • Pingback: Getting Started with the Cocos2D Game Engine

  • BG

    Very helpful!

    FYI: While doing this, I had a weird issue with a missing symbol (___restore_vfp_d8_d15_regs) that I resolved by compiling the library with GCC 4.0 instead of GCC 4.2. This was on Xcode 3.2, OSX 10.6, iPhone OS 3.1.

  • Michael

    I tried using this method with the facebook-connect iphone library but am having some issues. What I’m doing is simply opening a facebook session and attempting to display the login dialog. This works fine when I import the facebook source code directly into the project. With the project-reference approach, everything compiles and links fine. But when I try to run, no dialog. Any idea what might be going on? Thanks for the excellent article.