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 .dylib
s from application bundle.
Dynamic linking on Mac OS X, a tiny example
Steps:
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.)
cheers
-- denis