Skip to content

fix macos rpath: use @executable_path instead of literal $executable_path#34

Closed
curusarn wants to merge 1 commit into
ucpu:masterfrom
curusarn:fix-macos-rpath
Closed

fix macos rpath: use @executable_path instead of literal $executable_path#34
curusarn wants to merge 1 commit into
ucpu:masterfrom
curusarn:fix-macos-rpath

Conversation

@curusarn

Copy link
Copy Markdown
Collaborator

Summary

cmake/cage_build_configuration.cmake sets CMAKE_BUILD_RPATH / CMAKE_INSTALL_RPATH to the literal string $executable_path on Apple platforms. macOS dyld doesn't recognize that — it uses @-prefixed tokens (@executable_path, @loader_path, @rpath), unlike ELF's $ORIGIN. The result is an LC_RPATH that dyld can't resolve, so any binary that depends on a sibling dylib via @rpath/… fails to launch.

Symptom

Helper executables built against cage crash at launch on macOS:

Library not loaded: @rpath/libcage-core.dylib
  Referenced from: …/unnatural-server
  Reason: tried: '$executable_path/libcage-core.dylib' (no such file), …

The main game executable can mask this if it's launched with a cwd or env that happens to satisfy the broken rpath, but spawned subprocesses (which inherit a hardened-runtime env on macOS) reliably crash in dyld before main().

Discovered while debugging Unnatural Worlds — every spawned unnatural-server / unnatural-ugc / unnatural-map-editor died at launch, generating 23 .ips crash reports across an 8-minute session and producing localhost connection timeouts from the client.

Fix

Replace \$executable_path with @executable_path in the if(APPLE) branch. The Linux branch (\$ORIGIN) is correct and stays as-is — the leading \$ escape is needed there because $ is a CMake variable trigger; @ is not, so no escape is needed on the macOS side.

Test plan

  • Built Unnatural Worlds locally (binaries shipped via Steam depot 2369784, build 23280696) reproduce the crash.
  • Patching the shipped binaries post-hoc with install_name_tool -add_rpath @executable_path + codesign -fs - resolves the crash, confirming root cause.
  • CI build on macOS confirms otool -l <target> | grep -A2 LC_RPATH shows @executable_path (not $executable_path).
  • Linux build unaffected ($ORIGIN unchanged).

🤖 Generated with Claude Code

…path

The Apple branch was setting CMAKE_BUILD_RPATH/CMAKE_INSTALL_RPATH to
"\$executable_path" — a literal directory name that dyld cannot resolve.
macOS dyld uses @-prefixed tokens (@executable_path, @loader_path, @rpath),
not $-prefixed ones like ELF's $ORIGIN.

Symptom: helper executables that depend on @rpath/libcage-core.dylib
(or any other neighboring dylib via the configured rpath) crash at launch
with `Library not loaded: @rpath/libcage-core.dylib ... tried:
'$executable_path/libcage-core.dylib' (no such file)`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@malytomas malytomas closed this in 6c263f5 May 20, 2026
@malytomas

Copy link
Copy Markdown
Member

thanks

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants