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

wasm-builder: Use riscv32emac-unknown-none-polkavm.json target #6419

Merged
merged 41 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
d65bc32
wasm-builder: Use the custom target riscv32emac-unknown-none-polkavm
jarkkojs Nov 13, 2024
20c0928
Merge branch 'master' into wasm-builder-riscv32emac
athei Nov 13, 2024
bf56307
Update substrate/utils/wasm-builder/src/lib.rs
jarkkojs Nov 14, 2024
d47fe33
wasm-builder: fixup names in RustTarget
jarkkojs Nov 14, 2024
33075a4
wasm-build: RuntimeTarget fixups
jarkkojs Nov 14, 2024
15c9cce
wasm-builder: remove extra riscv rustc parameters
jarkkojs Nov 14, 2024
a2d7364
Merge branch 'master' into wasm-builder-riscv32emac
jarkkojs Nov 14, 2024
f4ae692
Bump polkavm version
jarkkojs Nov 14, 2024
71e3b92
Update Cargo.lock
jarkkojs Nov 14, 2024
e7334e1
Fix: Use std::io::Read trait to serialize the program
jarkkojs Nov 14, 2024
8fcdcbb
Remove std::io::Read import
jarkkojs Nov 14, 2024
fc9b2a2
Merge branch 'master' into wasm-builder-riscv32emac
jarkkojs Nov 14, 2024
57076cc
Merge branch 'master' into wasm-builder-riscv32emac
jarkkojs Nov 15, 2024
58f624e
Bump polkavm version
jarkkojs Nov 18, 2024
b762ac0
Update Cargo.toml
jarkkojs Nov 19, 2024
1816669
Merge branch 'master' into wasm-builder-riscv32emac
jarkkojs Nov 21, 2024
8104f30
wasm-builder: Use polkavm_linker::target_json_32_path()
jarkkojs Nov 21, 2024
68024f7
Update substrate/utils/wasm-builder/src/lib.rs
jarkkojs Nov 22, 2024
9452b55
Merge branch 'master' into wasm-builder-riscv32emac
jarkkojs Nov 22, 2024
4dd8d28
wasm-builder: Introduce fn `rustc_target_build_std()`
jarkkojs Nov 22, 2024
2b23009
wasm-builder: Fixup fn `rustc_target_build_std()`
jarkkojs Nov 22, 2024
f70c8dd
Merge branch 'master' into wasm-builder-riscv32emac
jarkkojs Nov 22, 2024
75a1650
Merge branch 'master' into wasm-builder-riscv32emac
jarkkojs Nov 25, 2024
3153d5a
wasm-builder: Remove spurious target json
jarkkojs Nov 25, 2024
0df733c
wasm-builder: Fix error handling in RuntimeTarget::new()
jarkkojs Nov 25, 2024
ba2da57
Merge branch 'master' into wasm-builder-riscv32emac
jarkkojs Nov 25, 2024
5ca710d
wasm-builder: fixup assert
jarkkojs Nov 25, 2024
8a4524e
Merge branch 'master' into wasm-builder-riscv32emac
jarkkojs Nov 25, 2024
5359e3e
Merge remote-tracking branch 'upstream/master' into wasm-builder-risc…
jarkkojs Nov 30, 2024
588458a
Merge branch 'master' into wasm-builder-riscv32emac
jarkkojs Dec 3, 2024
5bf5bf4
Update substrate/utils/wasm-builder/src/prerequisites.rs
jarkkojs Dec 3, 2024
334b78d
Merge branch 'master' into wasm-builder-riscv32emac
jarkkojs Dec 3, 2024
a23fa4e
Merge branch 'master' into wasm-builder-riscv32emac
jarkkojs Dec 3, 2024
455de15
Merge branch 'master' into wasm-builder-riscv32emac
jarkkojs Dec 3, 2024
c657d3c
Fix Cargo.lock
jarkkojs Dec 3, 2024
4058b0e
Bump polkavm-linker version
jarkkojs Dec 4, 2024
591e288
Bump polkavm-linker version
jarkkojs Dec 4, 2024
8d23a9a
Merge branch 'master' into wasm-builder-riscv32emac
jarkkojs Dec 4, 2024
beca7d7
Merge branch 'master' into wasm-builder-riscv32emac
jarkkojs Dec 4, 2024
2848a3d
Merge branch 'master' into wasm-builder-riscv32emac
jarkkojs Dec 4, 2024
2bcd113
Merge branch 'master' into wasm-builder-riscv32emac
jarkkojs Dec 4, 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
12 changes: 6 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1090,8 +1090,8 @@ polkadot-test-client = { path = "polkadot/node/test/client" }
polkadot-test-runtime = { path = "polkadot/runtime/test-runtime" }
polkadot-test-service = { path = "polkadot/node/test/service" }
polkavm = { version = "0.9.3", default-features = false }
polkavm-derive = "0.9.1"
polkavm-linker = "0.9.2"
polkavm-derive = "0.17.0"
polkavm-linker = "0.17.1"
portpicker = { version = "0.1.1" }
pretty_assertions = { version = "1.3.0" }
primitive-types = { version = "0.13.1", default-features = false, features = [
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
3 changes: 2 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,8 @@ impl WasmBuilder {

/// Build the WASM binary.
pub fn build(mut self) {
let target = crate::runtime_target();
let target = RuntimeTarget::new();

if target == RuntimeTarget::Wasm {
if self.export_heap_base {
self.rust_flags.push("-Clink-arg=--export=__heap_base".into());
Expand Down
105 changes: 43 additions & 62 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 @@ -409,50 +378,62 @@ 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;

crate::get_bool_environment_variable(crate::WASM_BUILD_STD).unwrap_or(default)
}

#[derive(Copy, Clone, PartialEq, Eq)]
enum RuntimeTarget {
Wasm,
Riscv,
}

impl RuntimeTarget {
fn rustc_target(self) -> &'static str {
/// Creates a new instance.
fn new() -> Self {
let Some(value) = env::var_os(RUNTIME_TARGET) else {
return Self::Wasm;
};

if value == "wasm" {
Self::Wasm
} else if value == "riscv" {
Self::Riscv
} else {
build_helper::warning!(
"RUNTIME_TARGET environment variable must be set to either \"wasm\" or \"riscv\""
);
std::process::exit(1);
}
}

/// Figures out the target parameter value for rustc.
fn rustc_target(self) -> String {
match self {
RuntimeTarget::Wasm => "wasm32-unknown-unknown",
RuntimeTarget::Riscv => "riscv32ema-unknown-none-elf",
RuntimeTarget::Wasm => "wasm32-unknown-unknown".to_string(),
RuntimeTarget::Riscv => {
let path = polkavm_linker::target_json_32_path().expect("riscv not found");
path.into_os_string().into_string().unwrap()
},
}
}

fn build_subdirectory(self) -> &'static str {
// Keep the build directories separate so that when switching between
// the targets we won't trigger unnecessary rebuilds.
/// Figures out the target directory name used by cargo.
fn rustc_target_dir(self) -> &'static str {
match self {
RuntimeTarget::Wasm => "wbuild",
RuntimeTarget::Riscv => "rbuild",
RuntimeTarget::Wasm => "wasm32-unknown-unknown",
RuntimeTarget::Riscv => "riscv32emac-unknown-none-polkavm",
}
}
}

fn runtime_target() -> RuntimeTarget {
let Some(value) = env::var_os(RUNTIME_TARGET) else {
return RuntimeTarget::Wasm;
};
/// Figures out the build-std argument.
fn rustc_target_build_std(self) -> Option<&'static str> {
if !crate::get_bool_environment_variable(crate::WASM_BUILD_STD).unwrap_or(true) {
return None;
}

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);
// This is a nightly-only flag.
let arg = match self {
RuntimeTarget::Wasm => "build-std",
RuntimeTarget::Riscv => "build-std=core,alloc",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bkchr @jarkkojs What is the point of doing -Zbuild-std for target riscv32emac-unknown-none-polkavm? It increases runtime build time for non-wasm targets.

Copy link
Member

@athei athei Dec 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is required for both targets but for different reasons:

wasm: The rustup provided standard library is compiled with wasm extensions enabled we dont support. Hence we need to recompile it.

riscv: Rustup doesn't contain any prebuilt binaries for this target. Hence we need to build it ourselves.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, so I guessed, i.e. it should be official target in rustc upstream to have prebuilt binaries, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[not actually at work yet, my keyboard just writes by itself]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@athei Thanks for the clarification! I think Parity could add to the pre-compiled libraries to riscv32emac-unknown-none-polkavm target in rlib format like the wasm32-unknown-unknown target does (located in ./lib/rustlib/wasm32-unknown-unknown/lib/libcore-192e883b194683b6.rlib).

};

Some(arg)
}
}
7 changes: 5 additions & 2 deletions substrate/utils/wasm-builder/src/prerequisites.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,14 @@ fn check_wasm_toolchain_installed(
error,
colorize_aux_message(&"-".repeat(60)),
))
}
};
}

let version = dummy_crate.get_rustc_version();
if crate::build_std_required() {

let target = RuntimeTarget::new();
assert!(target == RuntimeTarget::Wasm);
jarkkojs marked this conversation as resolved.
Show resolved Hide resolved
if target.rustc_target_build_std().is_some() {
if let Some(sysroot) = dummy_crate.get_sysroot() {
let src_path =
Path::new(sysroot.trim()).join("lib").join("rustlib").join("src").join("rust");
Expand Down
28 changes: 17 additions & 11 deletions substrate/utils/wasm-builder/src/wasm_project.rs
athei marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,15 @@ fn crate_metadata(cargo_manifest: &Path) -> Metadata {
crate_metadata
}

/// Keep the build directories separate so that when switching between the
/// targets we won't trigger unnecessary rebuilds.
fn build_subdirectory(target: RuntimeTarget) -> &'static str {
jarkkojs marked this conversation as resolved.
Show resolved Hide resolved
match target {
RuntimeTarget::Wasm => "wbuild",
RuntimeTarget::Riscv => "rbuild",
}
}

/// Creates the WASM project, compiles the WASM binary and compacts the WASM binary.
///
/// # Returns
Expand All @@ -125,7 +134,7 @@ pub(crate) fn create_and_compile(
#[cfg(feature = "metadata-hash")] enable_metadata_hash: Option<MetadataExtraInfo>,
) -> (Option<WasmBinary>, WasmBinaryBloaty) {
let runtime_workspace_root = get_wasm_workspace_root();
let runtime_workspace = runtime_workspace_root.join(target.build_subdirectory());
let runtime_workspace = runtime_workspace_root.join(build_subdirectory(target));

let crate_metadata = crate_metadata(orig_project_cargo_toml);

Expand Down Expand Up @@ -770,7 +779,7 @@ impl BuildConfiguration {
.collect::<Vec<_>>()
.iter()
.rev()
.take_while(|c| c.as_os_str() != target.build_subdirectory())
.take_while(|c| c.as_os_str() != build_subdirectory(target))
.last()
.expect("We put the runtime project within a `target/.../[rw]build` path; qed")
.as_os_str()
Expand Down Expand Up @@ -841,9 +850,7 @@ fn build_bloaty_blob(
"-C target-cpu=mvp -C target-feature=-sign-ext -C link-arg=--export-table ",
);
},
RuntimeTarget::Riscv => {
rustflags.push_str("-C target-feature=+lui-addi-fusion -C relocation-model=pie -C link-arg=--emit-relocs -C link-arg=--unique ");
},
RuntimeTarget::Riscv => (),
jarkkojs marked this conversation as resolved.
Show resolved Hide resolved
}

rustflags.push_str(default_rustflags);
Expand Down Expand Up @@ -907,10 +914,9 @@ fn build_bloaty_blob(
//
// So here we force the compiler to also compile the standard library crates for us
// to make sure that they also only use the MVP features.
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");
if let Some(arg) = target.rustc_target_build_std() {
build_cmd.arg("-Z").arg(arg);

if !cargo_cmd.supports_nightly_features() {
build_cmd.env("RUSTC_BOOTSTRAP", "1");
}
Expand All @@ -934,7 +940,7 @@ fn build_bloaty_blob(
let blob_name = get_blob_name(target, &manifest_path);
let target_directory = project
.join("target")
.join(target.rustc_target())
.join(target.rustc_target_dir())
.join(blob_build_profile.directory());
match target {
RuntimeTarget::Riscv => {
Expand Down Expand Up @@ -968,7 +974,7 @@ fn build_bloaty_blob(
},
};

std::fs::write(&polkavm_path, program.as_bytes())
std::fs::write(&polkavm_path, program)
.expect("writing the blob to a file always works");
}

Expand Down
Loading