-
Notifications
You must be signed in to change notification settings - Fork 418
/
Copy pathwasm_target.rs
141 lines (124 loc) · 4.28 KB
/
wasm_target.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//! Checking for the wasm32 target
use crate::child;
use crate::emoji;
use crate::PBAR;
use anyhow::{anyhow, bail, Context, Result};
use log::info;
use std::fmt;
use std::path::{Path, PathBuf};
use std::process::Command;
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
)
}
}
}
/// Ensure that `rustup` has the `wasm32-unknown-unknown` target installed for
/// current toolchain
pub fn check_for_wasm32_target() -> Result<()> {
let msg = format!("{}Checking for the Wasm target...", emoji::TARGET);
PBAR.info(&msg);
// Check if wasm32 target is present, otherwise bail.
match check_wasm32_target() {
Ok(ref wasm32_check) if wasm32_check.found => Ok(()),
Ok(wasm32_check) => bail!("{}", wasm32_check),
Err(err) => Err(err),
}
}
/// Get rustc's sysroot as a PathBuf
fn get_rustc_sysroot() -> Result<PathBuf> {
let command = Command::new("rustc")
.args(&["--print", "sysroot"])
.output()?;
if command.status.success() {
Ok(String::from_utf8(command.stdout)?.trim().into())
} else {
Err(anyhow!(
"Getting rustc's sysroot wasn't successful. Got {}",
command.status
))
}
}
/// Checks if the wasm32-unknown-unknown is present in rustc's sysroot.
fn is_wasm32_target_in_sysroot(sysroot: &Path) -> 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> {
let sysroot = get_rustc_sysroot()?;
let rustc_path = which::which("rustc")?;
// If wasm32-unknown-unknown already exists we're ok.
if is_wasm32_target_in_sysroot(&sysroot) {
Ok(Wasm32Check {
rustc_path,
sysroot,
found: true,
is_rustup: false,
})
// If it doesn't exist, then we need to check if we're using rustup.
} else {
// If sysroot contains "rustup", then we can assume we're using rustup
// and use rustup to add the wasm32-unknown-unknown target.
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,
})
}
}
}
/// Add wasm32-unknown-unknown using `rustup`.
fn rustup_add_wasm_target() -> Result<()> {
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(())
}