diff --git a/Cargo.lock b/Cargo.lock index 78eb0953be..b1e7f048e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1393,7 +1393,7 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.87", ] [[package]] @@ -3880,6 +3880,7 @@ dependencies = [ "serde_json", "sha256", "spinoff", + "strum 0.25.0", "wasm-opt", ] diff --git a/crates/iroha_wasm_builder/Cargo.toml b/crates/iroha_wasm_builder/Cargo.toml index 990a2ff8a9..d8864507d5 100644 --- a/crates/iroha_wasm_builder/Cargo.toml +++ b/crates/iroha_wasm_builder/Cargo.toml @@ -16,6 +16,7 @@ eyre = { workspace = true } serde_json = { workspace = true, features = ["std"] } sha256 = "1.5.0" path-absolutize = { workspace = true } +strum = { workspace = true, features = ["derive", "std"] } wasm-opt = "0.116.1" clap = { workspace = true, features = ["derive"] } diff --git a/crates/iroha_wasm_builder/src/lib.rs b/crates/iroha_wasm_builder/src/lib.rs index 84c2cca9c2..e4da047254 100644 --- a/crates/iroha_wasm_builder/src/lib.rs +++ b/crates/iroha_wasm_builder/src/lib.rs @@ -15,7 +15,24 @@ use path_absolutize::Absolutize; /// Current toolchain used to build smartcontracts const TOOLCHAIN: &str = "+nightly-2024-09-09"; -const OPTIMIZED_PROFILE: &str = "deploy"; + +/// Build profile for smartcontracts +#[derive(Debug, Copy, Clone, Eq, PartialEq, strum::Display, strum::EnumString, Default)] +#[strum(serialize_all = "snake_case")] +pub enum Profile { + /// Applies release optimization + #[default] + Release, + /// Applies release and size optimizations + Deploy, +} + +impl Profile { + /// Checks whether profile uses optimizations from wasm-opt + pub fn is_optimized(profile: Self) -> bool { + return profile == Profile::Deploy; + } +} /// WASM Builder for smartcontracts (e.g. triggers and executors). /// @@ -46,14 +63,14 @@ pub struct Builder<'path, 'out_dir> { /// Flag controlling whether to show output of the build process show_output: bool, /// Build profile - profile: String, + profile: Profile, } impl<'path, 'out_dir> Builder<'path, 'out_dir> { /// Initialize [`Builder`] with path to smartcontract. /// /// `relative_path` should be relative to `CARGO_MANIFEST_DIR`. - pub fn new

(relative_path: &'path P, profile: &str) -> Self + pub fn new

(relative_path: &'path P, profile: Profile) -> Self where P: AsRef + ?Sized, { @@ -61,7 +78,7 @@ impl<'path, 'out_dir> Builder<'path, 'out_dir> { path: relative_path.as_ref(), out_dir: None, show_output: false, - profile: profile.to_string(), + profile: profile, } } @@ -103,6 +120,17 @@ impl<'path, 'out_dir> Builder<'path, 'out_dir> { /// /// Will also return error if ran on workspace and not on the concrete package. pub fn build(self) -> Result { + let optimize = Profile::is_optimized(self.profile); + let output = self.into_internal()?.build()?; + if optimize { + output.optimize() + } else { + Ok(output) + } + } + + #[doc(hidden)] + pub fn build_unoptimized(self) -> Result { self.into_internal()?.build() } @@ -117,7 +145,7 @@ impl<'path, 'out_dir> Builder<'path, 'out_dir> { |out_dir| Ok(Cow::Borrowed(out_dir)), )?, show_output: self.show_output, - profile: self.profile.clone(), + profile: self.profile, }) } @@ -171,7 +199,7 @@ mod internal { pub absolute_path: PathBuf, pub out_dir: Cow<'out_dir, Path>, pub show_output: bool, - pub profile: String, + pub profile: Profile, } impl Builder<'_> { @@ -186,41 +214,16 @@ mod internal { pub fn build(self) -> Result { let absolute_path = self.absolute_path.clone(); - let optimize = self.profile == OPTIMIZED_PROFILE; - let show_output = self.show_output; + let optimize = Profile::is_optimized(self.profile); let output = self.build_smartcontract().wrap_err_with(|| { format!( "Failed to build the smartcontract at path: {}", absolute_path.display() ) })?; - + if optimize { - let sp = if show_output && std::env::var("CI").is_err() { - Some(spinoff::Spinner::new_with_stream( - spinoff::spinners::Binary, - "Optimizing the output", - None, - spinoff::Streams::Stderr, - )) - } else { - None - }; - - match output.optimize() { - Ok(optimized) => { - if let Some(mut sp) = sp { - sp.success("Output is optimized"); - } - Ok(optimized) - } - err => { - if let Some(mut sp) = sp { - sp.fail("Optimization failed"); - } - err - } - } + output.optimize() } else { Ok(output) } @@ -270,7 +273,7 @@ mod internal { let full_out_dir = self .out_dir .join("wasm32-unknown-unknown") - .join(self.profile.clone()); + .join(self.profile.to_string()); let wasm_file = full_out_dir.join(package_name).with_extension("wasm"); let previous_hash = if wasm_file.exists() { diff --git a/crates/iroha_wasm_builder/src/main.rs b/crates/iroha_wasm_builder/src/main.rs index 8585fd140b..f8b6282835 100644 --- a/crates/iroha_wasm_builder/src/main.rs +++ b/crates/iroha_wasm_builder/src/main.rs @@ -4,7 +4,7 @@ use std::path::PathBuf; use clap::{Args, Parser}; use color_eyre::eyre::{eyre, Context}; -use iroha_wasm_builder::Builder; +use iroha_wasm_builder::{Builder, Profile}; use owo_colors::OwoColorize; #[derive(Parser, Debug)] @@ -42,7 +42,8 @@ fn main() -> color_eyre::Result<()> { common: CommonArgs { path }, profile, } => { - let builder = Builder::new(&path, &profile).show_output(); + let profile: Profile = profile.parse().expect("Invalid profile provided"); + let builder = Builder::new(&path, profile).show_output(); builder.check()?; } Cli::Build { @@ -50,16 +51,47 @@ fn main() -> color_eyre::Result<()> { out_file, profile, } => { - let builder = Builder::new(&path, &profile).show_output(); + let profile: Profile = profile.parse().expect("Invalid profile provided"); + let builder = Builder::new(&path, profile).show_output(); let output = { // not showing the spinner here, cargo does a progress bar for us - match builder.build() { + match builder.build_unoptimized() { Ok(output) => output, err => err?, } }; + let output = if Profile::is_optimized(profile) { + let sp = if std::env::var("CI").is_err() { + Some(spinoff::Spinner::new_with_stream( + spinoff::spinners::Binary, + "Optimizing the output", + None, + spinoff::Streams::Stderr, + )) + } else { + None + }; + + match output.optimize() { + Ok(optimized) => { + if let Some(mut sp) = sp { + sp.success("Output is optimized"); + } + optimized + } + err => { + if let Some(mut sp) = sp { + sp.fail("Optimization failed"); + } + err? + } + } + } else { + output + }; + std::fs::copy(output.wasm_file_path(), &out_file).wrap_err_with(|| { eyre!( "Failed to write the resulting file into {}",