Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use dylib in Mac OS X (C++)

I made an application (an executable) calling some dylib successfully. However, the dylib files and the executable are in different directory. I added the directory contains dylib files to the $PATH environment variable. However, it still doesn't load. I copy all the dylib files to the executable, the program finally runs. This confirms the dylib files have no problem. However, how can I tell the OS to find it?
In windows, I just need to add the directory path contains dll files to $PATH. What do I need to do for Mac OS X?

like image 818
Alfred Zhong Avatar asked Jan 13 '11 05:01

Alfred Zhong


People also ask

What is Dylib Mac OS X?

A file with the DYLIB file extension is a Mach-O (Mach Object) Dynamic Library file that an application references during runtime in order to perform certain functions on an as-needed basis. The format has replaced the older A. OUT file format.

Where do I put Dylib files?

/usr/local/lib.

What is @rpath Mac?

@rpath stands for Runpath Search Path. In the Xcode, it's set with LD_RUNPATH_SEARCH_PATH setting. In ld command tool it's set with -rpath parameter when linking. So it's a search path for the linker. Runtime Search Path instructs the dynamic linker to search a list of paths in order, to locate the dynamic library.


1 Answers

After reading the link that Justin provided, I was successfully able to use the @executable_path token to change my dylib install_name to point to the same dir where my executable is located.

@executable_path Absolute paths are annoying. Sometimes you want to embed a framework into an application instead of having to install the framework into /Library or a similar location.

The Mac's solution to this is @executable_path. This is a magic token that, when placed at the beginning of a library's install name, gets expanded to the path of the executable that's loading it, minus the last component. For example, let's say that Bar.app links against Foo.framework. If Bar.app is installed in /Applications, @executable_path will expand to /Applications/Bar.app/Contents/MacOS. If you intend to embed the framework in Contents/Frameworks, then you can just set Foo.framework's install name to @executable_path/../Frameworks/Foo.framework/Versions/A/Foo. The dynamic linker will expand that to /Applications/Bar.app/Contents/MacOS/../Frameworks/Foo.framework/Versions/A/Foo and will find the framework there.

http://www.mikeash.com/pyblog/friday-qa-2009-11-06-linking-and-install-names.html

I will demonstrate with an example.

Let's say I have the following executable /opt/local/bin/convert and its dylibs are in /opt/local/lib. I want to copy it to another dir and have it load its dylibs from the same directory as where I copied the executable.

> mkdir ~/tmp/bin > cp /opt/local/bin/convert ~/tmp/bin 

Get a list of the executables dylibs

> otool -L ~/tmp/bin/convert ~/tmp/bin/convert:     /opt/local/lib/libtiff.3.dylib (compatibility version 13.0.0, current version 13.5.0)     /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)     /opt/local/lib/libjpeg.8.dylib (compatibility version 12.0.0, current version 12.0.0)     /opt/local/lib/libfontconfig.1.dylib (compatibility version 6.0.0, current version 6.4.0)     /opt/local/lib/libiconv.2.dylib (compatibility version 8.0.0, current version 8.1.0)     /opt/local/lib/libfreetype.6.dylib (compatibility version 15.0.0, current version 15.0.0)     /opt/local/lib/libexpat.1.dylib (compatibility version 7.0.0, current version 7.2.0)     /opt/local/lib/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.6)     /opt/local/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.6)     ... 

I only care about the dylibs in the /opt/local/lib dir, so we pull out only dylibs in /opt. I want to keep all other dylib references intact especially to /usr/lib/libSystem stuff.

> DYLIBS=`otool -L ~/tmp/bin/convert | grep "/opt" | awk -F' ' '{ print $1 }'` 

Copy all the dylibs that the executable references to the same dir where the executable has been copied to.

> for dylib in $DYLIBS; do cp $dylib ~/tmp/bin/; done; 

Use the install_name_tool to change the install name of all the dylibs we pulled out in the step above, and replace them by prepending the @executable_path to the dylib name. This will make the dynamic linker look for the dylib in the same directory as where the executable is located.

> for dylib in $DYLIBS; do install_name_tool -change $dylib @executable_path/`basename $dylib` ~/tmp/bin/convert; done; 

Confirm that the install names have been changed and that libSystem is still pointing to /usr/lib/libSystem.

> otool -L ~/tmp/bin/convert ~/tmp/bin/convert:     @executable_path/libtiff.3.dylib (compatibility version 13.0.0, current version 13.5.0)     /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)     @executable_path/libjpeg.8.dylib (compatibility version 12.0.0, current version 12.0.0)     @executable_path/libfontconfig.1.dylib (compatibility version 6.0.0, current version 6.4.0)     @executable_path/libiconv.2.dylib (compatibility version 8.0.0, current version 8.1.0)     @executable_path/libfreetype.6.dylib (compatibility version 15.0.0, current version 15.0.0)     @executable_path/libexpat.1.dylib (compatibility version 7.0.0, current version 7.2.0)     @executable_path/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.6)     @executable_path/libz.1.dylib (compatibility version 1.0.0, current version 1.2.6)     ... 
like image 150
Akos Cz Avatar answered Sep 23 '22 01:09

Akos Cz