Conflict Between Dynamic Linking Priority in Osx

Conflict between dynamic linking priority in OSX?

You should not set library paths using DYLD_LIBRARY_PATH. As you've discovered, that tends to explode. Executables and libraries should have their library requirements built into them at link time. Use otool -L to find out what the file is looking for:

$ otool -L /System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO
/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO:
/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO (compatibility version 1.0.0, current version 1.0.0)
...
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)

For an example of one of my homebrew-built programs:

$ otool -L /usr/local/bin/gifcolor
/usr/local/bin/gifcolor:
/usr/local/Cellar/giflib/4.1.6/lib/libgif.4.dylib (compatibility version 6.0.0, current version 6.6.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)

Note that it references /usr/local. If you've built it in such a way that it references the wrong library, I recommend rebuilding and pointing it to the correctly library.

If that's impossible, it is possible to edit what path is used using install_name_tool, but there are cases where this doesn't work, such as if the new path is longer than the old path and you didn't link it with -header_pad_max_install_names. Rebuilding with the correct path is preferred.

Note that there are a few "special" paths available that allow libraries to be found relative to their loader. See @executable_path/ and its kin in the dyld(1) man page.

What happens when two macOS .plugin depend on same .dylib and each bundles it separately inside plugins' folder?

The order of dynamic library search and load is described in Apple's Dynamic Library Usage Guidelines

In short, if paths to depended library in your plugins matches than this library will be loaded only once. On every next load only internal counter will be increased:

The dlopen function returns the same library handle it returned in the
first call, but it also increments the reference count associated with
the handle

If paths to library is different than different copies of library will be loaded.

Note: While checking whether the library is already loaded, the absolute path to it is used. It may be directly set in dependency, discovered during search in global directories or resolved from @rpath.

And about potential confilcts during symbol resolving:

Name conflicts between dynamic shared libraries are not discovered at
compile time, link time, or runtime. The dlsym function uses string
matching to find symbols. If two libraries use the same name for a
function, the dynamic loader returns the first one that matches the
symbol name given to dlsym.

So several copies will not crash program if both plugins uses the same library. If they expect different libraries under the same name than it's a big problem and you should use version compatibility mechanism - see Dynamic Library Design Guidelines

OSX framework linking issues

There are two things I can think of to try.

Option one

Using @rpath might be better suited for what you're trying to do. What's happening here is this:

Your libraries all expect that they will be positioned the same relative to whatever executable. They're all going to be at:

@executable_path/../Frameworks/MyCompany.framework/Versions/A/Resources/lib.dylib

Which you could make work as long as you put all your libraries in the right place relative to the executables. Instead, you can set the install name on the dylibs (via install_name_tool) to @rpath/lib.dylib. This should then work with the DYLD_LIBRARY_PATH environment variable, but it's really suited for use with the -rpath compiler flag, so this may work, but I've never tried it.

Option two

You can also create symbolic links so that the library will actually be found by traversing from the executables to through the path you've set as the install name.

Linking to libraries with $ld$hide$os10.X$ symbols in OSX

First off, you don’t actually need to do anything special to get your desired behavior, as you’re linking dynamically. Ensure that your netlib-built LAPACK appears before -lblas in the link command, and all LAPACK interfaces will be picked up from the netlib LAPACK (ld matches all the undefined symbols it can against each of the libraries being linked against in order).

Alternatively, assuming that your netlib LAPACK is linked against the system BLAS, you should be able to configure the link of LAPACK so that it reexports all of the BLAS symbols. Then you can simply link against your LAPACK and leave -lblas out of your link command entirely.


The $show$ and $hide$ symbols come into play if and only if you are linking against both the system BLAS and the system LAPACK libs. A simple example will show how they work in that case:

Kronecker:~ scanon$ cat foo.c
void dgetrf_(void);
int main(void) { dgetrf_(); return 0; }

Building this on 10.9 and breaking on dgetrf_, we see that the symbol was picked up from libLAPACK.dylib, even though -lblas appears first in the build command. This is because the symbol is hidden in libBLAS.dylib when targeting 10.9:

Kronecker:~ scanon$ clang foo.c -lblas -llapack
Kronecker:~ scanon$ lldb a.out
Current executable set to 'a.out' (x86_64).
(lldb) b dgetrf_
Breakpoint 1: 2 locations.
(lldb) run
...
frame #0: 0x00007fff89237b70 libLAPACK.dylib`dgetrf
libLAPACK.dylib`dgetrf:
...

If we specify -mmacosx-version-min=10.6 (telling the compiler and linker that we want to produce an executable that can run on 10.6 Snow Leopard), we will see that the symbol is picked up from libBLAS.dylib instead. This is because the symbol doesn’t exist in libLAPACK.dylib on 10.6, so our executable wouldn’t be able to run on that platform if the symbol in libLAPACK.dylib were used:

Kronecker:~ scanon$ clang foo.c -lblas -llapack -mmacosx-version-min=10.6
Kronecker:~ scanon$ lldb a.out
Current executable set to 'a.out' (x86_64).
(lldb) b dgetrf_
Breakpoint 1: 2 locations.
(lldb) run
...
frame #0: 0x00007fff8c9d6841 libBLAS.dylib`DGETRF_
libBLAS.dylib`DGETRF_:
...

Problem linking my code with ARPACK on OSX (using MacPorts for ARPACK)

add to linker -lgfortran .................



Related Topics



Leave a reply



Submit