use child;
use emoji;
use failure::{Error, ResultExt};
use log::info;
use std::fmt;
use std::path::PathBuf;
use std::process::Command;
use PBAR;
struct Wasm32Check {
rustc_path: PathBuf,
sysroot: PathBuf,
found: bool,
is_rustup: bool,
}
impl fmt::Display for Wasm32Check {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let target = "wasm32-unknown-unknown";
if !self.found {
let rustup_string = if self.is_rustup {
"It looks like Rustup is being used.".to_owned()
} else {
format!("It looks like Rustup is not being used. For non-Rustup setups, the {} target needs to be installed manually. See https://rustwasm.github.io/wasm-pack/book/prerequisites/non-rustup-setups.html on how to do this.", target)
};
writeln!(
f,
"{} target not found in sysroot: {:?}",
target, self.sysroot
)
.and_then(|_| {
writeln!(
f,
"\nUsed rustc from the following path: {:?}",
self.rustc_path
)
})
.and_then(|_| writeln!(f, "{}", rustup_string))
} else {
write!(
f,
"sysroot: {:?}, rustc path: {:?}, was found: {}, isRustup: {}",
self.sysroot, self.rustc_path, self.found, self.is_rustup
)
}
}
}
pub fn check_for_wasm32_target() -> Result<(), Error> {
let msg = format!("{}Checking for the Wasm target...", emoji::TARGET);
PBAR.info(&msg);
match check_wasm32_target() {
Ok(ref wasm32_check) if wasm32_check.found => Ok(()),
Ok(wasm32_check) => bail!("{}", wasm32_check),
Err(err) => Err(err),
}
}
fn get_rustc_sysroot() -> Result<PathBuf, Error> {
let command = Command::new("rustc")
.args(&["--print", "sysroot"])
.output()?;
if command.status.success() {
Ok(String::from_utf8(command.stdout)?.trim().into())
} else {
Err(format_err!(
"Getting rustc's sysroot wasn't successful. Got {}",
command.status
))
}
}
fn is_wasm32_target_in_sysroot(sysroot: &PathBuf) -> bool {
let wasm32_target = "wasm32-unknown-unknown";
let rustlib_path = sysroot.join("lib/rustlib");
info!("Looking for {} in {:?}", wasm32_target, rustlib_path);
if rustlib_path.join(wasm32_target).exists() {
info!("Found {} in {:?}", wasm32_target, rustlib_path);
true
} else {
info!("Failed to find {} in {:?}", wasm32_target, rustlib_path);
false
}
}
fn check_wasm32_target() -> Result<Wasm32Check, Error> {
let sysroot = get_rustc_sysroot()?;
let rustc_path = which::which("rustc")?;
if is_wasm32_target_in_sysroot(&sysroot) {
Ok(Wasm32Check {
rustc_path,
sysroot,
found: true,
is_rustup: false,
})
} else {
if sysroot.to_string_lossy().contains("rustup") {
rustup_add_wasm_target().map(|()| Wasm32Check {
rustc_path,
sysroot,
found: true,
is_rustup: true,
})
} else {
Ok(Wasm32Check {
rustc_path,
sysroot,
found: false,
is_rustup: false,
})
}
}
}
fn rustup_add_wasm_target() -> Result<(), Error> {
let mut cmd = Command::new("rustup");
cmd.arg("target").arg("add").arg("wasm32-unknown-unknown");
child::run(cmd, "rustup").context("Adding the wasm32-unknown-unknown target with rustup")?;
Ok(())
}