Skip to content

Commit

Permalink
wasm-builder: Use the custom target riscv32emac-unknown-none-polkavm
Browse files Browse the repository at this point in the history
Signed-off-by: Jarkko Sakkinen <[email protected]>
Signed-off-by: Jarkko Sakkinen <[email protected]>
  • Loading branch information
jarkkojs committed Nov 9, 2024
1 parent edf79aa commit 5199aa3
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 63 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
**/hfuzz_target/
**/hfuzz_workspace/
**/node_modules
**/rusty-tags.vi
**/target/
**/wip/*.stderr
**/__pycache__/
Expand Down
12 changes: 12 additions & 0 deletions prdoc/pr_6419.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json

title: Use the custom target riscv32emac-unknown-none-polkavm
doc:
- audience: Runtime Dev
description: |
Closes: https://github.com/paritytech/polkadot-sdk/issues/6335

crates:
- name: substrate-wasm-builder
bump: patch
1 change: 1 addition & 0 deletions substrate/utils/wasm-builder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ edition.workspace = true
repository.workspace = true
license = "Apache-2.0"
homepage.workspace = true
rust-version = "1.84"

[lints]
workspace = true
Expand Down
10 changes: 10 additions & 0 deletions substrate/utils/wasm-builder/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: Apache-2.0

use std::process::Command;

fn main() {
Command::new("rustup")
.args(["override", "set", "nightly-2024-11-01"]).output().expect("rustup");

println!("cargo::rerun-if-changed=build.rs");
}
26 changes: 26 additions & 0 deletions substrate/utils/wasm-builder/riscv32emac-unknown-none-polkavm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"arch": "riscv32",
"cpu": "generic-rv32",
"crt-objects-fallback": "false",
"data-layout": "e-m:e-p:32:32-i64:64-n32-S32",
"eh-frame-header": false,
"emit-debug-gdb-scripts": false,
"features": "+e,+m,+a,+c,+lui-addi-fusion,+xtheadcondmov",
"linker": "rust-lld",
"linker-flavor": "ld.lld",
"llvm-abiname": "ilp32e",
"llvm-target": "riscv32",
"max-atomic-width": 32,
"panic-strategy": "abort",
"relocation-model": "pie",
"target-pointer-width": "32",
"singlethread": true,
"pre-link-args": {
"ld": [
"--emit-relocs",
"--unique",
"--relocatable"
]
},
"env": "polkavm"
}
2 changes: 2 additions & 0 deletions substrate/utils/wasm-builder/rust-toolchain.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[toolchain]
channel = "nightly-2024-11-01"
8 changes: 7 additions & 1 deletion substrate/utils/wasm-builder/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,13 @@ impl WasmBuilder {

/// Build the WASM binary.
pub fn build(mut self) {
let target = crate::runtime_target();
let Some(target) = RuntimeTarget::new() else {
build_helper::warning!(
"RUNTIME_TARGET environment variable must be set to either \"wasm\" or \"riscv\""
);
std::process::exit(1);
};

if target == RuntimeTarget::Wasm {
if self.export_heap_base {
self.rust_flags.push("-Clink-arg=--export=__heap_base".into());
Expand Down
79 changes: 24 additions & 55 deletions substrate/utils/wasm-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@
//! wasm32-unknown-unknown --toolchain nightly-2020-02-20`.

use std::{
collections::BTreeSet,
env, fs,
io::BufRead,
path::{Path, PathBuf},
Expand Down Expand Up @@ -254,26 +253,22 @@ struct CargoCommand {
program: String,
args: Vec<String>,
version: Option<Version>,
target_list: Option<BTreeSet<String>>,
}

impl CargoCommand {
fn new(program: &str) -> Self {
let version = Self::extract_version(program, &[]);
let target_list = Self::extract_target_list(program, &[]);

CargoCommand { program: program.into(), args: Vec::new(), version, target_list }
CargoCommand { program: program.into(), args: Vec::new(), version }
}

fn new_with_args(program: &str, args: &[&str]) -> Self {
let version = Self::extract_version(program, args);
let target_list = Self::extract_target_list(program, args);

CargoCommand {
program: program.into(),
args: args.iter().map(ToString::to_string).collect(),
version,
target_list,
}
}

Expand All @@ -294,23 +289,6 @@ impl CargoCommand {
Version::extract(&version)
}

fn extract_target_list(program: &str, args: &[&str]) -> Option<BTreeSet<String>> {
// This is technically an unstable option, but we don't care because we only need this
// to build RISC-V runtimes, and those currently require a specific nightly toolchain
// anyway, so it's totally fine for this to fail in other cases.
let list = Command::new(program)
.args(args)
.args(&["rustc", "-Z", "unstable-options", "--print", "target-list"])
// Make sure if we're called from within a `build.rs` the host toolchain won't override
// a rustup toolchain we've picked.
.env_remove("RUSTC")
.output()
.ok()
.and_then(|o| String::from_utf8(o.stdout).ok())?;

Some(list.trim().split("\n").map(ToString::to_string).collect())
}

/// Returns the version of this cargo command or `None` if it failed to extract the version.
fn version(&self) -> Option<Version> {
self.version
Expand All @@ -326,19 +304,10 @@ impl CargoCommand {
fn supports_substrate_runtime_env(&self, target: RuntimeTarget) -> bool {
match target {
RuntimeTarget::Wasm => self.supports_substrate_runtime_env_wasm(),
RuntimeTarget::Riscv => self.supports_substrate_runtime_env_riscv(),
RuntimeTarget::Riscv => true,
}
}

/// Check if the supplied cargo command supports our RISC-V runtime environment.
fn supports_substrate_runtime_env_riscv(&self) -> bool {
let Some(target_list) = self.target_list.as_ref() else { return false };
// This is our custom target which currently doesn't exist on any upstream toolchain,
// so if it exists it's guaranteed to be our custom toolchain and have have everything
// we need, so any further version checks are unnecessary at this point.
target_list.contains("riscv32ema-unknown-none-elf")
}

/// Check if the supplied cargo command supports our Substrate wasm environment.
///
/// This means that either the cargo version is at minimum 1.68.0 or this is a nightly cargo.
Expand Down Expand Up @@ -411,7 +380,7 @@ fn get_bool_environment_variable(name: &str) -> Option<bool> {

/// Returns whether we need to also compile the standard library when compiling the runtime.
fn build_std_required() -> bool {
let default = runtime_target() == RuntimeTarget::Wasm;
let default = RuntimeTarget::new() != None;

crate::get_bool_environment_variable(crate::WASM_BUILD_STD).unwrap_or(default)
}
Expand All @@ -423,13 +392,30 @@ enum RuntimeTarget {
}

impl RuntimeTarget {
fn rustc_target(self) -> &'static str {
match self {
RuntimeTarget::Wasm => "wasm32-unknown-unknown",
RuntimeTarget::Riscv => "riscv32ema-unknown-none-elf",
/// Creates a new instance.
fn new() -> Option<Self> {
let Some(value) = env::var_os(RUNTIME_TARGET) else {
return Some(Self::Wasm);
};
if value == "wasm" {
Some(Self::Wasm)
} else if value == "riscv" {
Some(Self::Riscv)
} else {
None
}
}

/// Figures out the target parameter value for rustc. For the PolkaVM custom targets, apply the
/// full path to the JSON file.
fn value(self) -> String {
if self == RuntimeTarget::Wasm {
return "wasm32-unknown-unknown".to_string();
}
let path: &'static str = env!("CARGO_MANIFEST_DIR");
format!("{path}/riscv32emac-unknown-none-polkavm.json")
}

fn build_subdirectory(self) -> &'static str {
// Keep the build directories separate so that when switching between
// the targets we won't trigger unnecessary rebuilds.
Expand All @@ -439,20 +425,3 @@ impl RuntimeTarget {
}
}
}

fn runtime_target() -> RuntimeTarget {
let Some(value) = env::var_os(RUNTIME_TARGET) else {
return RuntimeTarget::Wasm;
};

if value == "wasm" {
RuntimeTarget::Wasm
} else if value == "riscv" {
RuntimeTarget::Riscv
} else {
build_helper::warning!(
"the '{RUNTIME_TARGET}' environment variable has an invalid value; it must be either 'wasm' or 'riscv'"
);
std::process::exit(1);
}
}
2 changes: 1 addition & 1 deletion substrate/utils/wasm-builder/src/prerequisites.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ impl<'a> DummyCrate<'a> {
// by accident - it can happen in some CI environments.
cmd.current_dir(&self.temp);
cmd.arg(subcommand)
.arg(format!("--target={}", self.target.rustc_target()))
.arg(format!("--target={}", self.target.value()))
.args(&["--manifest-path", &self.manifest_path.display().to_string()]);

if super::color_output_enabled() {
Expand Down
13 changes: 7 additions & 6 deletions substrate/utils/wasm-builder/src/wasm_project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,7 @@ fn build_bloaty_blob(

build_cmd
.arg("rustc")
.arg(format!("--target={}", target.rustc_target()))
.arg(format!("--target={}", target.value()))
.arg(format!("--manifest-path={}", manifest_path.display()))
.env("RUSTFLAGS", rustflags)
// Manually set the `CARGO_TARGET_DIR` to prevent a cargo deadlock (cargo locks a target dir
Expand Down Expand Up @@ -910,7 +910,10 @@ fn build_bloaty_blob(
if crate::build_std_required() {
// Unfortunately this is still a nightly-only flag, but FWIW it is pretty widely used
// so it's unlikely to break without a replacement.
build_cmd.arg("-Z").arg("build-std");
match target {
RuntimeTarget::Wasm => build_cmd.arg("-Z").arg("build-std"),
RuntimeTarget::Riscv => build_cmd.arg("-Z").arg("build-std=core,alloc")
};
if !cargo_cmd.supports_nightly_features() {
build_cmd.env("RUSTC_BOOTSTRAP", "1");
}
Expand All @@ -932,10 +935,8 @@ fn build_bloaty_blob(
}

let blob_name = get_blob_name(target, &manifest_path);
let target_directory = project
.join("target")
.join(target.rustc_target())
.join(blob_build_profile.directory());
let target_directory =
project.join("target").join(target.value()).join(blob_build_profile.directory());
match target {
RuntimeTarget::Riscv => {
let elf_path = target_directory.join(&blob_name);
Expand Down

0 comments on commit 5199aa3

Please sign in to comment.