8

(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!

ib.
  • 27,830
  • 11
  • 80
  • 100
Olie
  • 24,597
  • 18
  • 99
  • 131

2 Answers2

14

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.

ib.
  • 27,830
  • 11
  • 80
  • 100
abarnert
  • 354,177
  • 51
  • 601
  • 671
  • One thing I should have mentioned but didn't: If you want to use static libs, you need to check that the licenses are compatible. I'll edit the answer. – abarnert Apr 11 '13 at 17:09
  • 1
    Spot on - in terms of install_name_tool however, you are missing the fact that you need the name of the executable at the end of the line too. – Damian Apr 28 '13 at 17:20
  • 1
    @abarnert I have been notified that this part: _static-linking them means your whole app becomes a "derivative work"_ is not completely accurate, I have modified my answer to the question you link to. – wimh Jul 20 '13 at 10:24
  • @Wimmel: The only _right_ answer is that you need get your legal team to read the license, and the relevant commentary (and case history, but there isn't really any of that), and advise you on what's appropriate; nobody should trust you or me for legal advice. I'll edit my answer to be more appropriate. Thanks for bringing it up. – abarnert Jul 31 '13 at 15:49
-1

On macOS the dylibs are normally stored at "/usr/local/". By default all applications looks for any required dylibs in "/usr/local/".

Option 1 is to place the dylibs in your friends machines "/usr/local/".

Option 2, place the dylibs in the same directory as your executable.

Option 3, Fix the path in the application or the dylib. XCode dylib looking in /usr/lib will be useful. You can use this option to package the dylibs to the location of your choice i.e. both inside and outside the application package.

ib.
  • 27,830
  • 11
  • 80
  • 100
Vishvesh
  • 512
  • 8
  • 21
  • 3
    Applications do not look for dylibs in /usr/local. You probably meant /usr/local/lib, but even that's only partially accurate. The manpage on dyld explains where they look (see in particular DYLD_LIBRARY_PATH and DYLD_FALLBACK_LIBRARY_PATH). – abarnert Apr 26 '12 at 19:18