Overriding @executable_path in the DLL loaded by dlopen ()

The operating system is MacOS X, specifically 10.5 (Leopard) on PowerPC G4, but I have the same problem on x86 running 10.6.

I am writing an application that dynamically loads a DLL. A DLL (let it be called foo.dylib ) is part of another application located elsewhere on the hard drive; my application finds the program code foo.dylib (the exact installation may vary, perhaps the user specifies the path to the DLL via the GUI from the running application). For example, suppose my application is in the /Application/MyApp.app/Contents/MacOS directory, and foo.dylib is in /Application/OtherApp.app/Contents/MacOS . DLL loading uses dlopen() .

Now, it turns out that foo.dylib itself needs a bunch of other DLLs that are in the same directory, but of which I know nothing in advance. Each such additional DLL is registered in foo.dylib with a path like @executable_path/bar.dylib . The semantics of @executable_path is that it should be replaced by the directory in which the current executable file of the process was found. This works fine for OtherApp, not for me: when I open foo.dylib , it tries to load bar.dylib and it looks for it in /Application/MyApp.app/Contents/MacOS/bar.dylib , which is not the correct directory .

A workaround is to set the environment variable DYLD_FALLBACK_LIBRARY_PATH to /Application/OtherApp.app/Contents/MacOS , but this should be done before starting my application (this environment variable is read only once by the dynamic linker, modifying it programmatically using setenv() or putenv() does not affect). This is not compatible with the dynamic location detection of the foo.dylib file.

Is there a programmatic way to override the effect of @executable_path ?

+7
source share
2 answers

From reading dyld source (search for @executable_path), I would say that the answer is definitely no. @executable_path is replaced by the main executable path, which is stored as a global string in the dyld module.

And yes, your suspicion is correct, dyld reads and saves its environment variables at startup, so you cannot change them on the fly (you can search for the same source file that I linked for DYLD_LIBRARY_PATH). You may have a stub application that sets environment variables and then runs your real application. dyld does not offer you many solutions here, it is not intended to allow you to reference arbitrary private third-party libraries.

+6
source

if you support OtherApp, you can use @loader_path instead of @executable_path to search for dependencies: @loader_path always resolves the module path (i.e. library or executable), which requires loading the library, so there are always recursive dependencies.

It is available from Mac OS 10.5 onwards.
See "Man dyld" for more details.

Another option would be dlopen dependent dependencies in front of the main library.

+2
source

All Articles