Description
I tried this code:
Within the base crate, the #[divan::bench]
macro is used for benchmarking crate internals. Its generated code translates to something similar to:
#[used]
#[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func,mod_init_funcs")]
#[cfg_attr(target_os = "linux", link_section = ".init_array")]
#[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
static CONSTRUCTOR: extern "C" fn() = constructor;
extern "C" fn constructor() {
// Register benchmark...
}
This crate has a benchmark executable with only:
fn main() {
divan::main();
}
I expected to see this happen: run the add
benchmark and output the results. This runs correctly on Linux and Windows, but not macOS.
Instead, this happened: divan::main()
cannot find the benchmark because the pre-main
constructor function never ran.
In order to make the benchmarks visible to the executable, the base crate needs to have one of its items appear to be used, such as black_box
-ing any item from the crate.
Note that this also happens with code like:
#[used(linker)]
#[link_section = "__DATA,__my_values,regular,no_dead_strip"]
static VALUE: u32 = 42;
This issue occurs even when doing extern crate my_crate
or use my_crate as _
, which is a known workaround for similar issues.
Meta
rustc --version --verbose
:
rustc 1.82.0 (f6e511eec 2024-10-15)
binary: rustc
commit-hash: f6e511eec7342f59a25f7c0534f1dbea00d01b14
commit-date: 2024-10-15
host: aarch64-apple-darwin
release: 1.82.0
LLVM version: 19.1.1