Skip to content

Commit 59f5464

Browse files
authored
feat(worker-build): auto-install nightly prereqs for --panic-unwind (#972)
1 parent c6847ba commit 59f5464

3 files changed

Lines changed: 146 additions & 11 deletions

File tree

README.md

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -459,18 +459,10 @@ Or in your `wrangler.toml` build command:
459459
command = "cargo install worker-build && worker-build --release --panic-unwind"
460460
```
461461

462-
### Prerequisites
462+
This flag:
463463

464-
To configure the nightly toolchain with build std run:
465-
466-
```
467-
rustup toolchain install nightly
468-
rustup component add rust-src --toolchain nightly
469-
rustup target add wasm32-unknown-unknown --toolchain nightly
470-
```
471-
472-
- Uses the **nightly** Rust toolchain (requires `rustup toolchain install nightly`)
473-
- Rebuilds `std` with `-Zbuild-std=std,panic_unwind` and `-Cpanic=unwind`
464+
- Uses the **nightly** Rust toolchain (installed automatically if missing)
465+
- Rebuilds `std` with `-Zbuild-std=std,panic_unwind` and `-Cpanic=unwind` (the `rust-src` component and `wasm32-unknown-unknown` target for nightly are installed automatically if missing)
474466
- Enables wasm-bindgen's [panic catching](https://wasm-bindgen.github.io/wasm-bindgen/reference/catch-unwind.html)
475467
support, which catches panics at FFI boundaries and converts them to JavaScript `PanicError`
476468
exceptions

worker-build/src/build/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ impl Build {
282282
step_check_rustc_version,
283283
step_check_crate_config,
284284
step_check_for_wasm_target,
285+
step_check_nightly_prerequisites,
285286
step_check_lib_versions,
286287
step_install_wasm_bindgen,
287288
]
@@ -336,6 +337,16 @@ impl Build {
336337
Ok(())
337338
}
338339

340+
fn step_check_nightly_prerequisites(&mut self) -> Result<()> {
341+
if !self.panic_unwind {
342+
return Ok(());
343+
}
344+
info!("Checking nightly prerequisites for panic=unwind...");
345+
target::check_nightly_prerequisites()?;
346+
info!("Nightly prerequisites check was successful.");
347+
Ok(())
348+
}
349+
339350
fn step_build_wasm(&mut self) -> Result<()> {
340351
info!("Building wasm...");
341352
target::cargo_build_wasm(

worker-build/src/build/target.rs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ use std::path::Path;
1414
use std::path::PathBuf;
1515
use std::process::Command;
1616

17+
const NIGHTLY_TOOLCHAIN: &str = "nightly";
18+
1719
struct Wasm32Check {
1820
rustc_path: PathBuf,
1921
sysroot: PathBuf,
@@ -168,6 +170,136 @@ fn rustup_add_wasm_target() -> Result<()> {
168170
Ok(())
169171
}
170172

173+
/// Ensure that the nightly toolchain is installed and has the `rust-src` component
174+
/// and `wasm32-unknown-unknown` target, which are required for `-Z build-std`.
175+
pub fn check_nightly_prerequisites() -> Result<()> {
176+
let msg = format!(
177+
"{}Checking nightly toolchain prerequisites for panic=unwind...",
178+
emoji::TARGET
179+
);
180+
PBAR.info(&msg);
181+
182+
let nightly_sysroot = get_nightly_sysroot()?;
183+
184+
if !nightly_sysroot.exists() {
185+
install_nightly_toolchain()?;
186+
}
187+
188+
if !has_rust_src_component()? {
189+
install_rust_src_component()?;
190+
}
191+
192+
if !does_nightly_wasm32_target_exist() {
193+
rustup_add_wasm_target_nightly()?;
194+
}
195+
196+
Ok(())
197+
}
198+
199+
fn get_nightly_sysroot() -> Result<PathBuf> {
200+
let command = Command::new("rustc")
201+
.args(["+nightly", "--print", "sysroot"])
202+
.output()?;
203+
204+
if command.status.success() {
205+
Ok(String::from_utf8(command.stdout)?.trim().into())
206+
} else {
207+
Err(anyhow!(
208+
"Getting nightly rustc's sysroot wasn't successful. Got {}",
209+
command.status
210+
))
211+
}
212+
}
213+
214+
fn install_nightly_toolchain() -> Result<()> {
215+
let msg = format!(
216+
"{}Installing nightly toolchain via rustup...",
217+
emoji::TARGET
218+
);
219+
PBAR.info(&msg);
220+
221+
let mut cmd = Command::new("rustup");
222+
cmd.arg("toolchain").arg("install").arg(NIGHTLY_TOOLCHAIN);
223+
utils::run(cmd, "rustup").context("Installing the nightly toolchain with rustup")?;
224+
225+
Ok(())
226+
}
227+
228+
fn has_rust_src_component() -> Result<bool> {
229+
let command = Command::new("rustup")
230+
.args(["component", "list", "--toolchain", NIGHTLY_TOOLCHAIN])
231+
.output()?;
232+
233+
if !command.status.success() {
234+
return Ok(false);
235+
}
236+
237+
let stdout = String::from_utf8(command.stdout)?;
238+
Ok(stdout
239+
.lines()
240+
.any(|line| line.starts_with("rust-src") && line.contains("(installed)")))
241+
}
242+
243+
fn install_rust_src_component() -> Result<()> {
244+
let msg = format!(
245+
"{}Installing rust-src component for nightly toolchain...",
246+
emoji::TARGET
247+
);
248+
PBAR.info(&msg);
249+
250+
let mut cmd = Command::new("rustup");
251+
cmd.arg("component")
252+
.arg("add")
253+
.arg("rust-src")
254+
.arg("--toolchain")
255+
.arg(NIGHTLY_TOOLCHAIN);
256+
utils::run(cmd, "rustup").context("Adding the rust-src component with rustup")?;
257+
258+
Ok(())
259+
}
260+
261+
fn does_nightly_wasm32_target_exist() -> bool {
262+
let command = Command::new("rustc")
263+
.args([
264+
"+nightly",
265+
"--target",
266+
"wasm32-unknown-unknown",
267+
"--print",
268+
"target-libdir",
269+
])
270+
.output();
271+
272+
match command {
273+
Ok(output) if output.status.success() => {
274+
let path: PathBuf = String::from_utf8(output.stdout)
275+
.ok()
276+
.map(|s| s.trim().into())
277+
.unwrap_or_default();
278+
path.exists()
279+
}
280+
_ => false,
281+
}
282+
}
283+
284+
fn rustup_add_wasm_target_nightly() -> Result<()> {
285+
let msg = format!(
286+
"{}Adding wasm32-unknown-unknown target for nightly toolchain...",
287+
emoji::TARGET
288+
);
289+
PBAR.info(&msg);
290+
291+
let mut cmd = Command::new("rustup");
292+
cmd.arg("target")
293+
.arg("add")
294+
.arg("wasm32-unknown-unknown")
295+
.arg("--toolchain")
296+
.arg(NIGHTLY_TOOLCHAIN);
297+
utils::run(cmd, "rustup")
298+
.context("Adding the wasm32-unknown-unknown target for nightly with rustup")?;
299+
300+
Ok(())
301+
}
302+
171303
/// Ensure that `rustc` is present and that it is >= 1.30.0
172304
pub fn check_rustc_version() -> Result<String> {
173305
let local_minor_version = rustc_minor_version();

0 commit comments

Comments
 (0)