From 4c50674b0f32bf8d97578e2b4833c37fd37c74ad Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sun, 18 Aug 2024 22:45:34 +0000 Subject: [PATCH 1/2] Test wholearchive on rust staticlib --- tests/run-make/msvc-wholearchive/c.c | 1 + tests/run-make/msvc-wholearchive/dll.def | 4 +++ tests/run-make/msvc-wholearchive/rmake.rs | 41 ++++++++++++++++++++++ tests/run-make/msvc-wholearchive/static.rs | 9 +++++ 4 files changed, 55 insertions(+) create mode 100644 tests/run-make/msvc-wholearchive/c.c create mode 100644 tests/run-make/msvc-wholearchive/dll.def create mode 100644 tests/run-make/msvc-wholearchive/rmake.rs create mode 100644 tests/run-make/msvc-wholearchive/static.rs diff --git a/tests/run-make/msvc-wholearchive/c.c b/tests/run-make/msvc-wholearchive/c.c new file mode 100644 index 0000000000000..d6847845c6846 --- /dev/null +++ b/tests/run-make/msvc-wholearchive/c.c @@ -0,0 +1 @@ +// This page is intentionally left blank diff --git a/tests/run-make/msvc-wholearchive/dll.def b/tests/run-make/msvc-wholearchive/dll.def new file mode 100644 index 0000000000000..d55819e0d5e9f --- /dev/null +++ b/tests/run-make/msvc-wholearchive/dll.def @@ -0,0 +1,4 @@ +LIBRARY dll +EXPORTS + hello + number diff --git a/tests/run-make/msvc-wholearchive/rmake.rs b/tests/run-make/msvc-wholearchive/rmake.rs new file mode 100644 index 0000000000000..df4df1fa9501f --- /dev/null +++ b/tests/run-make/msvc-wholearchive/rmake.rs @@ -0,0 +1,41 @@ +//@ only-msvc +// Reason: this is testing the MSVC linker + +// This is a regression test for #129020 +// It ensures we can link a rust staticlib into DLL using the MSVC linker + +use std::path::Path; + +use run_make_support::{cc, env_var, extra_c_flags, rustc}; + +fn main() { + // FIXME: Make this test either work with or ignore LLVM. + if false { + return; + } + // Build the staticlib + rustc().crate_type("staticlib").input("static.rs").output("static.lib").run(); + // Create an empty obj file (using the C compiler) + // Then use it to link in the staticlib using `/WHOLEARCHIVE` and produce a DLL. + // We test for `cl.exe` to ensure we're using MSVC's tools and not the LLVM equivalents. + + if env_var("CC").ends_with("cl.exe") { + cc().input("c.c") + .args([ + "-MT", + "-link", + "-WHOLEARCHIVE:./static.lib", + "-dll", + "-def:dll.def", + "-out:dll.dll", + ]) + .args(extra_c_flags()) + .run(); + } + + // As a sanity check, make sure it works without /WHOLEARCHIVE + cc().input("c.c") + .args(["-MT", "-link", "./static.lib", "-dll", "-def:dll.def", "-out:dll2.dll"]) + .args(extra_c_flags()) + .run(); +} diff --git a/tests/run-make/msvc-wholearchive/static.rs b/tests/run-make/msvc-wholearchive/static.rs new file mode 100644 index 0000000000000..881c88565737a --- /dev/null +++ b/tests/run-make/msvc-wholearchive/static.rs @@ -0,0 +1,9 @@ +#[no_mangle] +pub extern "C" fn hello() { + println!("Hello world!"); +} + +#[no_mangle] +pub extern "C" fn number() -> u32 { + 42 +} From f64ecf12c7ec8d4e57507e33465e553d24467066 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sun, 18 Aug 2024 22:45:46 +0000 Subject: [PATCH 2/2] WIP --- Cargo.lock | 5 ++--- compiler/rustc_codegen_ssa/Cargo.toml | 14 ++++++++++++-- compiler/rustc_codegen_ssa/src/back/archive.rs | 6 +++++- src/tools/tidy/src/extdeps.rs | 1 + 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3ad21b0abf920..cdbe7856ba79a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -205,9 +205,8 @@ dependencies = [ [[package]] name = "ar_archive_writer" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de11a9d32db3327f981143bdf699ade4d637c6887b13b97e6e91a9154666963c" +version = "0.3.3" +source = "git+https://github.com/ChrisDenton/ar_archive_writer.git?branch=rename2#a5b424a6ef9d6416b299ac27c2dba224e2470253" dependencies = [ "object 0.36.2", ] diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 0af34a1b9fa62..f711c4533b645 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -ar_archive_writer = "0.4.0" +ar_archive_writer = { git = 'https://github.com/ChrisDenton/ar_archive_writer.git', branch = "rename2" } arrayvec = { version = "0.7", default-features = false } bitflags = "2.4.1" cc = "1.0.90" @@ -52,7 +52,17 @@ libc = "0.2.50" [dependencies.object] version = "0.36.2" default-features = false -features = ["read_core", "elf", "macho", "pe", "xcoff", "unaligned", "archive", "write", "wasm"] +features = [ + "read_core", + "elf", + "macho", + "pe", + "xcoff", + "unaligned", + "archive", + "write", + "wasm", +] [target.'cfg(windows)'.dependencies.windows] version = "0.52.0" diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 38a440a707a23..e838c82d569f9 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -108,7 +108,11 @@ pub trait ArchiveBuilderBuilder { &exports, machine, !sess.target.is_like_msvc, - /*comdat=*/ false, + // Tell the import library writer to make `.idata$3` a COMDAT section. + // This prevents duplicate symbol errors when using /WHOLEARCHIVE + // to link a staticlib with the MSVC linker. + // See #129020 + true, ) { sess.dcx() .emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }); diff --git a/src/tools/tidy/src/extdeps.rs b/src/tools/tidy/src/extdeps.rs index 55f937aeacf50..44a27cc95316f 100644 --- a/src/tools/tidy/src/extdeps.rs +++ b/src/tools/tidy/src/extdeps.rs @@ -8,6 +8,7 @@ const ALLOWED_SOURCES: &[&str] = &[ r#""registry+https://github.com/rust-lang/crates.io-index""#, // This is `rust_team_data` used by `site` in src/tools/rustc-perf, r#""git+https://github.com/rust-lang/team#a5260e76d3aa894c64c56e6ddc8545b9a98043ec""#, + r#""git+https://github.com/ChrisDenton/ar_archive_writer.git?branch=rename2#a5b424a6ef9d6416b299ac27c2dba224e2470253""#, ]; /// Checks for external package sources. `root` is the path to the directory that contains the