How to set dylib search path OSX
Asked Answered
B

1

12

I have a project in Xcode where I set DYLD_FALLBACK_LIBRARY_PATH in the environment variables pane to set where my application should look for libraries to link to (which works well for my purposes)

enter image description here

I am writing a CMakeLists.txt file to generate this project now and I would like to set this property from the script.

I am aware I can do this:

SET(ENV{DYLD_FALLBACK_LIBRARY_PATH} ${DYLD_FALLBACK_LIBRARY_PATH} /path/to/lib)

but when I run I get this error:

'dyld: Library not loaded ... Reason: image not found' 

when launching the application. I imagine the statement is not the same.

Does someone know how I can achieve the equivalent of what I have in Xcode from CMakeLists.txt?

I am vaguely aware of the CMake RPATH stuff but I'd rather avoid that if possible.

Thank you for your time!

Cheers!

Tom

Baiss answered 31/7, 2016 at 15:36 Comment(5)
I am vaguely aware of the CMake RPATH stuff but I'd rather avoid that if possible. - But this is the proper way for do things you want. See cmake.org/Wiki/CMake_RPATH_handling for more info. SET(ENV{..}) sets environment variable only on cmake run stage, it doesn't affect on environment for build or run stages.Phycomycete
Hi! I should probably have emphasised vaugely... :P My situation is I have a dylib (in this case SDL) that I want to link at runtime, but I do not want to have to add it to the system path (/usr/local/bin..) I had a look into the RPATH stuff but it all just looked super convoluted. I have read through that article and tried some of the CMake stuff it says to use but didn't have much luck. Do I have to do the dylib install_name_tool thing? I wanted to avoid that as it seemed a bit weird. My background is mainly Windows so maybe I'm missing something obvious! Thanks!Baiss
If you have problems when follow given CMake article about RPATH, describe that specific problems.Phycomycete
In the link you mention, I attempted to use the CMake example under the section 'Always full RPATH' - but I wasn't sure if I needed to modify my existing dylib. If I run otool -L, the paths are absolute, and my app is looking for my shared lib in usr/local/bin (where it isn't) I don't really want to modify the dylib if I can help it, and I haven't built that myself.Baiss
Maybe a bit late, but if somebody else wants to avoid the @rpath stuff and comes across this post, just call your compiled program like DYLD_LIBRARY_PATH=<path to lib> ./<program>. Credit: superuser.com/a/282451Xylene
B
20

I did finally get this working using a slightly different approach. This might not be the perfect solution and work in all cases, but hopefully this will help someone who is having similar problems to me.

The dylib I was trying to link to was libSDL2-2.0.0

If I navigate to where that file is located and run:

otool -L libSDL2-2.0.0.dylib

the top line I get in the output is this:

/usr/local/lib/libSDL2-2.0.0.dylib

if I then navigate to my built executable and run the same command, I see the same thing:

/usr/local/lib/libSDL2-2.0.0.dylib

(my executable links to SDL)

My problem was libSDL2-2.0.0.dylib is not actually located there, it's in my project structure in a libs folder. In order to get the linker to find the lib at runtime, I had to run this command on the dylib

install_name_tool -id "@executable_path/../path/to/lib/<lib_name>" <lib_name>

where @executable_path is the location of the application to run - in my case this was in - build/debug

The project structure:

root/
    CMakeLists.txt
    project/
        lib/
            libSDL2-2.0.0.dylib
    build/
        debug/
            my_app

This is an exact mapping for clarity:

install_name_tool -id "@executable_path/../../project/lib/libSDL2-2.0.0.dylib" libSDL2-2.0.0.dylib

If I run otool -L libSDL2-2.0.0.dylib I now see:

@executable_path/../../sdl-test/lib/libSDL2-2.0.0.dylib

in the first line of the output.

If I now build my project again (I'm just building in Xcode), this updates my app with the new relative path to the dylib. You only have to run install_name_tool on the library, you do not also have to run it on your executable, it will be updated when you build it.

If I run otool -L myapp I now see the same relative path to libSDL2-2.0.0.dylib

With that, when launching the app it was able to successfully find the dylib!

My understanding is that this is the way to achieve this on OSX and there isn't a brilliant alternative (other than messing with DYLD_FALLBACK_LIBRARY_PATH which I mentioned in my question)

I hope this has been of some help to someone who had similar difficulties to me!

Resources I found useful:

http://osiris.laya.com/coding/dylib_linking.html

https://www.fmod.org/questions/question/forum-23398/

https://blogs.oracle.com/dipol/entry/dynamic_libraries_rpath_and_mac

UPDATE:

I actually found an even better way to do this using rpaths and thought I'd write up how to do this for future reference:

In my CMakeLists.txt file I added these lines right at the end (after add_executable and target_link_libraries:

# set @rpaths for libraries to link against
set(CMAKE_SKIP_BUILD_RPATH  FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) 
set(CMAKE_INSTALL_RPATH "${PROJ_LIB_DIR}")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)

(see https://cmake.org/Wiki/CMake_RPATH_handling for more info)

where ${PROJ_LIB_DIR} is where my dylibs are located:

set(PROJ_LIB_DIR ${CMAKE_CURRENT_LIST_DIR}/lib)

I then ran:

example:

install_name_tool -id "@rpath/<my-dylib>.dylib" <my-dylib>.dylib

actual:

install_name_tool -id "@rpath/libSDL2-2.0.0.dylib" libSDL2-2.0.0.dylib

in the directory where my dylib is located (in my case libSDL2-2.0.0.dylib)

Now when I run cmake and then build my project, my new executable will search for the library in the location I set in the CMakeLists.txt file at runtime. @rpath will be substituted with the path specified in the CMakeLists.txt file and everything just works without explicitly having to set the @executable_path or @loader_path

Baiss answered 1/8, 2016 at 23:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.