Fix linking two dylibs together when both depend on profiler_builtins

See the comment inside this commit for why.
This commit is contained in:
bjorn3
2026-04-05 20:07:50 +02:00
parent 9602bda1dd
commit 642f348805
6 changed files with 46 additions and 2 deletions
+3 -1
View File
@@ -2972,9 +2972,11 @@ fn add_upstream_rust_crates(
// We must always link crates `compiler_builtins` and `profiler_builtins` statically.
// Even if they were already included into a dylib
// (e.g. `libstd` when `-C prefer-dynamic` is used).
// HACK: `dependency_formats` can report `profiler_builtins` as `NotLinked`.
// See the comment in inject_profiler_runtime for why this is the case.
let linkage = data[cnum];
let link_static_crate = linkage == Linkage::Static
|| linkage == Linkage::IncludedFromDylib
|| (linkage == Linkage::IncludedFromDylib || linkage == Linkage::NotLinked)
&& (crate_info.compiler_builtins == Some(cnum)
|| crate_info.profiler_runtime == Some(cnum));
+8 -1
View File
@@ -1024,12 +1024,19 @@ fn inject_profiler_runtime(&mut self, tcx: TyCtxt<'_>) {
info!("loading profiler");
// HACK: This uses conditional despite actually being unconditional to ensure that
// there is no error emitted when two dylibs independently depend on profiler_builtins.
// This is fine as profiler_builtins is always statically linked into the dylib just
// like compiler_builtins. Unlike compiler_builtins however there is no guaranteed
// common dylib that the duplicate crate check believes the crate to be included in.
// add_upstream_rust_crates has a corresponding check that forces profiler_builtins
// to be statically linked in even when marked as NotLinked.
let name = Symbol::intern(&tcx.sess.opts.unstable_opts.profiler_runtime);
let Some(cnum) = self.resolve_crate(
tcx,
name,
DUMMY_SP,
CrateDepKind::Unconditional,
CrateDepKind::Conditional,
CrateOrigin::Injected,
) else {
return;
@@ -0,0 +1 @@
pub fn something() {}
@@ -0,0 +1 @@
pub fn something_else() {}
@@ -0,0 +1,4 @@
fn main() {
dylib_a::something();
dylib_b::something_else();
}
@@ -0,0 +1,29 @@
// Checks that two dylibs compiled with code coverage enabled can be linked
// together without getting an error about duplicate profiler_builtins.
//@ needs-profiler-runtime
use run_make_support::{dynamic_lib_name, rustc};
fn main() {
rustc()
.crate_name("dylib_a")
.crate_type("dylib")
.arg("-Cinstrument-coverage")
.arg("-Cprefer-dynamic")
.input("dylib_a.rs")
.run();
rustc()
.crate_name("dylib_b")
.crate_type("dylib")
.arg("-Cinstrument-coverage")
.arg("-Cprefer-dynamic")
.input("dylib_b.rs")
.run();
rustc()
.crate_type("bin")
.extern_("dylib_a", dynamic_lib_name("dylib_a"))
.extern_("dylib_b", dynamic_lib_name("dylib_b"))
.input("main.rs")
.run();
}