Mark's Logs

Reading, thinking, and seeing.

Install_name on OS X

| Comments

On OS X, the loader dyld does have a search path, defined in the DYLD_FRAMEWORK_PATH and DYLD_LIBRARY_PATH variables. However, these are empty on OS X by default, so they rarely matter.

Sometimes, we want to install a third-party library to a location, which is not system-defined, not /usr/local/lib nor /usr/lib, for some personal reasons or when you did not have root privilege. Suppose it was libdummy. If libdummy’s install_name was just libdummy.1.dylib or so, and you were building a program which links against libdummy. After the compilation, you checked the shared libraries your program used:

otool -L program

then you could see libdummy.1.dylib in the output, just libdummy.1.dylib in that line. Ja, the linker stored install_name there, not the location of the library. Then you let the program run, but the dyld said it could not find the proper libdummy.1.dylib. That’s the story a lot of people would experience on OS X.

On Linux, we could modify /etc/ in order to include some other directories when the loader searches for a library. However, on OS X things are different. Also, we would not like to set DYLD_ variables every time launching the program, nor add those variables in .zshrc, .bashrc, …

De facto, as we know install_name matters, we could simply employ it.

On Darwin platform, gcc has some platform dependent options, such as -dynamic, -arch, -bundle, and -install_name plays an important role here.

gcc -o libdummy.dylib -install_name ${PREFIX}/lib/libdummy.dylib ...

would set install_name for libdummy.dylib to a well-defined path. Next time when linking your program against libdummy, the linker would store that path. Use otool -D to print the install_nam for specified library.

Besides absolute paths, we could use other techniques as well: @executable_path, @loader_path, @rpath. This article describes these very well.

For already built libraries and programs, there is no need to rebuild them. On OS X, there is a very useful tool: install_name_tool.

  • change install_name for a library: install_name_tool -id "new_install_name" libdummy.dylib
  • change linked install_name in a program: install_name_tool -change "old_install_name" "new_install_name" program

One more thing. If you use cmake to generate Makefile for you project, you could solve the install_name issue like this:

SET(CMAKE_INSTALL_NAME_DIR @executable_path)

Replace @executable_path with your own choice.