Bug #2705
closedInstall Path is not set in dylibs (shared libs) on OS X
0%
Description
The OS X dynamic loader is special in a way that it doesn't look in some predefined locations to discover the referenced shared libs when an application is launched.
Instead the path to the linked dylib is stored in the mach-o binary. These entries are generated at link time.
Every dylib has an install name embedded inside the mach-o header. This is the path to the library itself. When the linker links against a dylib it reads the install name and writes it to the currently building binary as dependency.
What the wt build script fails to do is setting this install name. So it uses the default which is just the name of the lib without a path. This mean the loader just searches in the current working dir and fails to find the dylibs in their installation location.
Alexanders-iMac:lib alexander$ pwd
/opt/wt/lib
Alexanders-iMac:lib alexander$ otool -L libwthttp.3.3.1.dylib
libwthttp.3.3.1.dylib:
libwthttp.36.dylib (compatibility version 36.0.0, current version 3.3.1)
libwt.36.dylib (compatibility version 36.0.0, current version 3.3.1)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)
/usr/lib/libssl.0.9.8.dylib (compatibility version 0.9.8, current version 50.0.0)
/usr/lib/libcrypto.0.9.8.dylib (compatibility version 0.9.8, current version 50.0.0)
/usr/local/lib/libboost_thread-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/local/lib/libboost_program_options-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/local/lib/libboost_system-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/local/lib/libboost_filesystem-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/local/lib/libboost_date_time-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/local/lib/libboost_random-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/local/lib/libboost_regex-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/local/lib/libboost_signals-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
You can pass -install_name to the linker to set the install name. Maybe there are some predefined functions in cmake to do this. I don't use cmake.
Updated by Wim Dumon over 10 years ago
- Status changed from New to Feedback
So maybe we should set this property? Could you test that and report if it works?
http://cmake.org/cmake/help/v2.8.10/cmake.html#prop_tgt:INSTALL_NAME_DIR
Updated by Wim Dumon over 10 years ago
Just found some extra information: http://www.cmake.org/Wiki/CMake_RPATH_handling
If I understand correctly cmake strips install_dir information on installation, maybe it helps if you change the defaults for some of the configuration options described there.
Updated by Alexander Theißen over 10 years ago
I added this to the CMakeLists.txt in the root dir:
SET (CMAKE_SKIP_BUILD_RPATH FALSE)
SET (CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
SET (CMAKE_INSTALL_RPATH \"${CMAKE_INSTALL_PREFIX}/lib\")
SET (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
Had no effect. I guess I have to set INSTALL_NAME_DIR on every target. But that means the full path is set even when not installing.
Updated by Alexander Theißen over 10 years ago
I meant:
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
Updated by Koen Deforche over 10 years ago
- Status changed from Feedback to InProgress
- Assignee set to Koen Deforche
- Target version set to 3.3.2
Hey,
I'm going to try this as well!
Regards,
koen
Updated by Koen Deforche over 10 years ago
- Status changed from InProgress to Feedback
Hey,
I found that by adding, in addition to the above, "SET (CMAKE_MACOSX_RPATH TRUE)" things started to move. Can you see if that's indeed the behavior you want?
Apparently this is available only since CMake 2.8.12: http://www.kitware.com/blog/home/post/510
Regards,
koen
Updated by Alexander Theißen over 10 years ago
It works now. I need to apply the following settings and set the RPATH (-rpath linker flag) on my own wt application.
# this is the new setting with 2.8.12 which makes the install name use @rpath
# you can check the install name with: otool -D <file>
set(CMAKE_MACOSX_RPATH TRUE)
# these 3 settings are to set the RPATH on the libs which will be substituted for @rpath at runtime
# you can check the RPATH with: otool -l <file> | grep LC_RPATH -A2
SET(CMAKE_SKIP_BUILD_RPATH FALSE) # activate the whole thing
SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) # we only need the RPATH when the lib is installed (otherwise use full path to source tree)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
The second block is important so that the different wt libs can find each other. Every lib or executable you link against wt therefore needs to set an appropriate RPATH. That makes it easily relocatable without messing with install_name_tool. If you get this code upstream and put a notice about setting the RPATH in the INSTALL, it would be appreciated.
Updated by Koen Deforche over 10 years ago
- Status changed from Feedback to Resolved
Hey,
Thanks for your help with this.
Regards,
koen
Updated by Koen Deforche over 10 years ago
- Status changed from Resolved to Closed