Skip to content

Commit afad8da

Browse files
bkchrGeneral-Beck
authored andcommitted
Extend rust nightly detection in wasm-builder (paritytech#5021)
Instead of just testing `cargo` and `rustup run nightly`, we now test the `CARGO` env variable and also scan non default nightlies. The user is also now able to select the toolchain with `WASM_BUILD_TOOLCHAIN`.
1 parent b88aef4 commit afad8da

File tree

3 files changed

+62
-22
lines changed

3 files changed

+62
-22
lines changed

utils/wasm-builder/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ By using environment variables, you can configure which WASM binaries are built
5050
- `WASM_BUILD_NO_COLOR` - Disable color output of the wasm build.
5151
- `WASM_TARGET_DIRECTORY` - Will copy any build wasm binary to the given directory. The path needs
5252
to be absolute.
53+
- `WASM_BUILD_TOOLCHAIN` - The toolchain that should be used to build the wasm binaries. The
54+
format needs to be the same as used by cargo, e.g. `nightly-2020-02-20`.
5355

5456
Each project can be skipped individually by using the environment variable `SKIP_PROJECT_NAME_WASM_BUILD`.
5557
Where `PROJECT_NAME` needs to be replaced by the name of the cargo project, e.g. `node-runtime` will
@@ -61,5 +63,8 @@ WASM builder requires the following prerequisites for building the WASM binary:
6163

6264
- rust nightly + `wasm32-unknown-unknown` toolchain
6365

66+
If a specific rust nightly is installed with `rustup`, it is important that the wasm target is installed
67+
as well. For example if installing the rust nightly from 20.02.2020 using `rustup install nightly-2020-02-20`,
68+
the wasm target needs to be installed as well `rustup target add wasm32-unknown-unknown --toolchain nightly-2020-02-20`.
6469

6570
License: GPL-3.0

utils/wasm-builder/src/lib.rs

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@
6666
//! - `WASM_BUILD_NO_COLOR` - Disable color output of the wasm build.
6767
//! - `WASM_TARGET_DIRECTORY` - Will copy any build wasm binary to the given directory. The path needs
6868
//! to be absolute.
69+
//! - `WASM_BUILD_TOOLCHAIN` - The toolchain that should be used to build the wasm binaries. The
70+
//! format needs to be the same as used by cargo, e.g. `nightly-2020-02-20`.
6971
//!
7072
//! Each project can be skipped individually by using the environment variable `SKIP_PROJECT_NAME_WASM_BUILD`.
7173
//! Where `PROJECT_NAME` needs to be replaced by the name of the cargo project, e.g. `node-runtime` will
@@ -77,8 +79,11 @@
7779
//!
7880
//! - rust nightly + `wasm32-unknown-unknown` toolchain
7981
//!
82+
//! If a specific rust nightly is installed with `rustup`, it is important that the wasm target is installed
83+
//! as well. For example if installing the rust nightly from 20.02.2020 using `rustup install nightly-2020-02-20`,
84+
//! the wasm target needs to be installed as well `rustup target add wasm32-unknown-unknown --toolchain nightly-2020-02-20`.
8085
81-
use std::{env, fs, path::PathBuf, process::{Command, Stdio, self}};
86+
use std::{env, fs, path::PathBuf, process::{Command, self}, io::BufRead};
8287

8388
mod prerequisites;
8489
mod wasm_project;
@@ -103,6 +108,9 @@ const WASM_TARGET_DIRECTORY: &str = "WASM_TARGET_DIRECTORY";
103108
/// Environment variable to disable color output of the wasm build.
104109
const WASM_BUILD_NO_COLOR: &str = "WASM_BUILD_NO_COLOR";
105110

111+
/// Environment variable to set the toolchain used to compile the wasm binary.
112+
const WASM_BUILD_TOOLCHAIN: &str = "WASM_BUILD_TOOLCHAIN";
113+
106114
/// Build the currently built project as wasm binary.
107115
///
108116
/// The current project is determined by using the `CARGO_MANIFEST_DIR` environment variable.
@@ -178,19 +186,56 @@ fn write_file_if_changed(file: PathBuf, content: String) {
178186

179187
/// Get a cargo command that compiles with nightly
180188
fn get_nightly_cargo() -> CargoCommand {
189+
let env_cargo = CargoCommand::new(
190+
&env::var("CARGO").expect("`CARGO` env variable is always set by cargo"),
191+
);
181192
let default_cargo = CargoCommand::new("cargo");
182-
let mut rustup_run_nightly = CargoCommand::new("rustup");
183-
rustup_run_nightly.args(&["run", "nightly", "cargo"]);
193+
let rustup_run_nightly = CargoCommand::new_with_args("rustup", &["run", "nightly", "cargo"]);
194+
let wasm_toolchain = env::var(WASM_BUILD_TOOLCHAIN).ok();
184195

185-
if default_cargo.is_nightly() {
196+
// First check if the user requested a specific toolchain
197+
if let Some(cmd) = wasm_toolchain.and_then(|t| get_rustup_nightly(Some(t))) {
198+
cmd
199+
} else if env_cargo.is_nightly() {
200+
env_cargo
201+
} else if default_cargo.is_nightly() {
186202
default_cargo
187-
} else if rustup_run_nightly.works() {
203+
} else if rustup_run_nightly.is_nightly() {
188204
rustup_run_nightly
189205
} else {
190-
default_cargo
206+
// If no command before provided us with a nightly compiler, we try to search one
207+
// with rustup. If that fails as well, we return the default cargo and let the prequisities
208+
// check fail.
209+
get_rustup_nightly(None).unwrap_or(default_cargo)
191210
}
192211
}
193212

213+
/// Get a nightly from rustup. If `selected` is `Some(_)`, a `CargoCommand` using the given
214+
/// nightly is returned.
215+
fn get_rustup_nightly(selected: Option<String>) -> Option<CargoCommand> {
216+
let host = format!("-{}", env::var("HOST").expect("`HOST` is always set by cargo"));
217+
218+
let version = match selected {
219+
Some(selected) => selected,
220+
None => {
221+
let output = Command::new("rustup").args(&["toolchain", "list"]).output().ok()?.stdout;
222+
let lines = output.as_slice().lines();
223+
224+
let mut latest_nightly = None;
225+
for line in lines.filter_map(|l| l.ok()) {
226+
if line.starts_with("nightly-") && line.ends_with(&host) {
227+
// Rustup prints them sorted
228+
latest_nightly = Some(line.clone());
229+
}
230+
}
231+
232+
latest_nightly?.trim_end_matches(&host).into()
233+
}
234+
};
235+
236+
Some(CargoCommand::new_with_args("rustup", &["run", &version, "cargo"]))
237+
}
238+
194239
/// Builder for cargo commands
195240
#[derive(Debug)]
196241
struct CargoCommand {
@@ -203,14 +248,11 @@ impl CargoCommand {
203248
CargoCommand { program: program.into(), args: Vec::new() }
204249
}
205250

206-
fn arg(&mut self, arg: &str) -> &mut Self {
207-
self.args.push(arg.into());
208-
self
209-
}
210-
211-
fn args(&mut self, args: &[&str]) -> &mut Self {
212-
args.into_iter().for_each(|a| { self.arg(a); });
213-
self
251+
fn new_with_args(program: &str, args: &[&str]) -> Self {
252+
CargoCommand {
253+
program: program.into(),
254+
args: args.iter().map(ToString::to_string).collect(),
255+
}
214256
}
215257

216258
fn command(&self) -> Command {
@@ -219,14 +261,6 @@ impl CargoCommand {
219261
cmd
220262
}
221263

222-
fn works(&self) -> bool {
223-
self.command()
224-
.stdout(Stdio::null())
225-
.stderr(Stdio::null())
226-
.status()
227-
.map(|s| s.success()).unwrap_or(false)
228-
}
229-
230264
/// Check if the supplied cargo command is a nightly version
231265
fn is_nightly(&self) -> bool {
232266
// `RUSTC_BOOTSTRAP` tells a stable compiler to behave like a nightly. So, when this env

utils/wasm-builder/src/wasm_project.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,7 @@ fn generate_rerun_if_changed_instructions(
453453
println!("cargo:rerun-if-env-changed={}", crate::WASM_BUILD_TYPE_ENV);
454454
println!("cargo:rerun-if-env-changed={}", crate::WASM_BUILD_RUSTFLAGS_ENV);
455455
println!("cargo:rerun-if-env-changed={}", crate::WASM_TARGET_DIRECTORY);
456+
println!("cargo:rerun-if-env-changed={}", crate::WASM_BUILD_TOOLCHAIN);
456457
}
457458

458459
/// Copy the WASM binary to the target directory set in `WASM_TARGET_DIRECTORY` environment variable.

0 commit comments

Comments
 (0)