2

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?

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
tryingtosolve
  • 763
  • 5
  • 20
  • I know your pain! `DYLD_LIBRARY_PATH` seems to no longer work in the last few iterations of MacOS. What you need to do is set a liner flag when creating your MEX file, that sets the file's `rpath`. If this question is still here tonight I'll try to write up an answer. – Cris Luengo Jan 09 '18 at 22:26
  • @CrisLuengo Is this what I need to do: ```mex LDFLAGS='$LDFLAGS -Wl,-rpath,/usr/local/gfortran/lib' filename.cpp``` – tryingtosolve Jan 09 '18 at 22:35
  • That looks like Linux syntax. It works differently with MacOS, though I haven't manually specified rpaths in a while (CMake does this for me). I need to look at some old makefiles to remember the exact syntax. – Cris Luengo Jan 09 '18 at 22:45
  • @CrisLuengo I asked because it didn't work. The compilation went through but at run time I still see the error. – tryingtosolve Jan 09 '18 at 22:56
  • @CrisLuengo Actually, the compilation didn't go through. It said "clang: error: unknown argument: '-rpath,/usr/local/gfortran/lib'". – tryingtosolve Jan 09 '18 at 22:58

1 Answers1

1

MacOS works differently than other OSes with regard to how it searches for dynamic libraries (== shared objects). A few things to know:

  1. 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.

  2. The "install name" can start with "@rpath", this indicates a relative path.

  3. 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
Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
  • I typed this without testing any of it, from memory and linked web pages. Please let me know if there are errors so that I can fix them. – Cris Luengo Jan 09 '18 at 23:06
  • Related answer, but assumes you compile the dependent libary also (i.e. setting its install name properly before you link your own executable): https://stackoverflow.com/a/31824839/7328782 – Cris Luengo Jan 09 '18 at 23:11
  • Well explained! I tried ```install_name_tool -change /usr/local/lib/libgomp.1.dylib usr/local/gfortran/lib/libgomp.1.dylib mexfile.mexmaci64``` but the terminal gives me ```can't open file: mexfile.mexmaci64 (No such file or directory)```. Where is it located? – tryingtosolve Jan 09 '18 at 23:14
  • Ah, sorry, that's the name of the MEX file that you compiled. You didn't give a name in the question, so I invented one... :) – Cris Luengo Jan 09 '18 at 23:15
  • I see. I can't use ```install_name_tool``` at the MATLAB command window can I? – tryingtosolve Jan 09 '18 at 23:16
  • I tried that, but that didn't work. This is what I did. Compile as usual ```mex filename.cpp```. Afterwards I did ```install_name_tool -change /usr/local/lib/libgomp.1.dylib usr/local/gfortran/lib/libgomp.1.dylib filename.mexmaci64```. However when I execute the function I see the same error: ```Library not loaded: /usr/local/lib/libgomp.1.dylib```. – tryingtosolve Jan 09 '18 at 23:22
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/162850/discussion-between-cris-luengo-and-tryingtosolve). – Cris Luengo Jan 09 '18 at 23:26