How do I create a dynamic library (dylib) with Xcode?
Asked Answered
A

4

30

I'm building few command-line utilities in Xcode (plain C, no Cocoa). I want all of them to use my customized version of libpng, and I want to save space by sharing one copy of the library among all executables (I don't mind re-distributing .dylib with them).

Do I need to do some magic to get libpng export symbols?

Does "Link Binary With Libraries" build phase link statically?

Apple's docs mention loading of libraries at run time with dlopen, but how I can make Xcode create executable without complaining about missing symbols?


I think I've figured it out:

  • libpng wasn't linking properly, because I've built 32/64-bit executables and 32-bit library. Build settings of the library and executables must match.

  • libpng's config.h needs to have tons of defines like #define FEATURE_XXX_SUPPORTED

  • "Link Binary With Libraries" build phase handles dynamic libraries just fine, and DYLD_FALLBACK_LIBRARY_PATH environmental variable is neccessary for loading .dylibs from application bundle.

Auditory answered 11/10, 2008 at 19:30 Comment(1)
I'd like to suggest the mach-o tag, but I don't suppose it's worth removing any of the existing tags in favor of it.Henrique
M
7

You probably need to ensure that the dynamic library you build has an exported symbols file that lists what should be exported from the library. It's just a flat list of the symbols, one per line, to export.

Also, when your dynamic library is built, it gets an install name embedded within it which is, by default, the path at which it is built. Subsequently anything that links against it will look for it at the specified path first and only afterwards search a (small) set of default paths described under DYLD_FALLBACK_LIBRARY_PATH in the dyld(1) man page.

If you're going to put this library next to your executables, you should adjust its install name to reference that. Just doing a Google search for "install name" should turn up a ton of information on doing that.

Moue answered 12/10, 2008 at 3:0 Comment(1)
What if I just have a simple pure C function and I want to expose it a Dynamic Library. How can I do that (I did it easily with Visual Studio on Windows)?Longsighted
L
56

Dynamic linking on Mac OS X, a tiny example

Steps:

  1. create a library libmylib.dylib containing mymod.o
  2. compile and link a "callmymod" which calls it
  3. call mymod from callmymod, using DYLD_LIBRARY_PATH and DYLD_PRINT_LIBRARIES

Problem: you "just" want to create a library for other modules to use. However there's a daunting pile of programs -- gcc, ld, macosx libtool, dyld -- with zillions of options, some well-rotted compost, and differences between MacOSX and Linux. There are tons of man pages (I count 7679 + 1358 + 228 + 226 lines in 10.4.11 ppc) but not much in the way of examples, or programs with a "tell me what you're doing" mode.

(The most important thing in understanding is to make a simplified OVERVIEW for yourself: draw some pictures, run some small examples, explain it to someone else).

Background: apple OverviewOfDynamicLibraries, Wikipedia Dynamic_library


Step 1, create libmylib.dylib --

mymod.c:
    #include <stdio.h>
    void mymod( int x )
    {
        printf( "mymod: %d\n", x );
    }
gcc -c mymod.c  # -> mymod.o
gcc -dynamiclib -current_version 1.0  mymod.o  -o libmylib.dylib
    # calls libtool with many options -- see man libtool
    # -compatibility_version is used by dyld, see also cmpdylib

file libmylib.dylib  # Mach-O dynamically linked shared library ppc
otool -L libmylib.dylib  # versions, refs /usr/lib/libgcc_s.1.dylib

Step 2, compile and link callmymod --

callmymod.c:
    extern void mymod( int x );
    int main( int argc, char** argv )
    {
        mymod( 42 );
    }
gcc -c callmymod.c
gcc -v callmymod.o ./libmylib.dylib -o callmymod
    # == gcc callmymod.o -dynamic -L. -lmylib
otool -L callmymod  # refs libmylib.dylib
nm -gpv callmymod  # U undef _mymod: just a reference, not mymod itself

Step 3, run callmymod linking to libmylib.dylib --

export DYLD_PRINT_LIBRARIES=1  # see what dyld does, for ALL programs
./callmymod
    dyld: loaded: libmylib.dylib ...
    mymod: 42

mv libmylib.dylib /tmp
export DYLD_LIBRARY_PATH=/tmp  # dir:dir:...
./callmymod
    dyld: loaded: /tmp/libmylib.dylib ...
    mymod: 42

unset DYLD_PRINT_LIBRARIES
unset DYLD_LIBRARY_PATH

That ends one tiny example; hope it helps understand the steps.
(If you do this a lot, see GNU Libtool which is glibtool on macs, and SCons.)

Livonia answered 5/2, 2009 at 13:54 Comment(2)
nice. what if you already have the .o files, but there are say, 9 of them, in the 3 folders, but all part of the same "framework"... is this a call to arms for lipo, or what? btw i'm trying to get libg7221 to "be" a "shared" "library", in this case...Avelinaaveline
@alex gray, don't know, sorry; ask that as a new question ?Livonia
M
7

You probably need to ensure that the dynamic library you build has an exported symbols file that lists what should be exported from the library. It's just a flat list of the symbols, one per line, to export.

Also, when your dynamic library is built, it gets an install name embedded within it which is, by default, the path at which it is built. Subsequently anything that links against it will look for it at the specified path first and only afterwards search a (small) set of default paths described under DYLD_FALLBACK_LIBRARY_PATH in the dyld(1) man page.

If you're going to put this library next to your executables, you should adjust its install name to reference that. Just doing a Google search for "install name" should turn up a ton of information on doing that.

Moue answered 12/10, 2008 at 3:0 Comment(1)
What if I just have a simple pure C function and I want to expose it a Dynamic Library. How can I do that (I did it easily with Visual Studio on Windows)?Longsighted
R
7

Unfortunately, in my experience Apple's documentation is antiquated, redundant and missing a LOT of common information that you would normally need.

I wrote a bunch of stuff on this on my website where I had to get FMOD (Sound API) to work with my cross platform game that we developed at uni. Its a weird process and I'm surprised that Apple do not add more info on their developer docs.

Unfortunately, as "evil" as Microsoft are, they actually do a much better job of looking after their devs with documentation ( this is coming from an Apple evangelist ).

I think basically, what you are not doing is AFTER you have compiled your .app Bundle. You then need to run a command on the executable binary /MyApp.app/contents/MacOS/MyApp in order to change where the executable looks for its library file. You must create a new build phase that can run a script. I won't explain this process again, I have already done it in depth here:

http://brockwoolf.com/blog/how-to-use-dynamic-libraries-in-xcode-31-using-fmod

Hope this helps.

Recension answered 23/11, 2008 at 1:33 Comment(2)
@wintermute: An unnecessary comment. Which I'm sure every user on this site has heard a million times before.Recension
Dead link. Archived web-beta.archive.org/web/20100620075647/http://…Delphadelphi
C
4

Are you aware of the Apple reference page Dynamic Library Programming Topics? It should cover most of what you need. Be aware that there a shared libraries that get loaded unconditionally at program startup and dynamically loaded libraries (bundles, IIRC) that are loaded on demand, and the two are somewhat different on MacOS X from the equivalents on Linux or Solaris.

Claireclairobscure answered 12/10, 2008 at 2:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.