From bfa8c3badc8b49402473b79d6df0d31ccb2efc5a Mon Sep 17 00:00:00 2001 From: Brooks Townsend Date: Fri, 10 Oct 2025 09:39:49 -0400 Subject: [PATCH 1/2] feat(build): support additional build toolchain args Signed-off-by: Brooks Townsend --- crates/wash/src/cli/component_build.rs | 49 ++++++++++++++++++++++---- crates/wash/src/cli/plugin.rs | 6 ++-- crates/wash/src/component_build.rs | 3 ++ 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/crates/wash/src/cli/component_build.rs b/crates/wash/src/cli/component_build.rs index f8292b9b..7a73eab7 100644 --- a/crates/wash/src/cli/component_build.rs +++ b/crates/wash/src/cli/component_build.rs @@ -41,6 +41,10 @@ pub struct ComponentBuildCommand { /// Skip fetching WIT dependencies, useful for offline builds #[clap(long = "skip-fetch")] skip_fetch: bool, + + /// The arguments to pass to the native build tool (cargo, tinygo, npm, etc.) + #[clap(name = "arg", trailing_var_arg = true, allow_hyphen_values = true)] + pub args: Vec, } impl CliCommand for ComponentBuildCommand { @@ -57,6 +61,16 @@ impl CliCommand for ComponentBuildCommand { ..Default::default() }) } + if let Some(build) = config.build.as_mut() { + if !self.args.is_empty() { + build.additional_args = self.args.clone(); + } + } else { + config.build = Some(crate::component_build::BuildConfig { + additional_args: self.args.clone(), + ..Default::default() + }); + } let result = build_component(&self.project_path, ctx, &config).await?; Ok(CommandOutput::ok( @@ -542,8 +556,15 @@ impl ComponentBuilder { // Build cargo command arguments let mut cargo_args = vec!["build".to_string()]; + let release_mode = rust_config.release + || config + .build + .as_ref() + .map(|b| b.additional_args.contains(&"--release".to_string())) + .unwrap_or(false); + // Apply release mode if configured - if rust_config.release { + if release_mode { cargo_args.push("--release".to_string()); } @@ -576,6 +597,14 @@ impl ComponentBuilder { cargo_args.push(flag.clone()); } + if let Some(build_config) = &config.build { + for arg in &build_config.additional_args { + if arg != "--release" { + cargo_args.push(arg.clone()); + } + } + } + debug!(cargo_args = ?cargo_args, "running cargo with args"); // Change to project directory and run cargo build @@ -619,11 +648,7 @@ impl ComponentBuilder { } // Find the generated wasm file - let build_type = if rust_config.release { - "release" - } else { - "debug" - }; + let build_type = if release_mode { "release" } else { "debug" }; let target_dir = self .project_path .join(format!("target/{}/{}", rust_config.target, build_type)); @@ -791,6 +816,12 @@ impl ComponentBuilder { tinygo_args.push(flag.to_string()); } + if let Some(build_config) = &config.build { + for arg in &build_config.additional_args { + tinygo_args.push(arg.clone()); + } + } + // Add source directory tinygo_args.push(".".to_string()); @@ -958,6 +989,12 @@ impl ComponentBuilder { build_args.push(flag.clone()); } + if let Some(build_config) = &config.build { + for arg in &build_config.additional_args { + build_args.push(arg.clone()); + } + } + debug!(package_manager = %package_manager, build_args = ?build_args, "running build command"); // Run package manager build command diff --git a/crates/wash/src/cli/plugin.rs b/crates/wash/src/cli/plugin.rs index 311dd103..52436c3b 100644 --- a/crates/wash/src/cli/plugin.rs +++ b/crates/wash/src/cli/plugin.rs @@ -196,7 +196,7 @@ pub struct TestCommand { name = "arg", conflicts_with = "type", trailing_var_arg = true, - // TODO: --help won't get collected into this args + allow_hyphen_values = true )] pub args: Vec, } @@ -383,7 +383,7 @@ impl TestCommand { ) => { let _ = e.print(); - return Ok(CommandOutput::error(e.to_string(), None)); + return Ok(CommandOutput::error("", None)); } Err(e) => anyhow::bail!("Failed to parse command arguments: {}", e), }; @@ -394,7 +394,7 @@ impl TestCommand { plugin_component: Some(plugin), }; - output.push_str(component_plugin_command.handle(ctx).await?.message.as_str()); + output = component_plugin_command.handle(ctx).await?.message; } Ok(CommandOutput::ok( diff --git a/crates/wash/src/component_build.rs b/crates/wash/src/component_build.rs index 867d34df..458b2df6 100644 --- a/crates/wash/src/component_build.rs +++ b/crates/wash/src/component_build.rs @@ -23,6 +23,9 @@ pub struct BuildConfig { /// Expected path to the built Wasm component artifact #[serde(skip_serializing_if = "Option::is_none")] pub component_path: Option, + + #[serde(skip_serializing_if = "Vec::is_empty", default)] + pub additional_args: Vec, } /// Types of projects that can be built From 18a0719ee9b04bad651ffe0669c5876a9ca6f6ad Mon Sep 17 00:00:00 2001 From: Bailey Hayes Date: Sat, 8 Nov 2025 14:15:59 -0500 Subject: [PATCH 2/2] fix: unit test failing Signed-off-by: Bailey Hayes --- Cargo.lock | 4 ++-- crates/wash/src/cli/component_build.rs | 19 ++++++++++--------- crates/wash/src/cli/plugin.rs | 2 +- crates/wash/src/component_build.rs | 1 + 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d8d448c4..1286fc24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5969,9 +5969,9 @@ checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-normalization" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" dependencies = [ "tinyvec", ] diff --git a/crates/wash/src/cli/component_build.rs b/crates/wash/src/cli/component_build.rs index 7a73eab7..6611dd86 100644 --- a/crates/wash/src/cli/component_build.rs +++ b/crates/wash/src/cli/component_build.rs @@ -42,7 +42,8 @@ pub struct ComponentBuildCommand { #[clap(long = "skip-fetch")] skip_fetch: bool, - /// The arguments to pass to the native build tool (cargo, tinygo, npm, etc.) + /// Additional arguments to pass to the native build tool after '--'. + /// Example: wash build -- --release --features extra #[clap(name = "arg", trailing_var_arg = true, allow_hyphen_values = true)] pub args: Vec, } @@ -61,15 +62,15 @@ impl CliCommand for ComponentBuildCommand { ..Default::default() }) } - if let Some(build) = config.build.as_mut() { - if !self.args.is_empty() { + if !self.args.is_empty() { + if let Some(build) = config.build.as_mut() { build.additional_args = self.args.clone(); + } else { + config.build = Some(crate::component_build::BuildConfig { + additional_args: self.args.clone(), + ..Default::default() + }); } - } else { - config.build = Some(crate::component_build::BuildConfig { - additional_args: self.args.clone(), - ..Default::default() - }); } let result = build_component(&self.project_path, ctx, &config).await?; @@ -560,7 +561,7 @@ impl ComponentBuilder { || config .build .as_ref() - .map(|b| b.additional_args.contains(&"--release".to_string())) + .map(|b| b.additional_args.iter().any(|arg| arg == "--release")) .unwrap_or(false); // Apply release mode if configured diff --git a/crates/wash/src/cli/plugin.rs b/crates/wash/src/cli/plugin.rs index 52436c3b..52916f9b 100644 --- a/crates/wash/src/cli/plugin.rs +++ b/crates/wash/src/cli/plugin.rs @@ -383,7 +383,7 @@ impl TestCommand { ) => { let _ = e.print(); - return Ok(CommandOutput::error("", None)); + return Ok(CommandOutput::error(e.to_string(), None)); } Err(e) => anyhow::bail!("Failed to parse command arguments: {}", e), }; diff --git a/crates/wash/src/component_build.rs b/crates/wash/src/component_build.rs index 458b2df6..2e54e833 100644 --- a/crates/wash/src/component_build.rs +++ b/crates/wash/src/component_build.rs @@ -24,6 +24,7 @@ pub struct BuildConfig { #[serde(skip_serializing_if = "Option::is_none")] pub component_path: Option, + /// Additional arguments to pass to the build toolchain (cargo, tinygo, npm) #[serde(skip_serializing_if = "Vec::is_empty", default)] pub additional_args: Vec, }