neděle 24. listopadu 2013

MacOSX - How to create self contained dynamically linked program which links to the .dylibs bundled with it

Today I had a task - to create version of sox binary (Sound Exchange - swiss knife for sound files) which will be self contained - which works out of the box without installation.

My first finding, there is apple command for detect on which particular executable depends:

otool -L ./sox

its like linux ldd command.


The easiest way how to install sox to mac os x is using homebrew, which is another story of course.

brew install sox

But its not an option because the created binary uses links to dynamic libraries .dylib (like linux shared objects .so) to /usr/local/lib.
bash-3.2$ otool -L /usr/local/Cellar/sox/14.4.1/bin/sox
/usr/local/Cellar/sox/14.4.1/bin/sox:
/usr/local/Cellar/sox/14.4.1/lib/libsox.2.dylib (compatibility version 3.0.0, current version 3.1.0)
/usr/local/lib/libltdl.7.dylib (compatibility version 11.0.0, current version 11.0.0)
/usr/local/lib/libpng15.15.dylib (compatibility version 30.0.0, current version 30.0.0)
/usr/local/lib/libao.4.dylib (compatibility version 5.0.0, current version 5.0.0)
/usr/local/lib/libmad.0.2.1.dylib (compatibility version 3.0.0, current version 3.1.0)
/usr/local/lib/libid3tag.0.3.0.dylib (compatibility version 4.0.0, current version 4.0.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)
/usr/local/lib/libvorbisenc.2.dylib (compatibility version 3.0.0, current version 3.9.0)
/usr/local/lib/libvorbisfile.3.dylib (compatibility version 7.0.0, current version 7.5.0)
/usr/local/lib/libvorbis.0.dylib (compatibility version 5.0.0, current version 5.6.0)
/usr/local/lib/libogg.0.dylib (compatibility version 9.0.0, current version 9.1.0)
/usr/local/lib/libwavpack.1.1.4.dylib (compatibility version 3.0.0, current version 3.4.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)

Downloading official sox binary for Mac OS X is also not an option. Due to licensing issues they don't bundle own sox with lame, vorbis and mad libraries.
bash-3.2$ otool -L ./sox
./sox:
/System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)
/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1094.0.0)

So I must checkout the source code and compile it on my own. First of all I will install sox from homebrew to reuse dependent libraries .dylib and .h for gcc compiler flags - LDFLAGS and CPPFLAGS.
git clone git://git.code.sf.net/p/sox/code sox-code
cd sox-code
./osxbuild
./configure
#...result of configure, we want those libraries enabled
#OPTIONAL FILE FORMATS
#amrnb......................no
#amrwb......................no
#ffmpeg.....................no
#flac.......................no
#gsm........................yes (in-tree)
#lpc10......................yes (in-tree)
#mp2/mp3....................yes
# id3tag....................yes
# lame......................no
# mad.......................yes
# dlopen mad................no
# twolame...................no
#oggvorbis..................yes
#sndfile....................no
#wavpack....................yes
make
I fighted with --enable-static --disable-shared options. I did not make the statically linked sox without needing .dylibs at all. 

But what about the second option, use dynamically linked libraries bundled with executable? I am looking for something like former linux statifier (nowadays does not work but its different story...)

I found this supreme program - Mac dylib bundler which is helping with exactly this. 

It looks to the library descriptors and find all of dependent libraries, copies next to executable to the libs folder and changes their descriptor to be pointed to the new location.

dylibbundler -x ./sox -b -of -od -d ../result

and vua la:
bash-3.2$ otool -L ./sox 
./sox:
/System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio (compatibility version 1.0.0, current version 1.0.0)
@executable_path/../libs/libpng15.15.dylib (compatibility version 30.0.0, current version 30.0.0)
@executable_path/../libs/libao.4.dylib (compatibility version 5.0.0, current version 5.0.0)
@executable_path/../libs/libFLAC.8.dylib (compatibility version 12.0.0, current version 12.0.0)
@executable_path/../libs/libmad.0.2.1.dylib (compatibility version 3.0.0, current version 3.1.0)
@executable_path/../libs/libid3tag.0.3.0.dylib (compatibility version 4.0.0, current version 4.0.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)
@executable_path/../libs/libmp3lame.0.dylib (compatibility version 1.0.0, current version 1.0.0)
@executable_path/../libs/libvorbisenc.2.dylib (compatibility version 3.0.0, current version 3.9.0)
@executable_path/../libs/libvorbisfile.3.dylib (compatibility version 7.0.0, current version 7.5.0)
@executable_path/../libs/libvorbis.0.dylib (compatibility version 5.0.0, current version 5.6.0)
@executable_path/../libs/libogg.0.dylib (compatibility version 9.0.0, current version 9.1.0)
@executable_path/../libs/libwavpack.1.1.4.dylib (compatibility version 3.0.0, current version 3.4.0)
@executable_path/../libs/libsndfile.1.dylib (compatibility version 2.0.0, current version 2.25.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)