Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can .dylib dynamically-linked libraries be packaged into an executable?

Tags:

macos

build

dylib

(Yes, I understand that the whole point of dylib is that it loads dynamically, but I’m trying to create a self-contained package.)

I’ve got an executable that I built from the command line (on macOS Lion, if it matters). I delivered the executable to a friend, but he can’t run it because he doesn’t have the libraries installed. He’d rather not install the libraries, so now I’m trying to create a package that includes the original executable, plus all the needed libs.

I’m used to working in the Xcode IDE and am not very familiar with make and other command-line build tools and their options. (I built this tool following very good instructions from the web.) Hence, explicit instructions would be helpful.

Thanks!

like image 720
Olie Avatar asked Feb 01 '12 15:02

Olie


1 Answers

You can’t directly put a dylib inside an executable. (That’s pretty much what bundles were invented for—but that doesn’t help you with command-line tools.)

You can rebuild each dylib as a static (.a) library, in which case all the code your executable needs will be copied into the executable, and you don’t need to distribute anything with it. If you’ve got the source to the libraries, this is usually very easy—but without knowing exactly how you’re building things, it’s hard to tell you what to change.

One thing to keep in mind with static linking is that it affects how different licenses play together. In particular, if any of the libraries you’re using are LGPL-licensed, static-linking them has consequences that dynamic linking doesn’t. See this question (and the links on the answer) for more details, but really, you shouldn’t trust answers on Stack Overflow for legal advice on licenses. Anyway, that probably isn’t an issue for the OP’s “I want to build a program and give it to my friend”, but for others reading this question later, it might be.

If static linking isn’t possible or desirable, all you need to do is package up the executable and dylibs together and get them onto your friend’s machine. Since he apparently doesn’t want to run an installer, that means a tarball or a ZIP file.

The only tricky part is making sure the executable knows where to find the dylibs. Unless each dylib is either in the dyld search path (see the manpage for dyld for more details, but it’s not going to help you if you don’t want to install anything), or in the exact same place it was at the time you linked it, running the executable will fail with an “image not found” error from dyld.

Fortunately, “exact same place” can mean a magic path like @executable_path/libfoo.dylib, which means “in the same directory as myexe”, rather than an absolute path like /opt/local/lib/libfoo.dylib or a relative path like ../../foo/build/Release/libfoo.dylib. (Note that normal relative paths are relative to the current working directory, not the executable or bundle directory.)

You can see where myexe is looking by doing this:

$ otool -L myexe

Anything that’s not looking in @executable_path (except for stuff in /lib and /usr/lib, which is a part of the OS and doesn’t need to be distributed), you can fix it like so:

$ install_name_tool -change ../../../mydl/build/Release/libmydl.dylib @executable_path/libmydl.dylib myexe

Now, you just need to copy all those dylibs right next to myexe, tar it up, and give it to your friend, and he can just untar it and run the exe.

like image 171
abarnert Avatar answered Sep 22 '22 09:09

abarnert