From 9985205307d0b0f62475a3b288590bbcbe5e76c4 Mon Sep 17 00:00:00 2001 From: Arshia Ghafoori Date: Wed, 15 Jul 2026 15:20:11 +0000 Subject: [PATCH] Force wasixcc to legacy EH to match the Rust toolchain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Rust toolchain builds in the legacy exception-handling configuration (its sysroot is the legacy-EH wasix-libc build), but wasixcc defaults to exnref, so the auto-configured C/C++ side of a build ended up in a different EH configuration than the Rust side. Set WASIXCC_WASM_EXCEPTIONS=legacy alongside the tool variables — overriding any value from the environment, since a mismatched configuration must not reach the build. wasm-opt still translates the final module to exnref in post-processing. The -dl target's WASIXCC_WASM_EXCEPTIONS=1 (exnref) default is gone for the same reason; with legacy EH, WASIXCC_PIC=1 selects sysroot-ehpic, matching the Rust dl target's sysroot32-ehpic. Verified with C setjmp/longjmp linked through the cc crate: the object now compiles as legacy EH (1 legacy try, 0 try_table pre-wasm-opt), translate-to-exnref unifies the module (1 try_table post), and the binary round-trips a longjmp under wasmer. Co-Authored-By: Claude Fable 5 --- src/lib.rs | 32 ++++++++++++++++++-------------- tests/tests/main.rs | 40 ++++++++++++++++++++++++++++------------ 2 files changed, 46 insertions(+), 26 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e8cf50e..5f14785 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -282,20 +282,24 @@ fn rmain(config: &mut Config) -> Result<()> { } } - // For the -dl target, set wasixcc-specific environment variables - if target.ends_with("-dl") { - // Enable position-independent code for dynamic linking - if std::env::var("WASIXCC_PIC").is_err() { - // SAFETY: not safe in multi-threaded environment - unsafe { env::set_var("WASIXCC_PIC", "1") }; - config.verbose(|| config.info("Set WASIXCC_PIC=1 for -dl target")); - } - // Enable WASM exceptions for better performance and C++ exception support - if std::env::var("WASIXCC_WASM_EXCEPTIONS").is_err() { - // SAFETY: not safe in multi-threaded environment - unsafe { env::set_var("WASIXCC_WASM_EXCEPTIONS", "1") }; - config.verbose(|| config.info("Set WASIXCC_WASM_EXCEPTIONS=1 for -dl target")); - } + // The Rust toolchain builds in the legacy exception-handling + // configuration (its sysroot is the legacy-EH wasix-libc build), while + // wasixcc defaults to exnref. Force wasixcc to legacy — overriding any + // value from the environment — so C/C++ objects match the Rust side of + // the binary; wasm-opt translates the whole module to exnref afterwards. + if which::which("wasixcc").is_ok() { + // SAFETY: not safe in multi-threaded environment + unsafe { env::set_var("WASIXCC_WASM_EXCEPTIONS", "legacy") }; + config.verbose(|| config.info("Set WASIXCC_WASM_EXCEPTIONS=legacy")); + } + + // For the -dl target, enable position-independent code for dynamic + // linking (with legacy EH above, this selects wasixcc's sysroot-ehpic — + // the same configuration the Rust toolchain's dl sysroot uses). + if target.ends_with("-dl") && std::env::var("WASIXCC_PIC").is_err() { + // SAFETY: not safe in multi-threaded environment + unsafe { env::set_var("WASIXCC_PIC", "1") }; + config.verbose(|| config.info("Set WASIXCC_PIC=1 for -dl target")); } // Make sure the project resolves crates through the WASIX overlay diff --git a/tests/tests/main.rs b/tests/tests/main.rs index a40c411..cfc4eed 100644 --- a/tests/tests/main.rs +++ b/tests/tests/main.rs @@ -1247,11 +1247,11 @@ fn wasixcc_pic_and_exceptions_for_dl_target() -> Result<()> { "build.rs", r#" fn main() { - if let Ok(pic) = std::env::var("WASIXCC_PIC") { - println!("cargo:warning=WASIXCC_PIC is set to: {}", pic); - } - if let Ok(exceptions) = std::env::var("WASIXCC_WASM_EXCEPTIONS") { - println!("cargo:warning=WASIXCC_WASM_EXCEPTIONS is set to: {}", exceptions); + for var in ["WASIXCC_PIC", "WASIXCC_WASM_EXCEPTIONS"] { + println!("cargo:rerun-if-env-changed={}", var); + if let Ok(v) = std::env::var(var) { + println!("cargo:warning={} is set to: {}", var, v); + } } } "#, @@ -1262,7 +1262,7 @@ fn wasixcc_pic_and_exceptions_for_dl_target() -> Result<()> { [package] name = "foo" version = '1.0.0' - + [package.metadata] dl = true "#, @@ -1272,17 +1272,33 @@ fn wasixcc_pic_and_exceptions_for_dl_target() -> Result<()> { let output = p.cargo_wasix("build").assert().success(); let stderr = String::from_utf8_lossy(&output.get_output().stderr); - // For -dl target, WASIXCC_PIC and WASIXCC_WASM_EXCEPTIONS should be set + // For -dl target, WASIXCC_PIC should be set assert!( stderr.contains("WASIXCC_PIC is set to: 1"), "Expected WASIXCC_PIC=1 for -dl target, stderr:\n{}", stderr ); - assert!( - stderr.contains("WASIXCC_WASM_EXCEPTIONS is set to: 1"), - "Expected WASIXCC_WASM_EXCEPTIONS=1 for -dl target, stderr:\n{}", - stderr - ); + // The Rust toolchain builds in the legacy EH configuration, so wasixcc + // must too (its own default is exnref). + if which::which("wasixcc").is_ok() { + assert!( + stderr.contains("WASIXCC_WASM_EXCEPTIONS is set to: legacy"), + "Expected WASIXCC_WASM_EXCEPTIONS=legacy, stderr:\n{}", + stderr + ); + + // Even a value from the environment is overridden: mismatched EH + // configurations must not reach the build. + let mut cmd = p.cargo_wasix("build"); + cmd.env("WASIXCC_WASM_EXCEPTIONS", "exnref"); + let output = cmd.assert().success(); + let stderr = String::from_utf8_lossy(&output.get_output().stderr); + assert!( + stderr.contains("WASIXCC_WASM_EXCEPTIONS is set to: legacy"), + "Expected the exnref value from the environment to be overridden, stderr:\n{}", + stderr + ); + } Ok(()) }