diff --git a/.gitignore b/.gitignore index e50fdfaa61..630f52abb6 100644 --- a/.gitignore +++ b/.gitignore @@ -24,7 +24,6 @@ vm/**/Cargo.lock # Others my-vm-tests.sh quick.sh -twiggy* template-test # Zip output with example wasm binaries diff --git a/Cargo.lock b/Cargo.lock index b208119b5d..a2e1cd41fe 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -2138,6 +2138,7 @@ dependencies = [ "tokio", "toml 0.5.11", "wasmparser", + "wasmprinter", "zip", ] @@ -3808,14 +3809,24 @@ checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasmparser" -version = "0.113.1" +version = "0.113.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a128cea7b8516703ab41b10a0b1aa9ba18d0454cd3792341489947ddeee268db" +checksum = "1fd0d44fab0bd78404e352f3399324eef76516a4580b52bc9031c60f064e98f3" dependencies = [ "indexmap 2.0.0", "semver", ] +[[package]] +name = "wasmprinter" +version = "0.2.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6615a5587149e753bf4b93f90fa3c3f41c88597a7a2da72879afcabeda9648f" +dependencies = [ + "anyhow", + "wasmparser", +] + [[package]] name = "web-sys" version = "0.3.64" diff --git a/framework/meta/Cargo.toml b/framework/meta/Cargo.toml index 54c066526a..7ad4357872 100644 --- a/framework/meta/Cargo.toml +++ b/framework/meta/Cargo.toml @@ -44,6 +44,7 @@ lazy_static = "1.4.0" convert_case = "0.6.0" hex = "0.4" wasmparser = "0.113.1" +wasmprinter = "0.2.67" [dependencies.multiversx-sc] version = "=0.43.4" diff --git a/framework/meta/src/cmd/contract/meta_config.rs b/framework/meta/src/cmd/contract/meta_config.rs index 12b983dd5a..992a6a05e8 100644 --- a/framework/meta/src/cmd/contract/meta_config.rs +++ b/framework/meta/src/cmd/contract/meta_config.rs @@ -2,7 +2,7 @@ use std::fs; use multiversx_sc::abi::ContractAbi; -use crate::{cli_args::BuildArgs, tools::post_build::check_tools_installed, CargoTomlContents}; +use crate::{cli_args::BuildArgs, tools::check_tools_installed, CargoTomlContents}; use super::output_contract::{OutputContract, OutputContractGlobalConfig}; diff --git a/framework/meta/src/cmd/contract/output_contract/wasm_build.rs b/framework/meta/src/cmd/contract/output_contract/wasm_build.rs index 901b6ce626..7b61617565 100644 --- a/framework/meta/src/cmd/contract/output_contract/wasm_build.rs +++ b/framework/meta/src/cmd/contract/output_contract/wasm_build.rs @@ -7,7 +7,7 @@ use crate::{ ei::EIVersion, mxsc_file_json::{save_mxsc_file_json, MxscFileJson}, print_util::*, - tools::{self, post_build}, + tools, }; impl OutputContract { @@ -108,7 +108,7 @@ impl OutputContract { let output_wasm_path = format!("{output_path}/{}", self.wasm_output_name(build_args)); print_call_wasm_opt(&output_wasm_path); - post_build::run_wasm_opt(output_wasm_path.as_str()); + tools::run_wasm_opt(output_wasm_path.as_str()); } fn run_wasm2wat(&self, build_args: &BuildArgs, output_path: &str) { @@ -119,7 +119,8 @@ impl OutputContract { let output_wasm_path = format!("{output_path}/{}", self.wasm_output_name(build_args)); let output_wat_path = format!("{output_path}/{}", self.wat_output_name(build_args)); print_call_wasm2wat(&output_wasm_path, &output_wat_path); - post_build::run_wasm2wat(output_wasm_path.as_str(), output_wat_path.as_str()); + tools::wasm_to_wat(output_wasm_path.as_str(), output_wat_path.as_str()) + .expect("could not convert wasm to wat"); } fn extract_imports(&self, build_args: &BuildArgs, output_path: &str) { @@ -136,7 +137,6 @@ impl OutputContract { print_extract_imports(&output_imports_json_path); let import_names = tools::extract_wasm_imports(&output_wasm_path) .expect("error occured while extracting imports from .wasm "); - println!("{import_names:?}"); write_imports_output(output_imports_json_path.as_str(), import_names.as_slice()); validate_ei(&import_names, &self.settings.check_ei); } @@ -173,7 +173,7 @@ impl OutputContract { if build_args.twiggy_top { let output_twiggy_top_path = format!("{output_path}/{}", self.twiggy_top_name(build_args)); - post_build::run_twiggy_top( + tools::twiggy::run_twiggy_top( output_wasm_path.as_str(), output_twiggy_top_path.as_str(), ); @@ -181,7 +181,7 @@ impl OutputContract { if build_args.twiggy_paths { let output_twiggy_paths_path = format!("{output_path}/{}", self.twiggy_paths_name(build_args)); - post_build::run_twiggy_paths( + tools::twiggy::run_twiggy_paths( output_wasm_path.as_str(), output_twiggy_paths_path.as_str(), ); @@ -189,7 +189,7 @@ impl OutputContract { if build_args.twiggy_monos { let output_twiggy_monos_path = format!("{output_path}/{}", self.twiggy_monos_name(build_args)); - post_build::run_twiggy_monos( + tools::twiggy::run_twiggy_monos( output_wasm_path.as_str(), output_twiggy_monos_path.as_str(), ); @@ -197,7 +197,7 @@ impl OutputContract { if build_args.twiggy_dominators { let output_twiggy_dominators_path = format!("{output_path}/{}", self.twiggy_dominators_name(build_args)); - post_build::run_twiggy_dominators( + tools::twiggy::run_twiggy_dominators( output_wasm_path.as_str(), output_twiggy_dominators_path.as_str(), ); diff --git a/framework/meta/src/print_util.rs b/framework/meta/src/print_util.rs index a6e3701946..e6fd7053d1 100644 --- a/framework/meta/src/print_util.rs +++ b/framework/meta/src/print_util.rs @@ -71,7 +71,7 @@ pub fn print_call_wasm_opt(wasm_path: &str) { pub fn print_call_wasm2wat(wasm_path: &str, wat_path: &str) { println!( "{}", - format!("Calling wasm2wat on {wasm_path} -> {wat_path} ...").green(), + format!("Extracting wat from {wasm_path} to {wat_path} ...").green(), ); } diff --git a/framework/meta/src/tools.rs b/framework/meta/src/tools.rs index fce1dc5ad3..c3bd3e6c84 100644 --- a/framework/meta/src/tools.rs +++ b/framework/meta/src/tools.rs @@ -1,6 +1,26 @@ mod git_describe; -pub mod post_build; +pub mod twiggy; mod wasm_imports; +mod wasm_opt; +mod wasm_to_wat; pub use git_describe::git_describe; pub use wasm_imports::extract_wasm_imports; +pub use wasm_opt::run_wasm_opt; +pub use wasm_to_wat::wasm_to_wat; + +use crate::cli_args::BuildArgs; + +pub fn check_tools_installed(build_args: &mut BuildArgs) { + if build_args.wasm_opt && !wasm_opt::is_wasm_opt_installed() { + println!("Warning: {} not installed", wasm_opt::WASM_OPT_NAME); + build_args.wasm_opt = false; + } + if build_args.has_twiggy_call() && !twiggy::is_twiggy_installed() { + println!("Warning: {} not installed", twiggy::TWIGGY_NAME); + build_args.twiggy_top = false; + build_args.twiggy_paths = false; + build_args.twiggy_monos = false; + build_args.twiggy_dominators = false; + } +} diff --git a/framework/meta/src/tools/post_build.rs b/framework/meta/src/tools/post_build.rs deleted file mode 100644 index b07fdf79b7..0000000000 --- a/framework/meta/src/tools/post_build.rs +++ /dev/null @@ -1,105 +0,0 @@ -use std::process::{Command, Stdio}; - -use crate::cli_args::BuildArgs; - -const WASM_OPT_NAME: &str = "wasm-opt"; -const WASM2WAT_NAME: &str = "wasm2wat"; -const TWIGGY_NAME: &str = "twiggy"; - -pub(crate) fn check_tools_installed(build_args: &mut BuildArgs) { - if build_args.wasm_opt && !is_wasm_opt_installed() { - println!("Warning: {WASM_OPT_NAME} not installed"); - build_args.wasm_opt = false; - } - if build_args.wat && !is_wasm2wat_installed() { - println!("Warning: {WASM2WAT_NAME} not installed"); - build_args.wat = false; - } - if build_args.has_twiggy_call() && !is_twiggy_installed() { - println!("Warning: {TWIGGY_NAME} not installed"); - build_args.twiggy_top = false; - build_args.twiggy_paths = false; - build_args.twiggy_monos = false; - build_args.twiggy_dominators = false; - } -} - -fn is_wasm_opt_installed() -> bool { - Command::new(WASM_OPT_NAME) - .args(["--version"]) - .output() - .is_ok() -} - -fn is_wasm2wat_installed() -> bool { - Command::new(WASM2WAT_NAME) - .args(["--version"]) - .output() - .is_ok() -} - -fn is_twiggy_installed() -> bool { - Command::new(TWIGGY_NAME) - .args(["--version"]) - .output() - .is_ok() -} - -pub(crate) fn run_wasm_opt(output_wasm_path: &str) { - let exit_status = Command::new(WASM_OPT_NAME) - .args([output_wasm_path, "-Oz", "--output", output_wasm_path]) - .spawn() - .expect("failed to spawn wasm-opt process") - .wait() - .expect("wasm-opt was not running"); - - assert!(exit_status.success(), "wasm-opt process failed"); -} - -pub(crate) fn run_wasm2wat(output_wasm_path: &str, output_wat_path: &str) { - let exit_status = Command::new(WASM2WAT_NAME) - .args([output_wasm_path, "--output", output_wat_path]) - .spawn() - .expect("failed to spawn wasm2wat process") - .wait() - .expect("wasm2wat was not running"); - - assert!(exit_status.success(), "wasm2wat process failed"); -} - -fn run_with_stdout_file(stdout_file_name: &str, args: I) -where - I: IntoIterator, - S: AsRef, -{ - let stdout_file = std::fs::File::create(stdout_file_name).unwrap(); - let _ = Command::new(TWIGGY_NAME) - .args(args) - .stdout(Stdio::from(stdout_file)) - .spawn() - .expect("failed to spawn twiggy process") - .wait() - .expect("twiggy was not running"); -} - -pub(crate) fn run_twiggy_top(output_wasm_path: &str, output_twiggy_top_path: &str) { - run_with_stdout_file( - output_twiggy_top_path, - ["top", "-n", "1000", output_wasm_path], - ); -} - -pub(crate) fn run_twiggy_paths(output_wasm_path: &str, output_twiggy_paths_path: &str) { - run_with_stdout_file(output_twiggy_paths_path, ["paths", output_wasm_path]); -} - -pub(crate) fn run_twiggy_monos(output_wasm_path: &str, output_twiggy_monos_path: &str) { - run_with_stdout_file(output_twiggy_monos_path, ["monos", output_wasm_path]); -} - -pub(crate) fn run_twiggy_dominators(output_wasm_path: &str, output_twiggy_dominators_path: &str) { - run_with_stdout_file( - output_twiggy_dominators_path, - ["dominators", output_wasm_path], - ); -} diff --git a/framework/meta/src/tools/twiggy.rs b/framework/meta/src/tools/twiggy.rs new file mode 100644 index 0000000000..3f93fcd459 --- /dev/null +++ b/framework/meta/src/tools/twiggy.rs @@ -0,0 +1,47 @@ +use std::process::{Command, Stdio}; + +pub const TWIGGY_NAME: &str = "twiggy"; + +pub fn is_twiggy_installed() -> bool { + Command::new(TWIGGY_NAME) + .args(["--version"]) + .output() + .is_ok() +} + +fn run_with_stdout_file(stdout_file_name: &str, args: I) +where + I: IntoIterator, + S: AsRef, +{ + let stdout_file = std::fs::File::create(stdout_file_name).unwrap(); + let _ = Command::new(TWIGGY_NAME) + .args(args) + .stdout(Stdio::from(stdout_file)) + .spawn() + .expect("failed to spawn twiggy process") + .wait() + .expect("twiggy was not running"); +} + +pub(crate) fn run_twiggy_top(output_wasm_path: &str, output_twiggy_top_path: &str) { + run_with_stdout_file( + output_twiggy_top_path, + ["top", "-n", "1000", output_wasm_path], + ); +} + +pub(crate) fn run_twiggy_paths(output_wasm_path: &str, output_twiggy_paths_path: &str) { + run_with_stdout_file(output_twiggy_paths_path, ["paths", output_wasm_path]); +} + +pub(crate) fn run_twiggy_monos(output_wasm_path: &str, output_twiggy_monos_path: &str) { + run_with_stdout_file(output_twiggy_monos_path, ["monos", output_wasm_path]); +} + +pub(crate) fn run_twiggy_dominators(output_wasm_path: &str, output_twiggy_dominators_path: &str) { + run_with_stdout_file( + output_twiggy_dominators_path, + ["dominators", output_wasm_path], + ); +} diff --git a/framework/meta/src/tools/wasm_opt.rs b/framework/meta/src/tools/wasm_opt.rs new file mode 100644 index 0000000000..9b818e5ef7 --- /dev/null +++ b/framework/meta/src/tools/wasm_opt.rs @@ -0,0 +1,21 @@ +use std::process::Command; + +pub const WASM_OPT_NAME: &str = "wasm-opt"; + +pub fn is_wasm_opt_installed() -> bool { + Command::new(WASM_OPT_NAME) + .args(["--version"]) + .output() + .is_ok() +} + +pub fn run_wasm_opt(output_wasm_path: &str) { + let exit_status = Command::new(WASM_OPT_NAME) + .args([output_wasm_path, "-Oz", "--output", output_wasm_path]) + .spawn() + .expect("failed to spawn wasm-opt process") + .wait() + .expect("wasm-opt was not running"); + + assert!(exit_status.success(), "wasm-opt process failed"); +} diff --git a/framework/meta/src/tools/wasm_to_wat.rs b/framework/meta/src/tools/wasm_to_wat.rs new file mode 100644 index 0000000000..c83383eee4 --- /dev/null +++ b/framework/meta/src/tools/wasm_to_wat.rs @@ -0,0 +1,9 @@ +use anyhow::Result; +use std::fs; + +/// Converts a .wasm file on the disk to .wat. +pub fn wasm_to_wat(output_wasm_path: &str, output_wat_path: &str) -> Result<()> { + let wat_string = wasmprinter::print_file(output_wasm_path)?; + fs::write(output_wat_path, wat_string)?; + Ok(()) +}