PDA

View Full Version : Games using dynamic libraries without installers


mushware
2002.11.20, 05:40 AM
I've just spent a while converting my game to run with dynamic libraries installed in the application bundle instead of the system paths. This means that the libraries can live inside the application and there's no need for an installer. It's a bit subtle, so I thought I'd post my results.

The key aspect is the load commands buried in the .dylib file. The otool command (from a terminal) will display this for you. Taking a vorbis library as an example:
otool -l libvorbis.0.2.0.dylib
produces output which contains, amongst other things,
Load command 3
cmd LC_ID_DYLIB
cmdsize 60
name /usr/local/lib/libvorbis.0.dylib (offset 24)
time stamp 1027081968 Fri Jul 19 13:32:48 2002
current version 3.0.0
compatibility version 3.0.0
The fundamental thing is to replace the hardcoded path /usr/local/lib/ with the magic words @executable_path/../Frameworks/, so that the output of the otool command looks like this:
Load command 3
cmd LC_ID_DYLIB
cmdsize 76
name @executable_path/../Frameworks/libvorbis.0.dylib (offset 24)
time stamp 1037730409 Tue Nov 19 18:26:49 2002
current version 3.0.0
compatibility version 3.0.0
Then you can put your libraries in the Contents/Frameworks directory of the application bundle and the dynamic loader will find them.

How to do it? If your library is part of a framework and you can get the prebinding to work, use the instructions at www.cocoadevcental.com (http://www.cocoadevcentral.com/tutorials/showpage.php?show=00000037.php) (thanks to OneSadCookie for that link). If you're building your libraries Unix-style with ./configure and make, I've found that a small edit to the libtool script supplied with the package (NOT /usr/bin/libtool) will usually do the job. The -install_name option controls the name in the LC_ID_DYLIB load command, and changing this line in libtool
archive_cmds="\$nonopt \$(test .\$module = .yes && echo -bundle || echo -dynamiclib) \
$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$linkopts -install_name \
\$rpath/\$soname \$verstring"
to this
archive_cmds="\$nonopt \$(test .\$module = .yes && echo -bundle || echo -dynamiclib) \
$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$linkopts -install_name \
@executable_path/../Frameworks/\$soname \$verstring"
will set the load command appropriately. This needs to be done after running ./configure but before make. The libraries can still be installed in /usr/local/lib/ during development as usual, and copied into the application and stripped for distribution.

codemattic
2002.11.20, 08:17 PM
thanks - this is useful info. (also thanks to OSC and cocoadevcentral.com)

Codemattic

henryj
2002.11.20, 11:08 PM
Good post. Maybe it should go into the wiki

Deland
2002.11.21, 02:35 AM
Very nice post here, I really appreciated the info.

0ctane
2006.01.10, 10:36 AM
This solved one of my problems. Thanks a bundle....