mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 14:37:57 +00:00
7ec0b8741b
resolve https://github.com/paritytech/polkadot-sdk/issues/3116 a follow-up on https://github.com/paritytech/polkadot-sdk/pull/3061#pullrequestreview-1847530265: - [x] reuse collator overseer builder for polkadot-node and collator - [x] run zombienet test (0001-parachains-smoke-test.toml) - [x] make wasm build errors more user-friendly for an easier problem detection when using different toolchains in Rust --------- Co-authored-by: ordian <write@reusable.software> Co-authored-by: s0me0ne-unkn0wn <48632512+s0me0ne-unkn0wn@users.noreply.github.com>
216 lines
7.2 KiB
Rust
216 lines
7.2 KiB
Rust
// This file is part of Substrate.
|
|
|
|
// Copyright (C) Parity Technologies (UK) Ltd.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
use crate::{write_file_if_changed, CargoCommand, CargoCommandVersioned, RuntimeTarget};
|
|
|
|
use console::style;
|
|
use std::{
|
|
fs,
|
|
path::{Path, PathBuf},
|
|
process::Command,
|
|
};
|
|
|
|
use tempfile::tempdir;
|
|
|
|
/// Colorizes an error message, if color output is enabled.
|
|
fn colorize_error_message(message: &str) -> String {
|
|
if super::color_output_enabled() {
|
|
style(message).red().bold().to_string()
|
|
} else {
|
|
message.into()
|
|
}
|
|
}
|
|
|
|
/// Colorizes an auxiliary message, if color output is enabled.
|
|
fn colorize_aux_message(message: &str) -> String {
|
|
if super::color_output_enabled() {
|
|
style(message).yellow().bold().to_string()
|
|
} else {
|
|
message.into()
|
|
}
|
|
}
|
|
|
|
/// Checks that all prerequisites are installed.
|
|
///
|
|
/// Returns the versioned cargo command on success.
|
|
pub(crate) fn check(target: RuntimeTarget) -> Result<CargoCommandVersioned, String> {
|
|
let cargo_command = crate::get_cargo_command(target);
|
|
match target {
|
|
RuntimeTarget::Wasm => {
|
|
if !cargo_command.supports_substrate_runtime_env(target) {
|
|
return Err(colorize_error_message(
|
|
"Cannot compile a WASM runtime: no compatible Rust compiler found!\n\
|
|
Install at least Rust 1.68.0 or a recent nightly version.",
|
|
));
|
|
}
|
|
|
|
check_wasm_toolchain_installed(cargo_command)
|
|
},
|
|
RuntimeTarget::Riscv => {
|
|
if !cargo_command.supports_substrate_runtime_env(target) {
|
|
return Err(colorize_error_message(
|
|
"Cannot compile a RISC-V runtime: no compatible Rust compiler found!\n\
|
|
Install a toolchain from here and try again: https://github.com/paritytech/rustc-rv32e-toolchain/",
|
|
));
|
|
}
|
|
|
|
let dummy_crate = DummyCrate::new(&cargo_command, target);
|
|
let version = dummy_crate.get_rustc_version();
|
|
Ok(CargoCommandVersioned::new(cargo_command, version))
|
|
},
|
|
}
|
|
}
|
|
|
|
struct DummyCrate<'a> {
|
|
cargo_command: &'a CargoCommand,
|
|
temp: tempfile::TempDir,
|
|
manifest_path: PathBuf,
|
|
target: RuntimeTarget,
|
|
}
|
|
|
|
impl<'a> DummyCrate<'a> {
|
|
/// Creates a minimal dummy crate.
|
|
fn new(cargo_command: &'a CargoCommand, target: RuntimeTarget) -> Self {
|
|
let temp = tempdir().expect("Creating temp dir does not fail; qed");
|
|
let project_dir = temp.path();
|
|
fs::create_dir_all(project_dir.join("src")).expect("Creating src dir does not fail; qed");
|
|
|
|
let manifest_path = project_dir.join("Cargo.toml");
|
|
write_file_if_changed(
|
|
&manifest_path,
|
|
r#"
|
|
[package]
|
|
name = "dummy-crate"
|
|
version = "1.0.0"
|
|
edition = "2021"
|
|
|
|
[workspace]
|
|
"#,
|
|
);
|
|
|
|
write_file_if_changed(project_dir.join("src/main.rs"), "fn main() {}");
|
|
DummyCrate { cargo_command, temp, manifest_path, target }
|
|
}
|
|
|
|
fn prepare_command(&self, subcommand: &str) -> Command {
|
|
let mut cmd = self.cargo_command.command();
|
|
// Chdir to temp to avoid including project's .cargo/config.toml
|
|
// by accident - it can happen in some CI environments.
|
|
cmd.current_dir(&self.temp);
|
|
cmd.arg(subcommand)
|
|
.arg(format!("--target={}", self.target.rustc_target()))
|
|
.args(&["--manifest-path", &self.manifest_path.display().to_string()]);
|
|
|
|
if super::color_output_enabled() {
|
|
cmd.arg("--color=always");
|
|
}
|
|
|
|
// manually set the `CARGO_TARGET_DIR` to prevent a cargo deadlock
|
|
let target_dir = self.temp.path().join("target").display().to_string();
|
|
cmd.env("CARGO_TARGET_DIR", &target_dir);
|
|
|
|
// Make sure the host's flags aren't used here, e.g. if an alternative linker is specified
|
|
// in the RUSTFLAGS then the check we do here will break unless we clear these.
|
|
cmd.env_remove("CARGO_ENCODED_RUSTFLAGS");
|
|
cmd.env_remove("RUSTFLAGS");
|
|
// Make sure if we're called from within a `build.rs` the host toolchain won't override a
|
|
// rustup toolchain we've picked.
|
|
cmd.env_remove("RUSTC");
|
|
cmd
|
|
}
|
|
|
|
fn get_rustc_version(&self) -> String {
|
|
let mut run_cmd = self.prepare_command("rustc");
|
|
run_cmd.args(&["-q", "--", "--version"]);
|
|
run_cmd
|
|
.output()
|
|
.ok()
|
|
.and_then(|o| String::from_utf8(o.stdout).ok())
|
|
.unwrap_or_else(|| "unknown rustc version".into())
|
|
}
|
|
|
|
fn get_sysroot(&self) -> Option<String> {
|
|
let mut sysroot_cmd = self.prepare_command("rustc");
|
|
sysroot_cmd.args(&["-q", "--", "--print", "sysroot"]);
|
|
sysroot_cmd.output().ok().and_then(|o| String::from_utf8(o.stdout).ok())
|
|
}
|
|
|
|
fn get_toolchain(&self) -> Option<String> {
|
|
let sysroot = self.get_sysroot()?;
|
|
Path::new(sysroot.trim())
|
|
.file_name()
|
|
.and_then(|s| s.to_str())
|
|
.map(|s| s.to_string())
|
|
}
|
|
|
|
fn try_build(&self) -> Result<(), Option<String>> {
|
|
let Ok(result) = self.prepare_command("build").output() else { return Err(None) };
|
|
if !result.status.success() {
|
|
return Err(Some(String::from_utf8_lossy(&result.stderr).into()));
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
fn check_wasm_toolchain_installed(
|
|
cargo_command: CargoCommand,
|
|
) -> Result<CargoCommandVersioned, String> {
|
|
let dummy_crate = DummyCrate::new(&cargo_command, RuntimeTarget::Wasm);
|
|
|
|
if let Err(error) = dummy_crate.try_build() {
|
|
let toolchain = dummy_crate.get_toolchain().unwrap_or("<unknown>".to_string());
|
|
let basic_error_message = colorize_error_message(
|
|
&format!("Rust WASM target for toolchain {toolchain} is not properly installed; please install it!")
|
|
);
|
|
return match error {
|
|
None => Err(basic_error_message),
|
|
Some(error) if error.contains("the `wasm32-unknown-unknown` target may not be installed") => {
|
|
Err(colorize_error_message(&format!("Cannot compile the WASM runtime: the `wasm32-unknown-unknown` target is not installed!\n\
|
|
You can install it with `rustup target add wasm32-unknown-unknown --toolchain {toolchain}` if you're using `rustup`.")))
|
|
},
|
|
// Apparently this can happen when we're running on a non Tier 1 platform.
|
|
Some(ref error) if error.contains("linker `rust-lld` not found") =>
|
|
Err(colorize_error_message("Cannot compile the WASM runtime: `rust-lld` not found!")),
|
|
Some(error) => Err(format!(
|
|
"{}\n\n{}\n{}\n{}{}\n",
|
|
basic_error_message,
|
|
colorize_aux_message("Further error information:"),
|
|
colorize_aux_message(&"-".repeat(60)),
|
|
error,
|
|
colorize_aux_message(&"-".repeat(60)),
|
|
))
|
|
}
|
|
}
|
|
|
|
let version = dummy_crate.get_rustc_version();
|
|
if crate::build_std_required() {
|
|
if let Some(sysroot) = dummy_crate.get_sysroot() {
|
|
let src_path =
|
|
Path::new(sysroot.trim()).join("lib").join("rustlib").join("src").join("rust");
|
|
if !src_path.exists() {
|
|
let toolchain = dummy_crate.get_toolchain().unwrap_or("<toolchain>".to_string());
|
|
return Err(colorize_error_message(
|
|
&format!("Cannot compile the WASM runtime: no standard library sources found at {}!\n\
|
|
You can install them with `rustup component add rust-src --toolchain {toolchain}` if you're using `rustup`.", src_path.display()),
|
|
))
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(CargoCommandVersioned::new(cargo_command, version))
|
|
}
|