Best way to locate shared (.dylib) libraries used by MATLAB mex files on MacOS X
54 次查看(过去 30 天)
显示 更早的评论
I'm using MATLAB on a MacOS X system, and building mex files. These mex files depend on various shared (.dylib) libraries, which I keep in the same directory as the mex files.
On older versions of MacOS X, in order to find those shared libraries at MATLAB run time, it was sufficient to have the environment variable DYLD_LIBRARY_PATH set to include that directory name. The variable could be set before starting MATLAB, or by setting it in a copy of the matlab script. Either way, so long as DYLD_LIBRARY_PATH was set to include the location before starting MATLAB or by making a copy of the matlab script which included a line to set DYLD_LIBRARY_PATH correctly, the mex files would work properly. If the environment variable was not set correctly, MATLAB would just issue an error message saying that dylibs couldn't be found.
But, on recent versions of MacOS X (or, perhaps, it's recent MacOS X combined with recent MATLAB - I'm not sure) this no longer works - DYLD_LIBRARY_PATH gets ignored, and the mex files fail, I guess because of Apple's tightened security policies.
What does work is to make sure that MATLAB's current working directory is the directory containing the mex files and dylibs when using the mex files for the first time. After that you can change directories and the mex files still work. When you do this there's no need to worry about DYLD_LIBRARY_PATH. Presumably once the dylibs have been loaded in this way, they stay loaded and no longer need to be in your path. As far as I can tell this works with all versions of MATLAB from at least R2015b up to R2017b and with all versions of MacOS up to the latest I've got access to, which is MacOS X 10.12 (sierra).
So - when I distribute my mex files to other people, I just need to tell them that they need to be in the right directory before they first use one of them (or add code to their startup.m file to do it for them). In fact, I've not found any other way of getting it to work.
My question is - is this a sensible way of ensuring that dylibs needed by mex files on MacOS are located? If not, what is the recommended way?
4 个评论
Walter Roberson
2017-10-4
On the other hand, I am not certain I have identified the correct problem. System Integrity Protection seems to be limited as to which files it affects, and user-installed /Applications are not affected; https://support.apple.com/en-ca/ht204899
回答(1 个)
Jim Hokanson
2018-3-7
编辑:Jim Hokanson
2023-11-26
I've had some luck with the following command in the same directory as my mex file.
install_name_tool -change /Users/jim/Documents/repos/matlab_git/mex_lib_code/zip/libzip.dylib @loader_path/libzip.dylib kzip_mex.mexmaci64
or more generally:
install_name_tool -change <old_dylib_path> @loader_path/<dylib_file_name> <mex_file_name>
To get the first value, run:
otool -L kzip_mex.mexmaci64
This should report where the dylibs are being loaded from. Use these values as the first input.
The second input, in my case @loader_path/libzip.dylib, should be replaced with your dylib name, keeping the @loader_path part.
Finally, the third input specifies what file should be targeted for this change. Give it the name of your mex file.
Rerun the otool command and now you should see the path to the dylib has changed ...
Adding on things becaues I couldn't follow my own directions!!!
Extra note, you need to match the first input exactly from otool, this is NOT necessarily just the path to the dynamic library.
for example I ran this on my file:
otool -L libgit.mexmaci64
and got:
libgit2.dylib (compatibility version 26.0.0, current version 0.26.0)
@rpath/libmx.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libmex.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1300.23.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.100.3
but I want libgit2.dylib to not just be generically loaded, but to load in the SAME directory as my libgit.mexmaci64 file. So that change is:
install_name_tool -change libgit2.dylib @loader_path/libgit2.dylib libgit.mexmaci64
running otool again:
otool -L libgit.mexmaci64
I get:
@loader_path/libgit2.dylib (compatibility version 26.0.0, current version 0.26.0)
@rpath/libmx.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libmex.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1300.23.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.100.3)
so that entry has been successfully changed from the old value to the new value
Note, the @loader_path is relative to your mex file. So if you kept your dylib file in a subfolder you would use something like @loader_path/my_sub_folder/mylib.dylib
Another note to self!!
The last file is the file you are modifying. It isn't being added to the dylib. Here's another example that I ran from inside MATLAB:
[status,result] = system('install_name_tool -change @rpath/libDIP.dylib @loader_path/libDIP.dylib numberofthreads.mexmaci64')
Doing this in MATLAB I could write a quick loop for all affected files.
base_str = 'install_name_tool -change @rpath/libDIP.dylib @loader_path/libDIP.dylib ';
d = dir([cd '/*mexmaci64'])
for i = 1:length(d)
[status,result] = system([base_str d(i).name]);
end
I could have probabaly moved the libDIP.dylib file to '/usr/lib' but this way the library is with the code and is easier for me to share.
2 个评论
Jim Hokanson
2018-9-2
I would think it would be pretty much the same process, just replace the mexmaci64 with the library that you are loading => my_library.dylib (instead of my_library.mexmaci64). Note in this case your goal is still to find dependencies of the dynamic library you are working with (either mex or dylib) and point those to a local copy.
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!