How to get an LC_RPATH and @rpath/ prefix on a dylib on macos

Hi All,
I’m trying to solve the apparently common problem on macos of getting cmake to do what I’m doing with install_name_tool. The common problem is that I link against 3rd party dylib, and at run-time the dylib is not found because it is not where macos expects it. (It isn’t installed in /usr/local/lib)

For my purposes, I’d like the reference to the dylib to be prefixed with @rpath/, and I’d like an LC_RPATH entry pointing at the location of the library that I linked against. I can do this using the install_name_tool:

install_name_tool -add_rpath /path/to/lib MyExecutable
install_name_tool -change libThirdParty.dylib @rpath/libThirdParty.dylib MyExecutable

Trouble is, despite all the posts on the subject, I have yet to find one that spells out what to do. There are hints about MACOSX_RPATH, use a POST_BUILD command (to do what I’m doing on the command-line), do something with CMAKE_BUILD_WITH_INSTALL_RPATH, or simply CMAKE_INSTALL_RPATH_USE_LINK_PATH.

Regardless of what I’ve tried, I never end up with new name in the LC_LOAD_DYLIB command nor a new path and an LC_RPATH command.

What can I try next?

1 Like

If the dependency is not built with an @rpath-using library ID, I would recommend getting it built with such an ID first. Any fixes like install_name_tool -change are best done during packaging rather than on every use within the build because it doesn’t scale at that point.

1 Like

Thanks for the response! Supposing I did patch the build of the dependency. Would I get my executable’s LC_RPATH command in the usual way via -rpath or is there a “proper” CMake way to do it?

You can use the target BUILD_RPATH and INSTALL_RPATH properties to add the path you need.

1 Like

Hmm… something like this?

add_executable(MyExecutable ${SOURCES_STAGE} )
set_target_properties(MyExecutable PROPERTIES
    BUILD_RPATH "/this/path/should/be/used"
    INSTALL_RPATH "/so/should/this"    
    )

Does this only affect the loader commands in the executable when it is installed? It doesn’t look like it changed anything according to otootl -l after I did a clean rebuild cmake --build build --clean-first.

INSTALL_RPATH only affects the installed binary; BUILD_RPATH should show up in the build tree.

1 Like

Does this mean that if I set the BUILD_RPATH property on my executable, that I should expect to see a matching LC_RPATH entry in executable found in my build tree?

1 Like

Yes. It should show up on the executable’s link line as well.

1 Like

Well this hasn’t been at all painful. :wink: Based on your comments I created a test project with nothing but hello world and an rpath — and … it worked. Just didn’t work in my “real” project.

After reducing my “real” project to building my test project, it still didn’t work, so I thought to compare CMakeCaches between the two projects. I found that the broken project had CMAKE_SKIP_RPATH set. So I trashed the cache, and reconfigured at which point I noticed a log message: Conan: Adjusting default RPATHs Conan policies which is presumably where the bit about skipping rpaths is set up. Just … wow.

Now to figure out where/why/how conan does that.

Anyway… thanks for moving the ball down the field!

1 Like