I have created a mex function which relies on a library that relies on another library. When I execute the function, it outputs this error at runtime:
Invalid MEX-file
...
Library not loaded: /usr/local/lib/libgomp.1.dylib
I do have this library on my computer but it is located in usr/local/gfortran/lib
So I tried this:
setenv('DYLD_LIBRARY_PATH', '/usr/local/gfortran/lib');
But this doesn't fix the issue at all. I'm using MacOS Sierra 10.12.6. How can I make MATLAB search for that specific folder?
MacOS works differently than other OSes with regard to how it searches for dynamic libraries (== shared objects). A few things to know:
Each .dylib
file has an "install name". This is a string embedded in the file that tells the linker where it is to be found. When you link your library/executable/MEX-file to the .dylib
, the "install name" is stored and used at run time to locate the library. That is, it's not the current location of the file that is stored, but the location that it reports it should be found at.
The "install name" can start with "@rpath", this indicates a relative path.
An executable/library/MEX-file that links to a .dylib
can specify alternative directories where to search for dependencies. This is equivalent to the rpath
under Linux. These directories can be absolute, or start with "@executable_path" or "@loader_path", indicating a relative path. "@executable_path" is the directory of the executable (the MATLAB binary in case of a MEX-file), and "@loader_path" is the path of the binary that is trying to load the library (e.g. the MEX-file).
Here is more information on these topics: https://www.mikeash.com/pyblog/friday-qa-2009-11-06-linking-and-install-names.html
There are linker flags that you can use to set correct install names and rpaths and so forth, but you can also use the install_name_tool
program to change these things after linking. This might be easiest in your case.
In your case, you can use something like this to change where your MEX-file looks for the dependent library:
install_name_tool -change /usr/local/lib/libgomp.1.dylib usr/local/gfortran/lib/libgomp.1.dylib mexfile.mexmaci64
(replace mexfile.mexmaci64
with the name of your MEX file).
If you want to use relative paths, for example if you move the dependent libgomp.1.dylib
to a path that depends on the location of the MEX file, you'd instead do:
install_name_tool -change /usr/local/lib/libgomp.1.dylib @rpath/libgomp.1.dylib mexfile.mexmaci64
install_name_tool -add_rpath @loader_path/../lib mexfile.mexmaci64
or
install_name_tool -change /usr/local/lib/libgomp.1.dylib @loader_path/../lib/libgomp.1.dylib mexfile.mexmaci64