1use crate::child;
4use crate::command::build::BuildProfile;
5use crate::emoji;
6use crate::manifest::Crate;
7use crate::PBAR;
8use anyhow::{anyhow, bail, Context, Result};
9use std::path::Path;
10use std::process::Command;
11use std::str;
12
13pub mod wasm_target;
14
15pub struct WasmPackVersion {
18 pub local: String,
20 pub latest: String,
23}
24
25pub fn check_rustc_version() -> Result<String> {
27 let local_minor_version = rustc_minor_version();
28 match local_minor_version {
29 Some(mv) => {
30 if mv < 30 {
31 bail!(
32 "Your version of Rust, '1.{}', is not supported. Please install Rust version 1.30.0 or higher.",
33 mv.to_string()
34 )
35 } else {
36 Ok(mv.to_string())
37 }
38 }
39 None => bail!("We can't figure out what your Rust version is- which means you might not have Rust installed. Please install Rust version 1.30.0 or higher."),
40 }
41}
42
43fn rustc_minor_version() -> Option<u32> {
45 macro_rules! otry {
46 ($e:expr) => {
47 match $e {
48 Some(e) => e,
49 None => return None,
50 }
51 };
52 }
53 let output = otry!(Command::new("rustc").arg("--version").output().ok());
54 let version = otry!(str::from_utf8(&output.stdout).ok());
55 let mut pieces = version.split('.');
56 if pieces.next() != Some("rustc 1") {
57 return None;
58 }
59 otry!(pieces.next()).parse().ok()
60}
61
62pub fn check_wasm_pack_versions() -> Result<WasmPackVersion> {
64 match wasm_pack_local_version() {
65 Some(local) => Ok(WasmPackVersion {local, latest: Crate::return_wasm_pack_latest_version()?.unwrap_or_else(|| "".to_string())}),
66 None => bail!("We can't figure out what your wasm-pack version is, make sure the installation path is correct.")
67 }
68}
69
70fn wasm_pack_local_version() -> Option<String> {
71 let output = env!("CARGO_PKG_VERSION");
72 Some(output.to_string())
73}
74
75pub fn cargo_build_wasm(
77 path: &Path,
78 profile: BuildProfile,
79 extra_options: &[String],
80) -> Result<()> {
81 let msg = format!("{}Compiling to Wasm...", emoji::CYCLONE);
82 PBAR.info(&msg);
83
84 let mut cmd = Command::new("cargo");
85 cmd.current_dir(path).arg("build").arg("--lib");
86
87 if PBAR.quiet() {
88 cmd.arg("--quiet");
89 }
90
91 match profile {
92 BuildProfile::Profiling => {
93 cmd.arg("--release");
99 }
100 BuildProfile::Release => {
101 cmd.arg("--release");
102 }
103 BuildProfile::Dev => {
104 }
107 }
108
109 cmd.arg("--target").arg("wasm32-unknown-unknown");
110
111 let mut handle_path = false;
114 let extra_options_with_absolute_paths = extra_options
115 .iter()
116 .map(|option| -> Result<String> {
117 let value = if handle_path && Path::new(option).is_relative() {
118 std::env::current_dir()?
119 .join(option)
120 .to_str()
121 .ok_or_else(|| anyhow!("path contains non-UTF-8 characters"))?
122 .to_string()
123 } else {
124 option.to_string()
125 };
126 handle_path = matches!(&**option, "--target-dir" | "--out-dir" | "--manifest-path");
127 Ok(value)
128 })
129 .collect::<Result<Vec<_>>>()?;
130 cmd.args(extra_options_with_absolute_paths);
131
132 child::run(cmd, "cargo build").context("Compiling your crate to WebAssembly failed")?;
133 Ok(())
134}
135
136pub fn cargo_build_wasm_tests(path: &Path, debug: bool, extra_options: &[String]) -> Result<()> {
150 let mut cmd = Command::new("cargo");
151
152 cmd.current_dir(path).arg("build").arg("--tests");
153
154 if PBAR.quiet() {
155 cmd.arg("--quiet");
156 }
157
158 if !debug {
159 cmd.arg("--release");
160 }
161
162 cmd.arg("--target").arg("wasm32-unknown-unknown");
163
164 cmd.args(extra_options);
165
166 child::run(cmd, "cargo build").context("Compilation of your program failed")?;
167 Ok(())
168}