From 019091a8fb422e1b22083d8349618d1f8ed0cd14 Mon Sep 17 00:00:00 2001 From: Audrey Tang Date: Wed, 25 Feb 2026 18:37:14 +0800 Subject: [PATCH] Add wasm64-unknown-unknown target support - Parameterize target triple in cargo_build_wasm() and cargo_build_wasm_tests() - Extract --target from extra_options in build and test commands - Add --enable-memory64 to wasm-opt args for wasm64 targets - Construct CARGO_TARGET_*_RUNNER env var dynamically from target triple - Pass target triple through to cargo_test_wasm() Co-Authored-By: Claude Opus 4.6 --- src/build/mod.rs | 14 ++++--- src/command/build.rs | 11 +++++- src/command/test.rs | 94 ++++++++++++++++++++++++++++++++++---------- src/manifest/mod.rs | 2 +- src/test/mod.rs | 3 +- 5 files changed, 94 insertions(+), 30 deletions(-) diff --git a/src/build/mod.rs b/src/build/mod.rs index cc0170d52..c8af150e8 100644 --- a/src/build/mod.rs +++ b/src/build/mod.rs @@ -79,6 +79,7 @@ pub fn cargo_build_wasm( path: &Path, profile: BuildProfile, extra_options: &[String], + target_triple: &str, ) -> Result { let msg = format!("{}Compiling to Wasm...", emoji::CYCLONE); PBAR.info(&msg); @@ -111,9 +112,7 @@ pub fn cargo_build_wasm( } } - // If user has specified a custom --target in Cargo options, we shouldn't override it. - // Otherwise, default to wasm32-unknown-unknown. - cmd.env("CARGO_BUILD_TARGET", "wasm32-unknown-unknown"); + cmd.env("CARGO_BUILD_TARGET", target_triple); // The `cargo` command is executed inside the directory at `path`, so relative paths set via extra options won't work. // To remedy the situation, all detected paths are converted to absolute paths. @@ -192,7 +191,12 @@ pub fn cargo_build_wasm( /// * `path`: Path to the crate directory to build tests. /// * `debug`: Whether to build tests in `debug` mode. /// * `extra_options`: Additional parameters to pass to `cargo` when building tests. -pub fn cargo_build_wasm_tests(path: &Path, debug: bool, extra_options: &[String]) -> Result<()> { +pub fn cargo_build_wasm_tests( + path: &Path, + debug: bool, + extra_options: &[String], + target_triple: &str, +) -> Result<()> { let mut cmd = Command::new("cargo"); cmd.current_dir(path).arg("build").arg("--tests"); @@ -205,7 +209,7 @@ pub fn cargo_build_wasm_tests(path: &Path, debug: bool, extra_options: &[String] cmd.arg("--release"); } - cmd.env("CARGO_BUILD_TARGET", "wasm32-unknown-unknown"); + cmd.env("CARGO_BUILD_TARGET", target_triple); cmd.args(extra_options); diff --git a/src/command/build.rs b/src/command/build.rs index 7310b1335..e74a9b938 100644 --- a/src/command/build.rs +++ b/src/command/build.rs @@ -387,8 +387,12 @@ impl Build { fn step_build_wasm(&mut self) -> Result<()> { info!("Building wasm..."); - let wasm_path = - build::cargo_build_wasm(&self.crate_path, self.profile.clone(), &self.extra_options)?; + let wasm_path = build::cargo_build_wasm( + &self.crate_path, + self.profile.clone(), + &self.extra_options, + &self.target_triple, + )?; info!("wasm built at {wasm_path:#?}."); self.wasm_path = Some(wasm_path); Ok(()) @@ -475,6 +479,9 @@ impl Build { if self.reference_types { args.push("--enable-reference-types".into()); } + if self.target_triple.starts_with("wasm64") { + args.push("--enable-memory64".into()); + } info!("executing wasm-opt with {:?}", args); wasm_opt::run( &self.cache, diff --git a/src/command/test.rs b/src/command/test.rs index e60291d29..1ad78a20c 100644 --- a/src/command/test.rs +++ b/src/command/test.rs @@ -99,6 +99,7 @@ pub struct Test { release: bool, test_runner_path: Option, extra_options: Vec, + target_triple: String, } type TestStep = fn(&mut Test) -> Result<()>; @@ -138,6 +139,17 @@ impl Test { let crate_data = manifest::CrateData::new(&crate_path, None)?; let any_browser = chrome || firefox || safari; + let target_triple = { + let mut iter = extra_options.iter(); + if iter.by_ref().any(|option| option == "--target") { + iter.next().map(|s| s.as_str()) + } else { + None + } + .unwrap_or("wasm32-unknown-unknown") + .to_owned() + }; + if !node && !any_browser { bail!("Must specify at least one of `--node`, `--chrome`, `--firefox`, or `--safari`") } @@ -164,6 +176,7 @@ impl Test { headless, release, test_runner_path: None, + target_triple, extra_options, }) } @@ -251,7 +264,7 @@ impl Test { fn step_check_for_wasm_target(&mut self) -> Result<()> { info!("Adding wasm-target..."); - build::wasm_target::check_for_wasm_target("wasm32-unknown-unknown")?; + build::wasm_target::check_for_wasm_target(&self.target_triple)?; info!("Adding wasm-target was successful."); Ok(()) } @@ -267,7 +280,12 @@ impl Test { } else { &self.extra_options }; - build::cargo_build_wasm_tests(&self.crate_path, !self.release, extra_options)?; + build::cargo_build_wasm_tests( + &self.crate_path, + !self.release, + extra_options, + &self.target_triple, + )?; info!("Finished compiling tests to wasm."); Ok(()) @@ -311,17 +329,26 @@ impl Test { fn step_test_node(&mut self) -> Result<()> { assert!(self.node); info!("Running tests in node..."); + let runner_env = format!( + "CARGO_TARGET_{}_RUNNER", + self.target_triple.replace('-', "_").to_uppercase() + ); + let runner_path = self + .test_runner_path + .as_ref() + .unwrap() + .to_str() + .unwrap() + .to_string(); test::cargo_test_wasm( &self.crate_path, self.release, vec![ - ( - "CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER", - &**self.test_runner_path.as_ref().unwrap(), - ), - ("WASM_BINDGEN_TEST_ONLY_NODE", "1".as_ref()), + (runner_env, runner_path), + ("WASM_BINDGEN_TEST_ONLY_NODE".to_string(), "1".to_string()), ], &self.extra_options, + &self.target_triple, )?; info!("Finished running tests in node."); Ok(()) @@ -339,16 +366,21 @@ impl Test { fn step_test_chrome(&mut self) -> Result<()> { let chromedriver = self.chromedriver.as_ref().unwrap().display().to_string(); - let chromedriver = chromedriver.as_str(); info!( "Running tests in Chrome with chromedriver at {}", chromedriver ); let mut envs = self.webdriver_env(); - envs.push(("CHROMEDRIVER", chromedriver)); + envs.push(("CHROMEDRIVER".to_string(), chromedriver)); - test::cargo_test_wasm(&self.crate_path, self.release, envs, &self.extra_options)?; + test::cargo_test_wasm( + &self.crate_path, + self.release, + envs, + &self.extra_options, + &self.target_triple, + )?; Ok(()) } @@ -364,16 +396,21 @@ impl Test { fn step_test_firefox(&mut self) -> Result<()> { let geckodriver = self.geckodriver.as_ref().unwrap().display().to_string(); - let geckodriver = geckodriver.as_str(); info!( "Running tests in Firefox with geckodriver at {}", geckodriver ); let mut envs = self.webdriver_env(); - envs.push(("GECKODRIVER", geckodriver)); + envs.push(("GECKODRIVER".to_string(), geckodriver)); - test::cargo_test_wasm(&self.crate_path, self.release, envs, &self.extra_options)?; + test::cargo_test_wasm( + &self.crate_path, + self.release, + envs, + &self.extra_options, + &self.target_triple, + )?; Ok(()) } @@ -386,28 +423,43 @@ impl Test { fn step_test_safari(&mut self) -> Result<()> { let safaridriver = self.safaridriver.as_ref().unwrap().display().to_string(); - let safaridriver = safaridriver.as_str(); info!( "Running tests in Safari with safaridriver at {}", safaridriver ); let mut envs = self.webdriver_env(); - envs.push(("SAFARIDRIVER", safaridriver)); + envs.push(("SAFARIDRIVER".to_string(), safaridriver)); - test::cargo_test_wasm(&self.crate_path, self.release, envs, &self.extra_options)?; + test::cargo_test_wasm( + &self.crate_path, + self.release, + envs, + &self.extra_options, + &self.target_triple, + )?; Ok(()) } - fn webdriver_env(&self) -> Vec<(&'static str, &str)> { - let test_runner = self.test_runner_path.as_ref().unwrap().to_str().unwrap(); + fn webdriver_env(&self) -> Vec<(String, String)> { + let test_runner = self + .test_runner_path + .as_ref() + .unwrap() + .to_str() + .unwrap() + .to_string(); info!("Using wasm-bindgen test runner at {}", test_runner); + let runner_env = format!( + "CARGO_TARGET_{}_RUNNER", + self.target_triple.replace('-', "_").to_uppercase() + ); let mut envs = vec![ - ("CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER", test_runner), - ("WASM_BINDGEN_TEST_ONLY_WEB", "1"), + (runner_env, test_runner), + ("WASM_BINDGEN_TEST_ONLY_WEB".to_string(), "1".to_string()), ]; if !self.headless { - envs.push(("NO_HEADLESS", "1")); + envs.push(("NO_HEADLESS".to_string(), "1".to_string())); } envs } diff --git a/src/manifest/mod.rs b/src/manifest/mod.rs index 9720ee4c9..953962a7a 100644 --- a/src/manifest/mod.rs +++ b/src/manifest/mod.rs @@ -557,7 +557,7 @@ impl CrateData { return Ok(()); } bail!( - "crate-type must be cdylib to compile to wasm32-unknown-unknown. Add the following to your \ + "crate-type must be cdylib to compile to WebAssembly. Add the following to your \ Cargo.toml file:\n\n\ [lib]\n\ crate-type = [\"cdylib\", \"rlib\"]" diff --git a/src/test/mod.rs b/src/test/mod.rs index 1fbe920da..db7a99b47 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -16,6 +16,7 @@ pub fn cargo_test_wasm( release: bool, envs: I, extra_options: &[String], + target_triple: &str, ) -> Result<()> where I: IntoIterator, @@ -35,7 +36,7 @@ where cmd.arg("--release"); } - cmd.arg("--target").arg("wasm32-unknown-unknown"); + cmd.arg("--target").arg(target_triple); cmd.args(extra_options);