rules_rust icon indicating copy to clipboard operation
rules_rust copied to clipboard

`alwayslink`ing a rust_library in a cc_binary

Open FaBrand opened this issue 3 months ago • 1 comments

Issue

When building a rust_library that contains unreferenced symbols that is a link dependency of a cc_binary

e.g. lowlevel CPU startup code that get's located into a defined address via the section.

To ensure that the symbols get linked the alwayslink attribut of the library gets set to True

Code Example
load("@rules_rust//rust:defs.bzl", "rust_library")

rust_library(
    name = "startup_code",
    srcs = glob(["rust/src/**/*.rs"]),
    deps = ["@crates//:vcell"],
    alwayslink = True,
)


cc_binary(
    name = "main",
    deps = [
      ":startup_code",
    ],
)
# rust/src/startup.rs
#[no_mangle]
#[link_section = ".cpu_entrypoint"]
pub fn _start() -> ! {
    // Startup code
}

#[link_section = ".cpu_entrypoint"]
#[no_mangle]
pub static __ENTRY_POINT: fn() -> ! = _start;

The error

ld.lld failed: error executing CppLink command (from target //:main)
ld.lld: error: bazel-out/platform-dbg/bin/libstartup_code-2667693308.a(lib.rmeta): not an ELF file

I assume that the archiver puts the rmeta file into the archive as well.

There are also warnings <other-archive>.a: archive member 'lib.rmeta' is neither ET_REL nor LLVM bitcode that hint at this

However with alwayslink we enforce to include the complete archive and the linker failes to include the rmeta file.

I tried my way through the code base. I saw the tests for alwayslink but only in combination with rust_binary.

FaBrand avatar Nov 07 '25 16:11 FaBrand

I found a similar issue in the llvm-project from wasm: https://github.com/llvm/llvm-project/issues/55786

Here also the --whole-archive is passed, leading to the same error

FaBrand avatar Nov 18 '25 15:11 FaBrand