Static libraries...

Member
Posts: 21
Joined: 2009.10
Post: #1
This shouldn't be a hard question for anybody here, but I'm at a loss... I've tried looking up tutorials for help, but every tutorial I've found seems to focus on much more advanced Xcode tricks than I'm interested in - I just want to have a static library which works both in the simulator and on hardware Cry

Okay, I've built up a collection of C++ and Objective-C++ classes commonly used in my iPod touch projects for university; this collection is <10KLOC but is spread over far too many files for my liking; so, I'd like to create a static library collecting all of those commonly used classes.

So, I created a test static library containing a C++ function just fprintf()'ing to stderr to prove that the function has been invoked.

(To create the test static library I created a new project using Xcode (OpenGL ES Application), added a static library target, dragged the .cpp file to the Compile Sources section of that target, and deleted the original application target.)

Building the static library using Mac OS X 10.5 as the active SDK and dropping the static library from build/Debug/ into a C++ Tool works fine.

Building the static library using iPhone OS - Device or Simulator - as the active SDK and dropping the static library from build/Debug-iphoneos/ or build/Debug-iphonesimulator/ into an iPhone OS application compiled using Device as the active SDK works fine.

But, compiling that same iPhone OS application using Simulator as the active SDK fails with a "symbol not found" compile time error.

So why is a static library compiled for Simulator/Debug - iPhone OS (i386) being correctly invoked in an application compiled for Debug - iPhone OS (armv6)? Cry
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #2
the_wandering_monster Wrote:I just want to have a static library which works both in the simulator and on hardware Cry

You have to use lipo to combine the x86 lib and the arm lib. In the terminal you'd do something like:

lipo myarmlib.a my386lib.a -create -output myfatlib.a
Quote this message in a reply
Member
Posts: 21
Joined: 2009.10
Post: #3
Thanks for that AnotherJake, but it still doesn't work - I'm still getting "symbol not found" compile time errors.

I probably should've made it clearer that I can't compile an application which uses the static library for the simulator at all, whether using the static library compiled for the simulator or compiled for the device.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #4
Which symbol isn't found?

Personally, I've found it a lot easier to use make and invoke the compiler/archiver directly rather than getting Xcode to do what I want. Here's how I create a 3-way universal iPhone library:

Code:
/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2 -isysroot /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.0.sdk -mmacosx-version-min=10.5 -D__IPHONE_OS_VERSION_MIN_REQUIRED=30000 -arch i386 -c -o hello_i386.o hello.c
/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk -miphoneos-version-min=3.0 -arch armv6 -c -o hello_armv6.o hello.c
/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk -miphoneos-version-min=3.0 -arch armv7 -c -o hello_armv7.o hello.c

/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/ar rc hello_i386.a hello_i386.o
/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ar rc hello_armv6.a hello_armv6.o
/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ar rc hello_armv7.a hello_armv7.o

/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/ranlib hello_i386.a
/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ranlib hello_armv6.a
/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ranlib hello_armv7.a

lipo -create hello.a hello_i386.a hello_armv6.a hello_armv7.a

hello.c:
Code:
#include <stdio.h>

void hello() {
    puts("Hello, world!");
}

To test and make sure the library was assembled properly:
Code:
/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2 -isysroot /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.0.sdk -mmacosx-version-min=10.5 -D__IPHONE_OS_VERSION_MIN_REQUIRED=30000 -arch i386 test.c hello.a
./a.out

test.c:
Code:
#include <stdlib.h>

void hello();

int main() {
    hello();
    return EXIT_SUCCESS;
}

You can also use `file hello.a` to get some info on the library to make sure all of the archs you expect are there. I get this:
Code:
hello.a: Mach-O universal binary with 3 architectures
hello.a (for architecture i386):    current ar archive random library
hello.a (for architecture armv6):    current ar archive random library
hello.a (for architecture armv7):    current ar archive random library
Quote this message in a reply
Member
Posts: 21
Joined: 2009.10
Post: #5
Thanks for that ThemsAllTook, but it still doesn't work, and now I've somehow broken even the little I had working yesterday; I've listed the process by which I've tried to test creating/using a static library - maybe somebody can see if there are any holes in my process?

  1. Created a new iPhone OS->Application->OpenGL ES Application using Xcode ("testlib")
  2. deleted all files from Classes, and deleted "main.m" from Other Sources
  3. deleted target "testlib"
  4. created new static library target "testlib"
  5. created the file "testlib.h" in Classes
    Code:
    #ifndef testlib_h

    #define testlib_h

    void InvokeTestLib( int p_int );

    #endif
  6. created the file "testlib.cpp" in Classes
    Code:
    #include "testlib.h"

    #include <stdio.h>

    void InvokeTestLib( int p_int )
    {
        fprintf( stderr, "I need scissors! %d!\n", p_int );
        return;
    }
  7. changed active SDK to Simulator - iPhone OS 2.2; compiled
  8. changed active SDK to Device - iPhone OS 2.2; compiled
  9. closed project
  10. renamed libraries for easier lipo, and copied to a folder
  11. Code:
    lipo libtestlib-iphonesimulator.a libtestlib-iphoneos.a -create -output fatlibtestlib.a
  12. Code:
    file fatlibtestlib.a
    fatlibtestlib.a: Mach-O universal binary with 2 architectures
    fatlibtestlib.a (for architecture i386):    current ar archive random library
    fatlibtestlib.a (for architecture cputype (12) cpusubtype (6)):    current ar archive random library
  13. created a new iPhone OS->Application->OpenGL ES Application using Xcode ("testapp")
  14. drag/dropped "testlib.h" into Classes
  15. drag/dropped "fatlibtestlib.a" into Classes
  16. changed active SDK to Device - iPhone OS 2.2; compiled
  17. changed active SDK to Simulator - iPhone OS 2.2; compiled
  18. added line #include "testlib.h" to top of "EAGLView.m"
  19. added line InvokeTestLib( 1 ); to top of - (void)drawView in "EAGLView.m"
  20. changed active SDK to Simulator - iPhone OS 2.2; compiled
    Code:
    compilation failed: Building target “testapp” of project “testapp” with configuration “Debug” — (1 error)
    [i][lots & lots cut][/i]
    "_InvokeTestLib", referenced from:
    -[EAGLView drawView] in EAGLView.o
    ld: symbol(s) not found
    collect2: ld returned 1 exit status
  21. changed active SDK to Device - iPhone OS 2.2; compiled; ditto
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #6
It looks like you've gotten the static library built correctly, but because your implementation file was .cpp instead of .c, InvokeTestLib will have been compiled with C++ function name mangling. I'm a little bit fuzzy on the details (it's been a while), but you'll need to add this around your function prototype in testlib.h:

Code:
#ifdef __cplusplus
extern "C" {
#endif

// Function prototype here

#ifdef __cplusplus
}
#endif

...and possibly around the implementation in testlib.cpp as well. Or just compile it as C. It also might work to compile EAGLView.m as Objective-C++.
Quote this message in a reply
Member
Posts: 21
Joined: 2009.10
Post: #7
Cheers ThemsAllTook, I thought of that maybe fifteen minutes after I posted but wasn't where I could test it Blush Tested it, and now I can use the static library both in simulator and device builds... although now I'm very confused as to why my original test didn't work, as the project I dropped the static library into was completely Objective-C++...
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Static Library kendric 9 3,547 Sep 17, 2009 11:24 AM
Last Post: kendric