How to use dylib in Mac OS X

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? Thanks a lot!

Check dependencies of your app using otool -L app. If they are hardcoded as absolute paths then modify them using install_name_tool -change old new file to become relative one. After that the linker may find a library in your DYLD_LIBRARY_PATH environment variable. –  aponomarenko


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.

Lets 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 intall 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)
    ...
share | improve this answer
 

You need to set the DYLD_LIBRARY_PATH environment variable.

From the dyld man page:

      This  is  a  colon  separated  list  of directories that contain libraries. The dynamic linker
      searches these directories before it searches the default locations for libraries.  It  allows
      you to test new versions of existing libraries.

      For  each  library  that  a program uses, the dynamic linker looks for it in each directory in
      DYLD_LIBRARY_PATH in turn. If it still can't find the library,  it  then  searches  DYLD_FALL-
      BACK_FRAMEWORK_PATH and DYLD_FALLBACK_LIBRARY_PATH in turn.
share | improve this answer
 
 
thanks! I also found this by google, I did set the DYLD_LIBRARY_PATH, however, it doesn't work, problem is still there! I am so confusing –   Alfred Zhong  Jan 13 '11 at 5:36
 
I just tried it and it works great on my Mac. –   EmeryBerger  Jan 13 '11 at 5:38
 
Hi, EmeryBerger,is you DYLD_LIBRARY_PATH variable originally empty. mine is. I don't know if this is wrong at the first place. –   Alfred Zhong  Jan 13 '11 at 5:41 
 
Yes, originally empty. –   EmeryBerger  Jan 13 '11 at 5:43
2  
@AlfredZhong Make sure you use export when you set DYLD_LIBRARY_PATH . See here for why:stackoverflow.com/a/8699244/402807 –   AlcubierreDrive  Jan 3 '12 at 3:37 

If the dylib is in the place specified by the INSTALL_NAME of the library, it will Just Work*.

Otherwise, you can add the location of the dylib to DYLD_LIBRARY_PATH. You might want to read thedyld documentation.

*) to be totally precise, it needs to be at DYLD_ROOT_PATH/INSTALL_NAME, but fussing with DYLD_ROOT_PATH is pretty rare.

share | improve this answer

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值