Description
With the additional of RFC 2951 (tracking: #81490, implementation: #83507), linking modifiers such as +whole-archive
are now possible to use for native libraries. However, +whole-archive
is not propagated to the final output of the build. I've minimally reproduced this issue as best I could here. It can probably be minimized more with raw calls to rustc, but I'm not familiar enough to do so right now.
Essentially, I have a static library which provides constructor and destructor functions which must be included in the final output.
I tried this code:
foo.c
#include <stdio.h>
void __attribute__((constructor)) construct();
void __attribute__((destructor)) destruct();
void construct()
{
printf("Constructor.\n");
}
void destruct()
{
printf("Destructor.\n");
}
build.rs
fn main() {
cc::Build::new()
.file("src/foo.c")
.cargo_metadata(false)
.static_flag(true)
.compile("foo");
println!(
"cargo:rustc-link-search=native={}",
std::env::var("OUT_DIR").unwrap()
);
println!("cargo:rustc-link-lib=static:+whole-archive=foo");
}
lib.rs
pub fn it_linked() {}
main.rs
fn main() {
indirect::it_linked();
println!("Hello, indirect!");
}
I expected to see this happen:
$ RUSTFLAGS="-Z unstable-options" cargo run --bin indirect
Compiling cc v1.0.69
Compiling direct v0.1.0 (/home/gcoakes/Documents/Source/minimal-whole-archive/indirect)
Finished dev [unoptimized + debuginfo] target(s) in 1.73s
Running `target/debug/indirect`
Constructor.
Hello, indirect!
Destructor.
$ nm target/debug/indirect | grep 'construct\|destruct'
0000000000007ab5 T construct
0000000000007acc T destruct
Instead, this happened:
$ RUSTFLAGS="-Z unstable-options" cargo run --bin indirect
Compiling indirect v0.1.0 (/home/gcoakes/Documents/Source/minimal-whole-archive/indirect)
Finished dev [unoptimized + debuginfo] target(s) in 0.68s
Running `target/debug/indirect`
Hello, indirect!
$ nm target/debug/indirect | grep 'construct\|destruct'
Resolution
I've done a bit of code inspection to determine where the linking issue actually is. I think it comes down to the link_upstream
closure in rustc_codegen_ssa::src::back::link::add_upstream_rust_crates::add_static_crate
. It should be adjusted to inspect the crates native libraries and determine if any of them have +whole-archive
. If one or more do, then it should run link_whole_rlib
on the crate's rlib instead of link_rlib
.
Meta
rustc --version --verbose
:
rustc 1.56.0-nightly (8007b506a 2021-08-14)
binary: rustc
commit-hash: 8007b506ac5da629f223b755f5a5391edd5f6d01
commit-date: 2021-08-14
host: x86_64-unknown-linux-gnu
release: 1.56.0-nightly
LLVM version: 12.0.1