From f9ad9e1ea179cd3981ad5dddb9e7da994119453b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 20 Aug 2026 11:28:11 -0700 Subject: [PATCH] Include startup crt objects on WASI for more outputs This commit adds the `crt1-reactor.o` object file in the list of pre-link-crt-objects for the `{Dynamic,Static}Dylib` output kinds for WASI targets. These previously were omitted I believe by accident and this means that the conventional `_initialize` function is not present which runs constructor functions, for example. This is additionally needed for the upcoming wasip3 target where this startup object file is more load bearing than it was previously and will become required. --- compiler/rustc_target/src/spec/crt_objects.rs | 16 +++++++++------- .../run-make-support/src/external_deps/rustc.rs | 7 +++++++ tests/run-make/wasm-export-all-symbols/rmake.rs | 5 ++++- .../run-make/wasm-symbols-not-exported/rmake.rs | 2 +- tests/run-make/wasm-unexpected-features/rmake.rs | 1 + 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_target/src/spec/crt_objects.rs b/compiler/rustc_target/src/spec/crt_objects.rs index 2d84e78f25572..39037132ca438 100644 --- a/compiler/rustc_target/src/spec/crt_objects.rs +++ b/compiler/rustc_target/src/spec/crt_objects.rs @@ -7,13 +7,13 @@ //! //! | Pre-link CRT objects | glibc | musl | bionic | mingw | wasi | //! |----------------------|------------------------|------------------------|------------------|-------------------|--------------| -//! | dynamic-nopic-exe | crt1, crti, crtbegin | crt1, crti, crtbegin | crtbegin_dynamic | crt2, crtbegin | crt1 | -//! | dynamic-pic-exe | Scrt1, crti, crtbeginS | Scrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin | crt1 | -//! | static-nopic-exe | crt1, crti, crtbeginT | crt1, crti, crtbegin | crtbegin_static | crt2, crtbegin | crt1 | -//! | static-pic-exe | rcrt1, crti, crtbeginS | rcrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin | crt1 | -//! | dynamic-dylib | crti, crtbeginS | crti, crtbeginS | crtbegin_so | dllcrt2, crtbegin | - | -//! | static-dylib (gcc) | crti, crtbeginT | crti, crtbeginS | crtbegin_so | dllcrt2, crtbegin | - | -//! | static-dylib (clang) | crti, crtbeginT | N/A | crtbegin_static | dllcrt2, crtbegin | - | +//! | dynamic-nopic-exe | crt1, crti, crtbegin | crt1, crti, crtbegin | crtbegin_dynamic | crt2, crtbegin | crt1-command | +//! | dynamic-pic-exe | Scrt1, crti, crtbeginS | Scrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin | crt1-command | +//! | static-nopic-exe | crt1, crti, crtbeginT | crt1, crti, crtbegin | crtbegin_static | crt2, crtbegin | crt1-command | +//! | static-pic-exe | rcrt1, crti, crtbeginS | rcrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin | crt1-command | +//! | dynamic-dylib | crti, crtbeginS | crti, crtbeginS | crtbegin_so | dllcrt2, crtbegin | crt1-reactor | +//! | static-dylib (gcc) | crti, crtbeginT | crti, crtbeginS | crtbegin_so | dllcrt2, crtbegin | crt1-reactor | +//! | static-dylib (clang) | crti, crtbeginT | N/A | crtbegin_static | dllcrt2, crtbegin | ctr1-reactor | //! | wasi-reactor-exe | N/A | N/A | N/A | N/A | crt1-reactor | //! //! | Post-link CRT objects | glibc | musl | bionic | mingw | wasi | @@ -127,6 +127,8 @@ pub(super) fn pre_wasi_self_contained() -> CrtObjects { (LinkOutputKind::StaticNoPicExe, &["crt1-command.o"]), (LinkOutputKind::StaticPicExe, &["crt1-command.o"]), (LinkOutputKind::WasiReactorExe, &["crt1-reactor.o"]), + (LinkOutputKind::DynamicDylib, &["crt1-reactor.o"]), + (LinkOutputKind::StaticDylib, &["crt1-reactor.o"]), ]) } diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index b5d9593ae9a6a..8168e0ab07922 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -397,6 +397,13 @@ impl Rustc { self } + /// Specify `-C link-self-contained={y,n}`. + pub fn link_self_contained(&mut self, enabled: bool) -> &mut Self { + let enabled = if enabled { "y" } else { "n" }; + self.cmd.arg(format!("-Clink-self-contained={enabled}")); + self + } + pub fn split_dwarf_out_dir(&mut self, out_dir: Option<&str>) -> &mut Self { if let Some(out_dir) = out_dir { self.cmd.arg(format!("-Zsplit-dwarf-out-dir={out_dir}")); diff --git a/tests/run-make/wasm-export-all-symbols/rmake.rs b/tests/run-make/wasm-export-all-symbols/rmake.rs index 4148cc29ec2f8..58abfb996461e 100644 --- a/tests/run-make/wasm-export-all-symbols/rmake.rs +++ b/tests/run-make/wasm-export-all-symbols/rmake.rs @@ -19,7 +19,10 @@ fn test(args: &[&str]) { rustc().input("foo.rs").target("wasm32-wasip1").args(args).run(); rustc().input("main.rs").target("wasm32-wasip1").args(args).run(); - verify_exports(Path::new("foo.wasm"), &[("foo", Func), ("FOO", Global), ("memory", Memory)]); + verify_exports( + Path::new("foo.wasm"), + &[("foo", Func), ("FOO", Global), ("memory", Memory), ("_initialize", Func)], + ); verify_exports( Path::new("main.wasm"), &[ diff --git a/tests/run-make/wasm-symbols-not-exported/rmake.rs b/tests/run-make/wasm-symbols-not-exported/rmake.rs index 0b9c9c6822ea1..62da63db26dbf 100644 --- a/tests/run-make/wasm-symbols-not-exported/rmake.rs +++ b/tests/run-make/wasm-symbols-not-exported/rmake.rs @@ -28,7 +28,7 @@ fn verify_symbols(path: &Path) { if e.kind != wasmparser::ExternalKind::Func { continue; } - if e.name == "foo" { + if e.name == "foo" || e.name == "_initialize" { continue; } panic!("unexpected export {e:?}"); diff --git a/tests/run-make/wasm-unexpected-features/rmake.rs b/tests/run-make/wasm-unexpected-features/rmake.rs index 44c6f3522267e..ffff64f1a876f 100644 --- a/tests/run-make/wasm-unexpected-features/rmake.rs +++ b/tests/run-make/wasm-unexpected-features/rmake.rs @@ -15,6 +15,7 @@ fn main() { .linker_plugin_lto("on") .link_arg("--import-memory") .extern_("minicore", path("libminicore.rlib")) + .link_self_contained(false) .run(); verify_features(Path::new("foo.wasm")); }