dlopen() with dependencies between libraries - macos

My program uses plugins, that are loaded dynamically with dlopen(). The locations of these plugins can be arbitrary, so they aren't necessarily in the library path. In some cases, one plugin needs to depend on another plugin. So if A and B are dynamic libraries, I'll first load A, then load B which uses symbols defined in A.
My reading of the dlopen() documentation implies that if I specify RTLD_GLOBAL this should all work. But it doesn't. When I call dlopen() on the second library, it fails with an error saying it couldn't find the first one (which had already been loaded with dlopen()):
Error loading library /usr/local/openmm/lib/plugins/libOpenMMRPMDOpenCL.dylib: dlopen(/usr/local/openmm/lib/plugins/libOpenMMRPMDOpenCL.dylib, 9): Library not loaded: libOpenMMOpenCL.dylib
Referenced from: /usr/local/openmm/lib/plugins/libOpenMMRPMDOpenCL.dylib
Reason: image not found
How can I make this work?

See this answer here:
dlopen() error image not found
If you modify the library to have an install name of #rpath/blah.dylib, you'll be able to do this.
Edit:
I'm also using cmake, use this:
set_target_properties(${MY_LIB} PROPERTIES BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "#rpath")
This doesn't break things on other platforms either, but make sure you haven't called CMAKE_SKIP_RPATH or it won't be invoked.

Related

Will a program run if a .so file is not found but no function is called

The question is for example I have my.binary that depends on 1.so that depends on 2.so that depends on 3.so.
When doing 'ldd 1.so', it only shows that it depends on '2.so', so will my.binary execute if '3.so' is missing but not a function is called from '3.so'? Basically '3.so' is shipped with my.binary, but during some runtime checks, it is not used under certain condition.
I do see sharedlibrary not found error if 2.so does not exist..
No, this functionality is called lazy loading and is not supported by Linux shared libraries. You can work around this by manually loading library via dlopen/dlsym instead of directly linking to it.

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

I have two plugins pluginA.plugin and pluginB.plugin which are both depend on same library libC.dylib. When plugins are built, I recursively go over dynamic dependencies (use otool -L), copy all dependencies inside each plugin's libs folder and adjust dependencies paths using install_name_tool, i.e. "carrying all all my stuff with me" approach.
I'm trying to understand what is happening when those two plugins will be loaded by some program? Will libC.dylib be loaded twice and this will cause runtime crash? Or will runtime realize that there are two copies of the same dylib (based on versions?) and use just one?
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

How can I tell why my program requires a specific shared library?

I'm working on an OS X application using a third-party framework. This framework is distributed both as shared objects and static objects. For my purposes, I want to use the static objects because I can't rely on the presence of the library on other systems.
However, when I build the application with Xcode, something decides it needs the shared objects, and when I run it, dyld tells me off before I even get to my program:
dyld: Library not loaded: /usr/local/lib/libshared.dylib
  Referenced from: /Users/me/Library/Developer/Xcode/snip/Application.app/Contents/MacOS/Application
  Reason: image not found
I ran otool -L on the executable, and sure enough, it tried to link against the shared objects (which aren't even installed on my system). However, when I ran it on the thirty-some .a files that I link against, none of them indicated any dependency on them.
Apple's ld -v is just a tad verbose: it displays the library search paths but doesn't produce any other kind of useful output.
How can I find what tried to link against the shared objects?
otool -L does list the libraries against which any object links.
This specific instance was caused by an Xcode bug (known as rdar://2725744 to the ones blessed with Apple bug database access, and not fixed as of Xcode 6.1.1) where if you try to link against a .a static library with Xcode but there's a .dylib (or .so) dynamic library with the same name in the same directory, the linker will pick the dynamic one.
When you instruct Xcode to link against a static library (say /some/path/to/my/libFooBar.a), it adds -L/some/path/to/my -lFooBar to the linker invocation. However, with it, ld first searches for a dynamic library called libFooBar.dylib, and it will fall back to the static library only if it can't find the dynamic one.
If you added the framework is listed in the "Build Phases" of "Link Binary with Libraries" and it has the setting of "Required" that could explain why the launch fails.
Try changing the setting to "Optional". Then if nothing uses the framework, it should launch fine. (If something tries to use the framework, but fails to check for it first, it might crash.)

Undefined reference to several OpenMP functions

I was trying to compile an openMP example and he refuses to compile saying "undefined reference to 'OSCR_init', undefined reference to `OSCR_getarg_int' and several other functions. Then I located these functions in the file OmpSCR.h, that came in another folder, searched inside it and saw that these funcions were defined externally, I believe that in omp.h. I included the file with "include " in the example source (OmpSCR.h was already included) hoping that it would solve the question, but nothing improved. I do have omp.h, it came with the os. Can it be a version conflict? I got the example file from OMPSCR_v2.0.tar.gz What should I do?
An "undefined reference" error means that no definition of the function was found at link time. A declaration in a header (such as omp.h) doesn't provide an implementation for the function; it just tells the compiler that the function exists somewhere. You have to link your program with a library that actually provides the function's implementation.
Basically, you just need to link your program to an OpenMP library. The way to do this depends on which compiler and which OpenMP implementation you're using, neither of which you've specified, so I can't provide specifics. (But if you happen to be using GCC, you should use the -fopenmp option for both compiling and linking.)

dyld: lazy symbol binding failed: can't resolve symbol

So I've been working on a c++ project in XCode and am making use of an external framework (SFML http://www.sfml-dev.org/ ).
I recently decided to upload my project to github and then tried checking out the project on another Mac.
However, when I try to run my program on the new computer, I get this error
dyld: lazy symbol binding failed: can't resolve symbol __ZN2sf5ImageC1Ev in
/Users/myname/Library/Developer/Xcode/DerivedData/projectname-
fufhzxbkoeekzeayzzlrtvgajvnn/Build/Products/Debug/projectname because dependent
dylib #3 could not be loaded
I have no idea what this means and have been having a hard time finding out online what exactly the issue is.
That error message indicates that you are linking against a Shared Library (dylib) which is not available in the library path at run time when you are executing it.
If you have installed the framework in one of the standard locations (such as /Library/Frameworks) on your original build and in the same place when you checked it your and rebuilt, then you should be OK. However, there are some complexities to framework linking that can cause trouble if you are not careful, especially if you use embedded frameworks. It looks like you are not building an application, so I assume you're not embedding the framework.
Compare the installation locations of your frameworks on both the new and old computer and if they are not the same, that's likely your problem.
If things look like they are in the same place, you may need to check the DYLD_LIBRARY_PATH (good stack exchange question about dyld).

Resources