Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Add production profile to substrate-wasm-builder #10747

Merged
merged 9 commits into from
Jan 31, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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: 13 additions & 3 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions utils/wasm-builder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ walkdir = "2.3.2"
wasm-gc-api = "0.1.11"
ansi_term = "0.12.1"
sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../primitives/maybe-compressed-blob" }
strum = { version = "0.23.0", features = ["derive"] }
2 changes: 1 addition & 1 deletion utils/wasm-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ pub use builder::{WasmBuilder, WasmBuilderSelectProject};
const SKIP_BUILD_ENV: &str = "SKIP_WASM_BUILD";

/// Environment variable to force a certain build type when building the wasm binary.
/// Expects "debug" or "release" as value.
/// Expects "debug", "release" or "production" as value.
///
/// By default the WASM binary uses the same build type as the main cargo build.
const WASM_BUILD_TYPE_ENV: &str = "WASM_BUILD_TYPE";
Expand Down
136 changes: 104 additions & 32 deletions utils/wasm-builder/src/wasm_project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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.
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -420,25 +423,95 @@ 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 = if let Ok(name) = env::var(crate::WASM_BUILD_TYPE_ENV) {
name
} 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.
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()
.unwrap()
.as_os_str()
.to_str()
.unwrap()
athei marked this conversation as resolved.
Show resolved Hide resolved
.to_string()
};
if let Some(profile) = Profile::iter().find(|p| p.directory() == name) {
return profile
}
} else {
true
panic!(
athei marked this conversation as resolved.
Show resolved Hide resolved
"Unexpected profile name: `{}`. One of the following is expected: {:?}",
name,
Profile::iter().map(|p| p.directory()).collect::<Vec<_>>(),
);
}

/// 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();

Expand Down Expand Up @@ -467,16 +540,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);
athei marked this conversation as resolved.
Show resolved Hide resolved
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),
}
Expand All @@ -485,18 +558,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()),
Expand Down