diff --git a/src/commands.rs b/src/commands.rs index 6c4941f7..9de87853 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -18,6 +18,7 @@ pub use self::build::*; pub use self::check::*; pub use self::metadata::*; pub use self::new::*; +use crate::target; fn root_manifest(manifest_path: Option<&Path>, config: &Config) -> Result { match manifest_path { @@ -136,6 +137,7 @@ impl CompileOptions { let spec = Packages::from_flags(self.workspace, self.exclude, self.packages)?; if self.targets.is_empty() { + target::install_wasm32_unknown_unknown()?; self.targets.push("wasm32-unknown-unknown".to_string()); } diff --git a/src/lib.rs b/src/lib.rs index 1524eb94..22c1c0f4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,8 @@ use wit_bindgen_gen_rust_wasm::Opts; use wit_component::ComponentEncoder; use wit_parser::Interface; +mod target; + pub mod commands; const COMPONENT_PATH: &str = "package.metadata.component"; diff --git a/src/target.rs b/src/target.rs new file mode 100644 index 00000000..a227e2f0 --- /dev/null +++ b/src/target.rs @@ -0,0 +1,51 @@ +use anyhow::{bail, Result}; +use std::{env, path::PathBuf, process::{Command, Stdio}}; + +pub fn install_wasm32_unknown_unknown() -> Result<()> { + let sysroot = get_sysroot()?; + if sysroot.join("lib/rustlib/wasm32-unknown-unknown").exists() { + return Ok(()); + } + + if env::var_os("RUSTUP_TOOLCHAIN").is_none() { + bail!( + "failed to find the `wasm32-unknown-unknown` target \ + and `rustup` is not available. If you're using rustup \ + make sure that it's correctly installed; if not, make sure to \ + install the `wasm32-unknown-unknown` target before using this command" + ); + } + + let output = Command::new("rustup") + .arg("target") + .arg("add") + .arg("wasm32-unknown-unknown") + .stderr(Stdio::inherit()) + .stdout(Stdio::inherit()) + .output()?; + + if !output.status.success() { + bail!("failed to install the `wasm32-unknown-unknown` target"); + } + + Ok(()) +} + +fn get_sysroot() -> Result { + let output = Command::new("rustc") + .arg("--print") + .arg("sysroot") + .output()?; + + if !output.status.success() { + bail!( + "failed to execute `rustc --print sysroot`, \ + command exited with error: {}", + String::from_utf8_lossy(&output.stderr) + ); + } + + let sysroot = PathBuf::from(String::from_utf8(output.stdout)?.trim()); + + Ok(sysroot) +}