Games using dynamic libraries without installers

mushware
Unregistered
 
Post: #1
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:
Code:
otool -l libvorbis.0.2.0.dylib
produces output which contains, amongst other things,
Code:
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:
Code:
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 (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
Code:
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
Code:
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.
Quote this message in a reply
Member
Posts: 304
Joined: 2002.04
Post: #2
thanks - this is useful info. (also thanks to OSC and cocoadevcentral.com)

Codemattic
Quote this message in a reply
henryj
Unregistered
 
Post: #3
Good post. Maybe it should go into the wiki
Quote this message in a reply
Deland
Unregistered
 
Post: #4
Very nice post here, I really appreciated the info.
Quote this message in a reply
Apprentice
Posts: 15
Joined: 2005.12
Post: #5
This solved one of my problems. Thanks a bundle....
Quote this message in a reply
Post Reply