Skip to content

Whole archive modifier for native libraries is not propagated to final output. #88085

Description

@gcoakes

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

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions