Skip to content

Feature/unified rpath darwin#741

Draft
heyitsmohdd wants to merge 2 commits into
metacall:developfrom
heyitsmohdd:feature/unified-rpath-darwin
Draft

Feature/unified rpath darwin#741
heyitsmohdd wants to merge 2 commits into
metacall:developfrom
heyitsmohdd:feature/unified-rpath-darwin

Conversation

@heyitsmohdd
Copy link
Copy Markdown

I’ve implemented a unified RPath patching module (PatchRPath.cmake) to handle binary portability across both Darwin and Linux. This replaces the legacy, platform-specific hacks and the hard dependency on patchelf for macOS builds.

Key Changes:

Unified API: Created a metacall_patch_rpath function that automatically switches between install_name_tool (Darwin) and patchelf (Linux).

Darwin Linker Fixes: Updated the Rust loader build to use -Wl,-undefined,dynamic_lookup on macOS. This allows the compiler to ignore undefined MetaCall core symbols at build time, which are resolved at runtime when the plugin is loaded.

Dynamic Cargo Configuration: Introduced a .cargo/config.in template. CMake now generates the correct .cargo/config based on the host OS, ensuring Linux-specific flags like $ORIGIN don't break the Mac linker.

Build Order & Dependency Logic: Fixed a race condition where patching was attempted before the library was finished. The patching target now correctly waits for the Cargo build to complete and specifically includes the loader's own .dylib in the patch list.

How I tested it
I’ve verified this on Apple Silicon (M-series) with the following results:

Compilation: The Rust loader and MetaCall CLI now build to 100% success without manual environment tweaks.

Screenshot 2026-03-28 at 2 40 53 AM

Header Verification: Used otool -l to confirm that @loader_path is correctly embedded in the Mach-O load commands.

Screenshot 2026-03-28 at 2 42 04 AM

Runtime Check: The metacallcli initializes successfully. While it currently shows missing plugin errors (due to .so vs .dylib mapping), the core linking issues are fully resolved.

Screenshot 2026-03-28 at 2 51 38 AM

Comment thread cmake/PatchRPath.cmake
# limitations under the License.
#

include_guard(GLOBAL)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you explain this? it's new for me

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a modern CMake command introduced in 3.10 that works like #pragma once in C++. I used include_guard(GLOBAL) to prevent the script from being processed multiple times if it's included in different parts of the build tree. It’s a bit cleaner than the old if(NOT DEFINED) guard pattern

Comment thread cmake/PatchRPath.cmake
get_filename_component(lib_basename "${lib_path}" NAME)

add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${Patchelf_EXECUTABLE}" --set-rpath "$ORIGIN" "${lib_path}"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this work like this?

		COMMAND ${Patchelf_EXECUTABLE} --set-rpath [=["\$$ORIGIN"]=] ${PROJECT_OUTPUT_DIR}/${rustc_lib_name}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I know that looks wild Tbh I spent a good amout of time figuring out with the linker because both CMake and the shell kept trying to eat dollar sign in $ORIGIN.

I stumbled upon this bracket argument thing it’s basically a raw string that tells CMake to don't remove the $ sign It’s def a bit heavy handed so if there’s a more standard way MetaCall usually handles escaping let me know and I’ll update it

@@ -1,3 +1,3 @@
parallel-compiler = true
[build]
rustflags = ["-C", "link-args=-Wl,-rpath=$ORIGIN"]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this file be added to .gitignore?

@viferga
Copy link
Copy Markdown
Member

viferga commented Apr 15, 2026

@heyitsmohdd one more question, for testing this we should enable rust in the macos ci, right?

@viferga
Copy link
Copy Markdown
Member

viferga commented Apr 15, 2026

I'm running the CI but this will test Linux only, we have to enable it on macos too.

@viferga viferga marked this pull request as draft April 15, 2026 22:32
@viferga
Copy link
Copy Markdown
Member

viferga commented Apr 15, 2026

Once it's tested I will merge it.

@viferga
Copy link
Copy Markdown
Member

viferga commented Apr 17, 2026

@heyitsmohdd the whole linux ci is failing...

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