Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(wasm-builder): allow building with stable toolchain #3459

Merged
merged 31 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
eaa20f3
fix(wasm-builder): remove build scripts environment variables
StackOverflowExcept1on Oct 30, 2023
cf92679
add simple test in check action
StackOverflowExcept1on Oct 30, 2023
89fc899
remove wrappers
StackOverflowExcept1on Oct 30, 2023
27ac13e
ci(time-consuming-tests): build & tests on two toolchains
StackOverflowExcept1on Oct 30, 2023
9345f9c
try this to fix ci
StackOverflowExcept1on Oct 30, 2023
04899da
install stable but w/o as default toolchain
StackOverflowExcept1on Oct 30, 2023
af137e6
back to old code
StackOverflowExcept1on Oct 30, 2023
c18a745
experiment with RUSTC RUSTC_BOOTSTRAP
StackOverflowExcept1on Oct 30, 2023
03bd5c7
add some comments
StackOverflowExcept1on Oct 31, 2023
8908cf2
revert RUSTC_BOOTSTRAP & pin version
StackOverflowExcept1on Oct 31, 2023
11bf2d6
pin specific toolchain and provide error handling
StackOverflowExcept1on Oct 31, 2023
b0246e8
use ensure!
StackOverflowExcept1on Oct 31, 2023
c258f69
extract lists into const slices
StackOverflowExcept1on Nov 10, 2023
65efa62
read toolchain from workspace dir
StackOverflowExcept1on Nov 10, 2023
e53233e
apply suggestion
StackOverflowExcept1on Nov 10, 2023
0e85180
Merge remote-tracking branch 'origin/master' into av/wasm-builder-cle…
StackOverflowExcept1on Dec 26, 2023
c4e2e56
remove concept of pinned toolchain
StackOverflowExcept1on Dec 26, 2023
77f1f29
small fix
StackOverflowExcept1on Dec 26, 2023
0f77875
Merge remote-tracking branch 'origin/master' into av/wasm-builder-cle…
StackOverflowExcept1on Jan 10, 2024
1d56886
ws
StackOverflowExcept1on Jan 10, 2024
254fad6
add recommended toolchain to wasm-builder
StackOverflowExcept1on Jan 12, 2024
68906f2
Merge remote-tracking branch 'origin/master' into av/wasm-builder-cle…
StackOverflowExcept1on Jan 12, 2024
eaa92fc
add check on ci
StackOverflowExcept1on Jan 12, 2024
603e2fd
resolve conversations
StackOverflowExcept1on Jan 15, 2024
1f8d2bc
use with_forced_recommended_toolchain in out-of-memory demo
StackOverflowExcept1on Jan 16, 2024
95ad91b
Merge remote-tracking branch 'origin/master' into av/wasm-builder-cle…
StackOverflowExcept1on Jan 16, 2024
6cdbc09
[skip-ci] add docs about internal use
StackOverflowExcept1on Jan 16, 2024
9e5b362
[skip-ci] add better error msg
StackOverflowExcept1on Jan 16, 2024
5e95541
[skip-ci] fix comment
StackOverflowExcept1on Jan 16, 2024
beb4d72
more comments
StackOverflowExcept1on Jan 17, 2024
19800ad
Merge remote-tracking branch 'origin/master' into av/wasm-builder-cle…
StackOverflowExcept1on Jan 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,25 @@ jobs:
exit 1
fi

- name: "Test: Wasm-builder recommended toolchain matches rust-toolchain.toml"
run: |
TOOLCHAIN=$(grep 'channel' rust-toolchain.toml | cut -d '"' -f 2)
CARGO_TOOLCHAIN="utils/wasm-builder/src/cargo_toolchain.rs"
StackOverflowExcept1on marked this conversation as resolved.
Show resolved Hide resolved
if ! grep -q "$TOOLCHAIN" $CARGO_TOOLCHAIN; then
echo "Please update PINNED_NIGHTLY_TOOLCHAIN constant in $CARGO_TOOLCHAIN to match rust-toolchain.toml."
exit 1
fi

- name: "Install: Rust stable toolchain"
uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-unknown-unknown
components: llvm-tools

- name: "Check: Compiling gstd on stable"
run: cargo +stable check -p gstd
run: |
cargo +stable check -p gstd --target wasm32-unknown-unknown
cargo +stable check --manifest-path utils/wasm-builder/test-program/Cargo.toml

fuzzer:
runs-on: [kuberunner, github-runner-01]
Expand Down
2 changes: 1 addition & 1 deletion examples/out-of-memory/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ homepage.workspace = true
repository.workspace = true

[dependencies]
gstd.workspace = true
gstd = { workspace = true, features = ["oom-handler"] }

[build-dependencies]
gear-wasm-builder.workspace = true
Expand Down
7 changes: 6 additions & 1 deletion examples/out-of-memory/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use gear_wasm_builder::WasmBuilder;

fn main() {
gear_wasm_builder::build();
WasmBuilder::new()
.exclude_features(vec!["std"])
.with_forced_recommended_toolchain()
StackOverflowExcept1on marked this conversation as resolved.
Show resolved Hide resolved
.build();
}
7 changes: 7 additions & 0 deletions utils/wasm-builder/src/builder_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,11 @@ pub enum BuilderError {

#[error("cargo toolchain is invalid `{0}`")]
CargoToolchainInvalid(String),

#[error(
"recommended toolchain `{0}` not found, install it using the command:\n\
rustup toolchain install {0} --component llvm-tools --target wasm32-unknown-unknown\n\n\
after installation, do not forget to set `channel = \"{0}\"` in `rust-toolchain.toml` file"
)]
RecommendedToolchainNotFound(String),
}
73 changes: 67 additions & 6 deletions utils/wasm-builder/src/cargo_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

use crate::cargo_toolchain::Toolchain;
use anyhow::{ensure, Context, Result};
use std::{path::PathBuf, process::Command};
use std::{env, path::PathBuf, process::Command};

use crate::builder_error::BuilderError;

Expand All @@ -31,6 +31,8 @@ pub struct CargoCommand {
target_dir: PathBuf,
features: Vec<String>,
toolchain: Toolchain,
check_recommended_toolchain: bool,
force_recommended_toolchain: bool,
paths_to_remap: Vec<(PathBuf, &'static str)>,
}

Expand All @@ -44,7 +46,9 @@ impl CargoCommand {
rustc_flags: vec!["-C", "link-arg=--import-memory", "-C", "linker-plugin-lto"],
target_dir: "target".into(),
features: vec![],
toolchain: Toolchain::nightly(),
toolchain: Toolchain::try_from_rustup().expect("Failed to get toolchain from rustup"),
check_recommended_toolchain: false,
force_recommended_toolchain: false,
paths_to_remap: vec![],
}
}
Expand All @@ -71,9 +75,14 @@ impl CargoCommand {
self.features = features.into();
}

/// Set toolchain.
pub(crate) fn set_toolchain(&mut self, toolchain: Toolchain) {
self.toolchain = toolchain;
/// Sets whether to check the version of the recommended toolchain.
pub(crate) fn set_check_recommended_toolchain(&mut self, check_recommended_toolchain: bool) {
self.check_recommended_toolchain = check_recommended_toolchain;
}

/// Sets whether to force the version of the recommended toolchain.
pub(crate) fn set_force_recommended_toolchain(&mut self, force_recommended_toolchain: bool) {
self.force_recommended_toolchain = force_recommended_toolchain;
}

/// Set paths to remap.
Expand All @@ -85,10 +94,23 @@ impl CargoCommand {

/// Execute the `cargo` command with invoking supplied arguments.
pub fn run(&self) -> Result<()> {
if self.check_recommended_toolchain {
self.toolchain.check_recommended_toolchain()?;
}

let toolchain = if self.force_recommended_toolchain {
Toolchain::recommended_nightly()
} else {
self.toolchain.clone()
};

let mut cargo = Command::new(&self.path);
if self.force_recommended_toolchain {
self.clean_up_environment(&mut cargo);
}
cargo
.arg("run")
.arg(self.toolchain.nightly_toolchain_str().as_ref())
.arg(toolchain.raw_toolchain_str().as_ref())
.arg("cargo")
.arg("rustc")
.arg("--target=wasm32-unknown-unknown")
Expand Down Expand Up @@ -135,6 +157,45 @@ impl CargoCommand {
Ok(())
}

fn clean_up_environment(&self, command: &mut Command) {
// Inherited build script environment variables must be removed
// so that they cannot change the behavior of the cargo package manager.

// https://doc.rust-lang.org/cargo/reference/environment-variables.html
// `RUSTC_WRAPPER` and `RUSTC_WORKSPACE_WRAPPER` are not removed due to tools like sccache.
const INHERITED_ENV_VARS: &[&str] = &[
"CARGO",
"CARGO_MANIFEST_DIR",
"CARGO_MANIFEST_LINKS",
"CARGO_MAKEFLAGS",
"OUT_DIR",
"TARGET",
"HOST",
"NUM_JOBS",
"OPT_LEVEL",
"PROFILE",
"RUSTC",
"RUSTDOC",
"RUSTC_LINKER",
"CARGO_ENCODED_RUSTFLAGS",
];

for env_var in INHERITED_ENV_VARS {
command.env_remove(env_var);
}

const INHERITED_ENV_VARS_WITH_PREFIX: &[&str] =
&["CARGO_FEATURE_", "CARGO_CFG_", "DEP_", "CARGO_PKG_"];

for (env_var, _) in env::vars() {
for prefix in INHERITED_ENV_VARS_WITH_PREFIX {
if env_var.starts_with(prefix) {
command.env_remove(&env_var);
}
}
}
}

fn remove_cargo_encoded_rustflags(&self, command: &mut Command) {
// substrate's wasm-builder removes these vars so do we
// check its source for details
Expand Down
40 changes: 14 additions & 26 deletions utils/wasm-builder/src/cargo_toolchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ static TOOLCHAIN_CHANNELS: &[&str] = &[
pub(crate) struct Toolchain(String);

impl Toolchain {
StackOverflowExcept1on marked this conversation as resolved.
Show resolved Hide resolved
/// Returns `Toolchain` representing the most recent nightly version.
pub fn nightly() -> Self {
Self("nightly".into())
/// This is a version of nightly toolchain, tested on our CI.
const PINNED_NIGHTLY_TOOLCHAIN: &'static str = "nightly-2023-09-05";

/// Returns `Toolchain` representing the recommended nightly version.
pub fn recommended_nightly() -> Self {
Self(Self::PINNED_NIGHTLY_TOOLCHAIN.into())
}

/// Fetches `Toolchain` via rustup.
Expand Down Expand Up @@ -93,28 +96,13 @@ impl Toolchain {
self.0.as_str().into()
}

/// Returns toolchain string specification without target triple
/// and with raw `<channel>` substituted by `nightly`.
///
/// `nightly[-<date>]`
///
/// `<date> = YYYY-MM-DD`
pub fn nightly_toolchain_str(&'_ self) -> Cow<'_, str> {
if !self.is_nightly() {
let date_start_idx = self
.0
.find('-')
.unwrap_or_else(|| self.raw_toolchain_str().len());
let mut toolchain_str = self.0.clone();
toolchain_str.replace_range(..date_start_idx, "nightly");
toolchain_str.into()
} else {
self.raw_toolchain_str()
}
}

// Returns bool representing nightly toolchain.
fn is_nightly(&self) -> bool {
self.0.starts_with("nightly")
/// Checks whether the toolchain is recommended.
pub fn check_recommended_toolchain(&self) -> Result<()> {
let toolchain = Self::PINNED_NIGHTLY_TOOLCHAIN;
anyhow::ensure!(
self.raw_toolchain_str() == toolchain,
BuilderError::RecommendedToolchainNotFound(toolchain.into()),
);
Ok(())
}
}
43 changes: 41 additions & 2 deletions utils/wasm-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#![doc(html_logo_url = "https://docs.gear.rs/logo.svg")]
#![doc(html_favicon_url = "https://gear-tech.io/favicons/favicon.ico")]

use crate::{cargo_command::CargoCommand, cargo_toolchain::Toolchain, wasm_project::WasmProject};
use crate::{cargo_command::CargoCommand, wasm_project::WasmProject};
use anyhow::{Context, Result};
use gmeta::{Metadata, MetadataRepr};
use regex::Regex;
Expand Down Expand Up @@ -82,6 +82,22 @@ impl WasmBuilder {
self
}

/// Add check of recommended toolchain.
pub fn with_recommended_toolchain(mut self) -> Self {
self.cargo.set_check_recommended_toolchain(true);
self
}

/// Force the recommended toolchain to be used, but do not check whether the
/// current toolchain is recommended.
///
/// NOTE: For internal use only, not recommended for production programs.
#[doc(hidden)]
pub fn with_forced_recommended_toolchain(mut self) -> Self {
self.cargo.set_force_recommended_toolchain(true);
self
}

/// Build the program and produce an output WASM binary.
pub fn build(self) {
if env::var("__GEAR_WASM_BUILDER_NO_BUILD").is_ok() {
Expand All @@ -101,7 +117,6 @@ impl WasmBuilder {
fn build_project(mut self) -> Result<()> {
self.wasm_project.generate()?;

self.cargo.set_toolchain(Toolchain::try_from_rustup()?);
self.cargo
.set_manifest_path(self.wasm_project.manifest_path());
self.cargo.set_target_dir(self.wasm_project.target_dir());
Expand Down Expand Up @@ -229,3 +244,27 @@ pub fn build_metawasm() {
.exclude_features(FEATURES_TO_EXCLUDE_BY_DEFAULT.to_vec())
.build();
}

/// Shorthand function to be used in `build.rs`.
pub fn recommended_nightly() {
WasmBuilder::new()
.exclude_features(FEATURES_TO_EXCLUDE_BY_DEFAULT.to_vec())
.with_recommended_toolchain()
.build();
}

/// Shorthand function to be used in `build.rs`.
pub fn recommended_nightly_with_metadata<T: Metadata>() {
WasmBuilder::with_meta(T::repr())
.exclude_features(FEATURES_TO_EXCLUDE_BY_DEFAULT.to_vec())
.with_recommended_toolchain()
.build();
}

/// Shorthand function to be used in `build.rs`.
pub fn recommended_nightly_metawasm() {
WasmBuilder::new_metawasm()
.exclude_features(FEATURES_TO_EXCLUDE_BY_DEFAULT.to_vec())
.with_recommended_toolchain()
.build();
}
47 changes: 42 additions & 5 deletions utils/wasm-builder/tests/smoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use gear_wasm_builder::TARGET;
use std::{fs, process::Command};
use std::{fs, process::Command, sync::OnceLock};

struct CargoRunner(Command);

Expand All @@ -26,6 +26,13 @@ impl CargoRunner {
Self(Command::new("cargo"))
}

fn stable() -> Self {
let mut cmd = Command::new("cargo");
cmd.arg("+stable");

Self(cmd)
}

fn args<const SIZE: usize>(mut self, args: [&str; SIZE]) -> Self {
self.0.args(args);
self
Expand All @@ -42,35 +49,65 @@ impl CargoRunner {
}
}

fn install_stable_toolchain() {
static STABLE_TOOLCHAIN: OnceLock<()> = OnceLock::new();

STABLE_TOOLCHAIN.get_or_init(|| {
let status = Command::new("rustup")
.arg("toolchain")
.arg("install")
.arg("stable")
.arg("--component")
.arg("llvm-tools")
.arg("--target")
.arg("wasm32-unknown-unknown")
.status()
.expect("rustup run error");
assert!(status.success());
});
}

#[ignore]
#[test]
fn test_debug() {
install_stable_toolchain();

CargoRunner::new().args(["test"]).run();
CargoRunner::stable().args(["test"]).run();
}

#[ignore]
#[test]
fn build_debug() {
CargoRunner::new().args(["build"]).run()
install_stable_toolchain();

CargoRunner::new().args(["build"]).run();
CargoRunner::stable().args(["build"]).run();
}

#[ignore]
#[test]
fn test_release() {
CargoRunner::new().args(["test", "--release"]).run()
install_stable_toolchain();

CargoRunner::new().args(["test", "--release"]).run();
CargoRunner::stable().args(["test", "--release"]).run();
}

#[ignore]
#[test]
fn build_release() {
CargoRunner::new().args(["build", "--release"]).run()
install_stable_toolchain();

CargoRunner::new().args(["build", "--release"]).run();
CargoRunner::stable().args(["build", "--release"]).run();
}

#[test]
fn build_release_for_target() {
CargoRunner::new()
.args(["build", "--release", "--target", TARGET])
.run()
.run();
}

#[ignore]
Expand Down