Skip to content

Deduplicate @executable_path rpaths on macos #25

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

mjakeman
Copy link
Contributor

@mjakeman mjakeman commented Aug 3, 2025

Fixes an issue where duplicate rpath entries prevent dynamic library loading on macOS.

Lots of hair-pulling involved here 😫

Change to ld behaviour on macOS Sequoia

This is really poorly documented, but on macOS 15.4 and later (may be related to an XCode version bump), there's been a change which prevents dynamically loading a library with duplicate rpaths.

This means when linking against more than one SDL library, the resulting artefact can't itself be loaded as a shared library.

(Same issue as NixOS/nixpkgs#395169)

The Problem

In the following configuration:

  • Dynamic library (e.g. mygame) linking to SDL2_image and SDL2_ttf
  • Host executable (e.g. mygame-host) which renders a window using SDL2 and loads the above dylib

Because both link_SDL2_image and link_SDL2_ttf contain the following line:

.macos => {
    compile_step.linkFramework("SDL2_image");

    // this one ----
    compile_step.root_module.addRPathSpecial("@executable_path");
},

We end up having a library mygame with multiple RPATH addRPathSpecial("@executable_path") entries.

Manual Fix

We can look at the built library:

$ otool -l /some/path/to/mygame.dylib

...
Load command 11
          cmd LC_RPATH
      cmdsize 32
         path @executable_path (offset 12)
Load command 12
          cmd LC_RPATH
      cmdsize 32
         path @executable_path (offset 12)
...

Fixing manually:

install_name_tool -delete_rpath @executable_path /some/path/to/mygame.dylib

Proper Fix?

The only way I could think of (acknowledging that other zig dependencies could also set an rpath) was to check whether an rpath exists first before adding our own. It's a bit convoluted, but works well in my testing.

@hazeycode
Copy link
Member

Alternatively, we should leave it up the user to do the appropriate linking for their use case... Maybe we delete the link_ fns from build.zig and offer linking advice in the Readme instead?

@mjakeman
Copy link
Contributor Author

mjakeman commented Aug 5, 2025

Maybe we delete the link_ fns from build.zig and offer linking advice in the Readme instead?

Yep, agreed that's the best option here. Unambiguous, and we don't try to do "too much".

Happy to do that in this PR

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

Successfully merging this pull request may close these issues.

2 participants