Add production profile to substrate-wasm-builder (#10747)

* Add production profile to wasm builder

* Fix profile detection

* Apply suggestions from code review

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Replace panic! by println! + exit

* Default to `release` for wasm on debug builds

* Replaced unwrap by expect

* Update all weights

Rerun on the bm2 server.

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* cargo run --quiet --profile=production  --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_contracts --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/contracts/src/weights.rs --template=./.maintain/frame-weight-template.hbs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: Parity Bot <admin@parity.io>
This commit is contained in:
Alexander Theißen
2022-01-31 15:16:26 +01:00
committed by GitHub
parent 21d5573b25
commit f3168c3fa0
35 changed files with 1943 additions and 1833 deletions
+118 -33
View File
@@ -17,6 +17,8 @@
use crate::{write_file_if_changed, CargoCommandVersioned};
use build_helper::rerun_if_changed;
use cargo_metadata::{CargoOpt, Metadata, MetadataCommand};
use std::{
borrow::ToOwned,
collections::HashSet,
@@ -26,13 +28,8 @@ use std::{
path::{Path, PathBuf},
process,
};
use strum::{EnumIter, IntoEnumIterator};
use toml::value::Table;
use build_helper::rerun_if_changed;
use cargo_metadata::{CargoOpt, Metadata, MetadataCommand};
use walkdir::WalkDir;
/// Colorize an info message.
@@ -128,9 +125,9 @@ pub(crate) fn create_and_compile(
features_to_enable,
);
build_project(&project, default_rustflags, cargo_cmd);
let profile = build_project(&project, default_rustflags, cargo_cmd);
let (wasm_binary, wasm_binary_compressed, bloaty) =
compact_wasm_file(&project, project_cargo_toml, wasm_binary_name);
compact_wasm_file(&project, profile, project_cargo_toml, wasm_binary_name);
wasm_binary
.as_ref()
@@ -246,16 +243,22 @@ fn create_project_cargo_toml(
let mut wasm_workspace_toml = Table::new();
// Add `profile` with release and dev
// Add different profiles which are selected by setting `WASM_BUILD_TYPE`.
let mut release_profile = Table::new();
release_profile.insert("panic".into(), "abort".into());
release_profile.insert("lto".into(), true.into());
release_profile.insert("lto".into(), "thin".into());
let mut production_profile = Table::new();
production_profile.insert("inherits".into(), "release".into());
production_profile.insert("lto".into(), "fat".into());
production_profile.insert("codegen-units".into(), 1.into());
let mut dev_profile = Table::new();
dev_profile.insert("panic".into(), "abort".into());
let mut profile = Table::new();
profile.insert("release".into(), release_profile.into());
profile.insert("production".into(), production_profile.into());
profile.insert("dev".into(), dev_profile.into());
wasm_workspace_toml.insert("profile".into(), profile.into());
@@ -420,25 +423,106 @@ fn create_project(
wasm_project_folder
}
/// Returns if the project should be built as a release.
fn is_release_build() -> bool {
if let Ok(var) = env::var(crate::WASM_BUILD_TYPE_ENV) {
match var.as_str() {
"release" => true,
"debug" => false,
var => panic!(
"Unexpected value for `{}` env variable: {}\nOne of the following are expected: `debug` or `release`.",
crate::WASM_BUILD_TYPE_ENV,
var,
),
/// The cargo profile that is used to build the wasm project.
#[derive(Debug, EnumIter)]
enum Profile {
/// The `--profile dev` profile.
Debug,
/// The `--profile release` profile.
Release,
/// The `--profile production` profile.
Production,
}
impl Profile {
/// Create a profile by detecting which profile is used for the main build.
///
/// We cannot easily determine the profile that is used by the main cargo invocation
/// because the `PROFILE` environment variable won't contain any custom profiles like
/// "production". It would only contain the builtin profile where the custom profile
/// inherits from. This is why we inspect the build path to learn which profile is used.
///
/// # Note
///
/// Can be overriden by setting [`crate::WASM_BUILD_TYPE_ENV`].
fn detect(wasm_project: &Path) -> Profile {
let (name, overriden) = if let Ok(name) = env::var(crate::WASM_BUILD_TYPE_ENV) {
(name, true)
} else {
// First go backwards to the beginning of the target directory.
// Then go forwards to find the "wbuild" directory.
// We need to go backwards first because when starting from the root there
// might be a chance that someone has a "wbuild" directory somewhere in the path.
let name = wasm_project
.components()
.rev()
.take_while(|c| c.as_os_str() != "target")
.collect::<Vec<_>>()
.iter()
.rev()
.take_while(|c| c.as_os_str() != "wbuild")
.last()
.expect("We put the wasm project within a `target/.../wbuild` path; qed")
.as_os_str()
.to_str()
.expect("All our profile directory names are ascii; qed")
.to_string();
(name, false)
};
match (Profile::iter().find(|p| p.directory() == name), overriden) {
// When not overriden by a env variable we default to using the `Release` profile
// for the wasm build even when the main build uses the debug build. This
// is because the `Debug` profile is too slow for normal development activities.
(Some(Profile::Debug), false) => Profile::Release,
// For any other profile or when overriden we take it at face value.
(Some(profile), _) => profile,
// Invalid profile specified.
(None, _) => {
// We use println! + exit instead of a panic in order to have a cleaner output.
println!(
"Unexpected profile name: `{}`. One of the following is expected: {:?}",
name,
Profile::iter().map(|p| p.directory()).collect::<Vec<_>>(),
);
process::exit(1);
},
}
} else {
true
}
/// The name of the profile as supplied to the cargo `--profile` cli option.
fn name(&self) -> &'static str {
match self {
Self::Debug => "dev",
Self::Release => "release",
Self::Production => "production",
}
}
/// The sub directory within `target` where cargo places the build output.
///
/// # Note
///
/// Usually this is the same as [`Self::name`] with the exception of the debug
/// profile which is called `dev`.
fn directory(&self) -> &'static str {
match self {
Self::Debug => "debug",
_ => self.name(),
}
}
/// Whether the resulting binary should be compacted and compressed.
fn wants_compact(&self) -> bool {
!matches!(self, Self::Debug)
}
}
/// Build the project to create the WASM binary.
fn build_project(project: &Path, default_rustflags: &str, cargo_cmd: CargoCommandVersioned) {
fn build_project(
project: &Path,
default_rustflags: &str,
cargo_cmd: CargoCommandVersioned,
) -> Profile {
let manifest_path = project.join("Cargo.toml");
let mut build_cmd = cargo_cmd.command();
@@ -467,16 +551,16 @@ fn build_project(project: &Path, default_rustflags: &str, cargo_cmd: CargoComman
build_cmd.arg("--color=always");
}
if is_release_build() {
build_cmd.arg("--release");
};
let profile = Profile::detect(project);
build_cmd.arg("--profile");
build_cmd.arg(profile.name());
println!("{}", colorize_info_message("Information that should be included in a bug report."));
println!("{} {:?}", colorize_info_message("Executing build command:"), build_cmd);
println!("{} {}", colorize_info_message("Using rustc version:"), cargo_cmd.rustc_version());
match build_cmd.status().map(|s| s.success()) {
Ok(true) => {},
Ok(true) => profile,
// Use `process.exit(1)` to have a clean error output.
_ => process::exit(1),
}
@@ -485,18 +569,17 @@ fn build_project(project: &Path, default_rustflags: &str, cargo_cmd: CargoComman
/// Compact the WASM binary using `wasm-gc` and compress it using zstd.
fn compact_wasm_file(
project: &Path,
profile: Profile,
cargo_manifest: &Path,
wasm_binary_name: Option<String>,
) -> (Option<WasmBinary>, Option<WasmBinary>, WasmBinaryBloaty) {
let is_release_build = is_release_build();
let target = if is_release_build { "release" } else { "debug" };
let default_wasm_binary_name = get_wasm_binary_name(cargo_manifest);
let wasm_file = project
.join("target/wasm32-unknown-unknown")
.join(target)
.join(profile.directory())
.join(format!("{}.wasm", default_wasm_binary_name));
let wasm_compact_file = if is_release_build {
let wasm_compact_file = if profile.wants_compact() {
let wasm_compact_file = project.join(format!(
"{}.compact.wasm",
wasm_binary_name.clone().unwrap_or_else(|| default_wasm_binary_name.clone()),
@@ -687,11 +770,13 @@ fn copy_wasm_to_target_directory(cargo_manifest: &Path, wasm_binary: &WasmBinary
};
if !target_dir.is_absolute() {
panic!(
// We use println! + exit instead of a panic in order to have a cleaner output.
println!(
"Environment variable `{}` with `{}` is not an absolute path!",
crate::WASM_TARGET_DIRECTORY,
target_dir.display(),
);
process::exit(1);
}
fs::create_dir_all(&target_dir).expect("Creates `WASM_TARGET_DIRECTORY`.");