Is it OK to use DYLD_LIBRARY_PATH on Mac OS X? And, what's the dynamic library search algorithm with it?

Solution 1:

As you've noted, DYLD_LIBRARY_PATH behaves like LD_LIBRARY_PATH on other *nix. However, there is another environment variable you should look at called DYLD_FALLBACK_LIBRARY_PATH.

In general, these are (both on osx and linux) suggested only for development use as they can cause symbol lookup errors when you override with a library that does not have the same symbol table. A good example of this is when you attempt to override the default install of VecLib (e.g. blas lapack) with a custom install. This will cause symbol not found errors in applications linked to the system VecLib if DYLD_LIBRARY_PATH is set and the reverse (symbol lookup errors in custom applications) if it is not. This is due to the system blas/lapack not being a full implementation of the ATLAS libs.

DYLD_FALLBACK_LIBRARY_PATH will not produce these problems.

When installing libraries to a non-standard location, DYLD_FALLBACK_LIBRARY_PATH is much more sane. This will look for symbols in libraries provided in the default paths and if the symbol is not found there, fall back to the specified path.

The benefit is that this process will not cause symbol lookup errors in applications compiled against the default libraries.

In general, when libraries are installed to non-standard locations absolute paths should be specified which negates the ambiguity of the dynamic lookup.

Solution 2:

DYLD_LIBRARY_PATH does not behave like LD_LIBRARY_PATH. The OS X dlopen documentation (https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man3/dlopen.3.html) specifies that when providing an absolute path, it will first look in locations specified by DYLD_LIBRARY_PATH:

When path contains a slash but is not a framework path (i.e. a full path or a partial path to a dylib), dlopen() searches the following until it finds a compatible Mach-O file: $DYLD_LIBRARY_PATH (with leaf name from path ), then the supplied path (using current working directory for relative paths), then $DYLD_FALLBACK_LIBRARY_PATH (with leaf name from path ).

In other words, if you set DYLD_LIBRARY_PATH to /Hello, the following two dlopen calls:

dlopen("/Hello/libfoo.so", RTLD_NOW);
dlopen("/World/libfoo.so", RTLD_NOW);

will both resolve to /Hello/libfoo.so. This is quite counter-intuitive, and represents a security vulnerability. Software using dlopen has no way to guarantee it is loading the correct libraries (perhaps override DYLD_LIBRARY_PATH in its own environment?)