How to build universal ios static library

Julie picture Julie · Oct 24, 2010 · Viewed 7.7k times · Source

I'm trying to build a static library that I can use with both ios3.x and ios4.x. I can build a static library with ios3.0 that works with another project in ios3.0 but won't compile in ios4. The same is true going from ios4 to ios3.

Here's how to recreate:

  1. Open XCode 3.2.4 and start a new project that's a Cocoa Touch Static Library called Library4
  2. Click on the classes folder and create a new UIViewController named "TestViewController"
  3. Right click on Frameworks folder, add existing framework, pick UIKit
  4. In the left panel, expand targets, right-click on my library target and click get info. Change to all configurations, Change the base sdk to iphone simulator 4.0, change ios deployment target to ios3.0
  5. Click on the Link Library with Binaries folder. In the right pane, change the roles of both to "Weak"
  6. Build the Library
  7. Open Xcode 3.2.2 and start a new View based application called Library4Test
  8. Copy TestViewController.h to the classes folder
  9. Copy libLibrary4.a file to the frameworks folder. It automatically gets added to the linker phase of the target
  10. Right-click on the Library4Test Target and click get info. In other linker flags, add "-ObjC" and "-all_load"
  11. In the app delegate header add Import "TestViewController.h"
  12. IN the app delegate header's application's didFinishLaunchingWithOptions method add

    TestViewController *test = [TestViewController alloc] init;

  13. Compile with ios3.0 simulator

When I compile I get:

Ld build/Debug-iphonesimulator/library4Test.app/library4Test normal i386
cd /Users/test/Documents/Testing/library4Test
setenv MACOSX_DEPLOYMENT_TARGET 10.5
setenv PATH "/Developer/GrandpaIPhone/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Developer/GrandpaIPhone/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/Developer/GrandpaIPhone/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2 -arch i386 -isysroot /Developer/GrandpaIPhone/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.3.sdk -L/Users/test/Documents/Testing/library4Test/build/Debug-iphonesimulator -L/Users/test/Documents/Testing/library4Test -F/Users/test/Documents/Testing/library4Test/build/Debug-iphonesimulator -filelist /Users/test/Documents/Testing/library4Test/build/library4Test.build/Debug-iphonesimulator/library4Test.build/Objects-normal/i386/library4Test.LinkFileList -mmacosx-version-min=10.5 -framework Foundation -framework UIKit -framework CoreGraphics -llibrary4_1 -o /Users/test/Documents/Testing/library4Test/build/Debug-iphonesimulator/library4Test.app/library4Test

Undefined symbols:
"_objc_msgSendSuper2", referenced from:
-TestViewController didReceiveMemoryWarning in liblibrary4_1.a(TestViewController.o)
-TestViewController viewDidUnload in liblibrary4_1.a(TestViewController.o)
-TestViewController dealloc in liblibrary4_1.a(TestViewController.o)
"__objc_empty_vtable", referenced from:
_OBJC_METACLASS_$_TestViewController in liblibrary4_1.a(TestViewController.o)
_OBJC_CLASS_$_TestViewController in liblibrary4_1.a(TestViewController.o)
"_OBJC_CLASS_$_UIViewController", referenced from:
_OBJC_CLASS_$_TestViewController in liblibrary4_1.a(TestViewController.o)
"_OBJC_METACLASS_$_UIViewController", referenced from:
_OBJC_METACLASS_$_TestViewController in liblibrary4_1.a(TestViewController.o)
".objc_class_name_TestViewController", referenced from:
literal-pointer@__OBJC@__cls_refs@TestViewController in library4_1os3TestAppDelegate.o
"_OBJC_METACLASS_$_NSObject", referenced from:
_OBJC_METACLASS_$_TestViewController in liblibrary4_1.a(TestViewController.o)
ld: symbol(s) not found
collect2: ld returned 1 exit status

Answer

Elise van Looij picture Elise van Looij · Nov 29, 2010

Not sure exactly, but it looks like a linking problem (all those .o things). Here's how I set up my iOS static library. It's a very simple thing, but it works.

  1. Start a new project and choose iOS Libarary >> Cocoa Touch Static Library
  2. Add some classes. Mine are categories on UIView that give better descriptions for use in NSLog.
  3. Select the target and make sure the Role of each class is set to an appropriate value. In the case of my categories that should be 'public'.
  4. Double-click on the target and choose the Build tab.
  5. Select the Configuration Release and set the following build settings:
  6. Deployment Location YES (check)
    Deployment Postprocessing YES (check)
    Installation Build Products Location /

Build your static library. By default it will build in /usr/local/lib

Now create a symbolic link for easy access to your new library. An easy way is to open your terminal and run the following commands:

cd ~    
ln -s /usr/local/lib

Now open the Xcode project in which you want to use your library. Create a group called Libraries or something like that, ctrl-click and use 'Add existing files' to add the library. It will be called something like libYourLibrary.a When you run your project, you'll get a linking error. So double-click the project file, go to Build >> All configurations and add the following value to the "Library Search Paths" setting: ~/lib