Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash on macOS: dyld[50112]: Library not loaded: @rpath/libclang.dylib #6

Open
mario-grgic opened this issue Apr 7, 2024 · 5 comments

Comments

@mario-grgic
Copy link

Describe the bug
Built clangql from git on macOS Sonoma 14.4.1 with rust 1.71.1 and the resulting binary is crashing due to unset LC_RPATH, and hence the binary fails to load libclang.dylib

$ clangql
dyld[50112]: Library not loaded: @rpath/libclang.dylib
  Referenced from: <2E046823-CCFD-39AC-8724-B8765694F2F4> /usr/local/bin/clangql
  Reason: no LC_RPATH's found
Abort trap: 6
@narayana-dev
Copy link

I used DYLD_FALLBACK_LIBRARY_PATH to set my libclang.dylib path and it worked afterwards. Not sure if there is any way to fix this via code. I seen that opencv faces this issue in rust

@AmrDeveloper
Copy link
Owner

I used DYLD_FALLBACK_LIBRARY_PATH to set my libclang.dylib path and it worked afterwards. Not sure if there is any way to fix this via code. I seen that opencv faces this issue in rust

Thats good i think we can't solve this using code but when we release executables we don't need dyn linking for all users

I will mark this issue as solution for anyone who faced same issue

Thank you

@mario-grgic
Copy link
Author

Please note that macOS sanitizes your environment if you have System Integrity Protection (SIP) enabled. E.g. export DYLD_FALLBACK_LIBRARY_PATH=/usr/local/lib followed by echo $DYLD_FALLBACK_LIBRARY_PATH prints nothing.

The following variables are sanitized:

    DYLD_LIBRARY_PATH
    DYLD_FALLBACK_LIBRARY_PATH
    LD_LIBRARY_PATH
    DYLD_INSERT_LIBRARIES

See more info here: https://briandfoy.github.io/macos-s-system-integrity-protection-sanitizes-your-environment/

Please also note that from macOS Sonoma onwards the dynamic linker no longer sets DYLD_FALLBACK_LIBRARY_PATH (it used to be set to /usr/local/lib:/usr/lib previously, which allowed binaries to find libraries in those paths without having to explicitly set library load paths). This means that maintainers of software now have to make an explicit decision on how to find dependent libraries. The choices are to:

  1. Set the absolute path to the dependent library
  2. Use @rpath and LC_PATH loader command to set absolute path to the library from
  3. Use @rpath and LC_PATH loader command to set library load path relative to the executable (use variables like @executable_path or @loader_path).

Last choice offers most flexibility to relocate the executable binary. However, low level system tools should probably use option 1. I think this tool probably should as well.

For more information see man dyld.

So, the proper solution here is to somehow pass -rpath option to the system linker. I've done a bit of research and it looks like cargo build system is a bit immature in this regard. There was a request to add support for setting arbitrary rpaths through cargo over 6 years ago, but it is still Open:

rust-lang/cargo#5077

@AmrDeveloper
Copy link
Owner

Please note that macOS sanitizes your environment if you have System Integrity Protection (SIP) enabled. E.g. export DYLD_FALLBACK_LIBRARY_PATH=/usr/local/lib followed by echo $DYLD_FALLBACK_LIBRARY_PATH prints nothing.

The following variables are sanitized:

    DYLD_LIBRARY_PATH
    DYLD_FALLBACK_LIBRARY_PATH
    LD_LIBRARY_PATH
    DYLD_INSERT_LIBRARIES

See more info here: https://briandfoy.github.io/macos-s-system-integrity-protection-sanitizes-your-environment/

Please also note that from macOS Sonoma onwards the dynamic linker no longer sets DYLD_FALLBACK_LIBRARY_PATH (it used to be set to /usr/local/lib:/usr/lib previously, which allowed binaries to find libraries in those paths without having to explicitly set library load paths). This means that maintainers of software now have to make an explicit decision on how to find dependent libraries. The choices are to:

  1. Set the absolute path to the dependent library
  2. Use @rpath and LC_PATH loader command to set absolute path to the library from
  3. Use @rpath and LC_PATH loader command to set library load path relative to the executable (use variables like @executable_path or @loader_path).

Last choice offers most flexibility to relocate the executable binary. However, low level system tools should probably use option 1. I think this tool probably should as well.

For more information see man dyld.

So, the proper solution here is to somehow pass -rpath option to the system linker. I've done a bit of research and it looks like cargo build system is a bit immature in this regard. There was a request to add support for setting arbitrary rpaths through cargo over 6 years ago, but it is still Open:

rust-lang/cargo#5077

Thank you so much for information, I will use them in CD Too

@narayana-dev
Copy link

@AmrDeveloper Try using compiler flags -rpath liek @mario-grgic suggested. When I faced this problem for cpp project I built in that way not sure if there is a way to do that in Rust or not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants