Skip to content

Add cc_runtime_linkage setting for static C++ runtime in shared libs#25

Merged
dzbarsky merged 1 commit into
hermeticbuild:mainfrom
walter-zeromatter:wgray/cc-runtime-linkage
Jun 10, 2026
Merged

Add cc_runtime_linkage setting for static C++ runtime in shared libs#25
dzbarsky merged 1 commit into
hermeticbuild:mainfrom
walter-zeromatter:wgray/cc-runtime-linkage

Conversation

@walter-zeromatter

Copy link
Copy Markdown

Motivation

cdylib/dylib targets link the cc toolchain's C++ runtime (libstdc++/libc++ and the unwinder) dynamicallyget_cc_toolchain_runtime_libs calls cc_toolchain.dynamic_runtime_lib() for these crate types. The runtime therefore becomes an external DT_NEEDED on the produced .so.

When shipping a self-contained shared library to a consumer that uses a different C++ stdlib (e.g. a GCC libstdc++ environment consuming a library built with an LLVM/libc++ toolchain), forcing a dynamic libc++/libc++abi/libunwind dependency is undesirable — the consumer would have to ship the producer's C++ runtime.

What this adds

An opt-in way to link the C++ runtime statically into shared libraries, so they carry no external C++ runtime dependency and the unwinder is embedded:

  • //rust/settings:cc_runtime_linkage string flag — dynamic | static, default dynamic (no behavior change for existing users).
  • cc_runtime_linkage attribute on rust_shared_libraryauto | dynamic | static, auto (default) defers to the flag, so individual targets can opt in without flipping the global default.
  • get_cc_toolchain_runtime_libs gains a linkage parameter; when static, it returns cc_toolchain.static_runtime_lib(...) for cdylib/dylib (the same call already used for all non-shared crate types). Both call sites resolve linkage via resolve_cc_runtime_linkage(ctx) (per-target attr overriding the flag).

Non-shared crate types are unchanged.

Effect (with cc_runtime_linkage = "static")

A Rust cdylib built against an LLVM/libc++ toolchain goes from:

NEEDED libc++.so.1, libc++abi.so.1, libunwind.so.1   (+ _Unwind_* UND)

to a self-contained .so: those NEEDED entries gone, _Unwind_* defined in-binary.

@walter-zeromatter walter-zeromatter marked this pull request as ready for review June 10, 2026 19:39
rust_shared_library links the cc toolchain's C++ runtime
(libstdc++/libc++ and the unwinder) dynamically, so it becomes an
external DT_NEEDED on the produced shared library. When shipping a
self-contained .so to a consumer that uses a different C++ stdlib,
that dynamic dependency is undesirable.

Add a `cc_runtime_linkage` attribute on rust_shared_library
(dynamic|static, default dynamic so existing behavior is unchanged).
When static, the C++ runtime is linked via
cc_toolchain.static_runtime_lib so it is embedded in the shared
library and no libstdc++/libc++/libunwind DT_NEEDED is emitted.

get_cc_toolchain_runtime_libs gains a `linkage` parameter resolved
from the attribute. Non-shared crate types are unchanged.
@walter-zeromatter walter-zeromatter force-pushed the wgray/cc-runtime-linkage branch from 9f60d26 to e3b36f3 Compare June 10, 2026 21:45
@dzbarsky dzbarsky merged commit f9dc9d2 into hermeticbuild:main Jun 10, 2026
0 of 3 checks passed
dzbarsky pushed a commit that referenced this pull request Jun 14, 2026
#25)

rust_shared_library links the cc toolchain's C++ runtime
(libstdc++/libc++ and the unwinder) dynamically, so it becomes an
external DT_NEEDED on the produced shared library. When shipping a
self-contained .so to a consumer that uses a different C++ stdlib,
that dynamic dependency is undesirable.

Add a `cc_runtime_linkage` attribute on rust_shared_library
(dynamic|static, default dynamic so existing behavior is unchanged).
When static, the C++ runtime is linked via
cc_toolchain.static_runtime_lib so it is embedded in the shared
library and no libstdc++/libc++/libunwind DT_NEEDED is emitted.

get_cc_toolchain_runtime_libs gains a `linkage` parameter resolved
from the attribute. Non-shared crate types are unchanged.
@ArchangelX360

Copy link
Copy Markdown

@walter-zeromatter Thank you so much for this, I faced the same issue and was working around it with a dirty patch, really appreciate the work you did here 🙏🏼

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.

3 participants