From 740d1f62c56cea88f1ce575d8fd26a203bbfb97d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dj8yf0=CE=BCl?= <26653921+dj8yfo@users.noreply.github.com> Date: Wed, 16 Oct 2024 16:59:49 +0300 Subject: [PATCH] feat!: use `wasm-opt -O` (via wasm-opt-rs) as post-step of build (#231) --- Cargo.lock | 148 ++++++++++++++++-- cargo-near-build/Cargo.toml | 2 + cargo-near-build/src/near/build/mod.rs | 15 ++ cargo-near-build/src/pretty_print.rs | 12 ++ .../types/near/build/input/docker_context.rs | 8 + .../src/types/near/build/input/mod.rs | 5 + cargo-near/src/commands/build_command/mod.rs | 6 + 7 files changed, 182 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d736e6db..2a038f14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -493,6 +493,7 @@ dependencies = [ "git2", "hex", "home", + "humantime", "libloading", "near-abi", "nix", @@ -508,6 +509,7 @@ dependencies = [ "tracing", "unix_path", "url", + "wasm-opt", "zstd 0.13.2", ] @@ -695,6 +697,16 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "color-eyre" version = "0.6.3" @@ -947,6 +959,50 @@ dependencies = [ "syn 2.0.77", ] +[[package]] +name = "cxx" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54ccead7d199d584d139148b04b4a368d1ec7556a1d9ea2548febb1b9d49f9a4" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77953e99f01508f89f55c494bfa867171ef3a6c8cea03d26975368f2121a5c1" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn 2.0.77", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65777e06cc48f0cb0152024c77d6cf9e4bdb4408e7b48bea993d42fa0f5b02b6" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98532a60dedaebc4848cb2cba5023337cc9ea3af16a5b062633fabfd9f18fb60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + [[package]] name = "darling" version = "0.20.10" @@ -1406,9 +1462,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1416,9 +1472,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" @@ -1433,15 +1489,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", @@ -1450,21 +1506,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -2231,6 +2287,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "link-cplusplus" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" +dependencies = [ + "cc", +] + [[package]] name = "linked-hash-map" version = "0.5.6" @@ -3792,6 +3857,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scratch" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" + [[package]] name = "scroll" version = "0.10.2" @@ -4420,6 +4491,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "textwrap" version = "0.16.1" @@ -5041,6 +5121,46 @@ version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +[[package]] +name = "wasm-opt" +version = "0.116.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd87a4c135535ffed86123b6fb0f0a5a0bc89e50416c942c5f0662c645f679c" +dependencies = [ + "anyhow", + "libc", + "strum", + "strum_macros", + "tempfile", + "thiserror", + "wasm-opt-cxx-sys", + "wasm-opt-sys", +] + +[[package]] +name = "wasm-opt-cxx-sys" +version = "0.116.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c57b28207aa724318fcec6575fe74803c23f6f266fce10cbc9f3f116762f12e" +dependencies = [ + "anyhow", + "cxx", + "cxx-build", + "wasm-opt-sys", +] + +[[package]] +name = "wasm-opt-sys" +version = "0.116.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a1cce564dc768dacbdb718fc29df2dba80bd21cb47d8f77ae7e3d95ceb98cbe" +dependencies = [ + "anyhow", + "cc", + "cxx", + "cxx-build", +] + [[package]] name = "wasmparser" version = "0.83.0" diff --git a/cargo-near-build/Cargo.toml b/cargo-near-build/Cargo.toml index e7f17bba..ebfc8238 100644 --- a/cargo-near-build/Cargo.toml +++ b/cargo-near-build/Cargo.toml @@ -31,6 +31,8 @@ pathdiff = { version = "0.2.1", features = ["camino"], optional = true } unix_path = { version = "1.0.1", optional = true } tempfile = { version = "3.10.1", optional = true } shell-words = { version = "1.0.0", optional = true} +wasm-opt = "=0.116.1" +humantime = "2.1.0" [target.'cfg(target_os = "linux")'.dependencies] nix = { version = "0.29.0", features = ["user", "process"], optional = true } diff --git a/cargo-near-build/src/near/build/mod.rs b/cargo-near-build/src/near/build/mod.rs index 702d6db5..53a2334c 100644 --- a/cargo-near-build/src/near/build/mod.rs +++ b/cargo-near-build/src/near/build/mod.rs @@ -25,6 +25,7 @@ pub mod export; /// builds a contract whose crate root is current workdir, or identified by [`Cargo.toml`/BuildOpts::manifest_path](crate::BuildOpts::manifest_path) location pub fn run(args: Opts) -> eyre::Result { + let start = std::time::Instant::now(); VersionMismatch::export_builder_and_near_abi_versions(); export::nep_330_build_command(&args)?; env_keys::nep330::print_env(); @@ -145,6 +146,19 @@ pub fn run(args: Opts) -> eyre::Result { )?; wasm_artifact.path = crate::fs::copy(&wasm_artifact.path, &out_dir)?; + + if !args.no_wasmopt { + println!(); + pretty_print::handle_step( + "Running an optimize for size post-step with wasm-opt...", + || { + wasm_opt::OptimizationOptions::new_optimize_for_size() + .run(&wasm_artifact.path, &wasm_artifact.path)?; + Ok(()) + }, + )?; + } + wasm_artifact.builder_version_mismatch = builder_version_mismatch; // todo! if we embedded, check that the binary exports the __contract_abi symbol @@ -172,5 +186,6 @@ pub fn run(args: Opts) -> eyre::Result { } messages.pretty_print(); + pretty_print::duration(start, "cargo near build"); Ok(wasm_artifact) } diff --git a/cargo-near-build/src/pretty_print.rs b/cargo-near-build/src/pretty_print.rs index 15e5c656..69ef4823 100644 --- a/cargo-near-build/src/pretty_print.rs +++ b/cargo-near-build/src/pretty_print.rs @@ -1,3 +1,5 @@ +use std::time::Instant; + use colored::Colorize; pub fn handle_step(msg: &str, f: F) -> eyre::Result @@ -21,3 +23,13 @@ pub fn step(msg: &str) { pub fn success(msg: &str) { eprintln!("{} {}", "✓".bold().green(), msg); } + +pub fn duration(start: Instant, activity: &str) { + let duration = std::time::Duration::from_secs(start.elapsed().as_secs()); + println!( + " {} {} in {}", + "Finished".bold().cyan(), + activity, + humantime::format_duration(duration) + ); +} diff --git a/cargo-near-build/src/types/near/build/input/docker_context.rs b/cargo-near-build/src/types/near/build/input/docker_context.rs index c74e2bdc..4b20bff1 100644 --- a/cargo-near-build/src/types/near/build/input/docker_context.rs +++ b/cargo-near-build/src/types/near/build/input/docker_context.rs @@ -85,6 +85,7 @@ impl super::Opts { cli_args.extend(self.no_abi.then_some("--no-abi".into())); cli_args.extend(self.no_embed_abi.then_some("--no-embed-abi".into())); cli_args.extend(self.no_doc.then_some("--no-doc".into())); + cli_args.extend(self.no_wasmopt.then_some("--no-wasmopt".into())); if let Some(ref features) = self.features { cli_args.extend(["--features".into(), features.clone()]); @@ -138,6 +139,13 @@ impl super::Opts { Self::BUILD_COMMAND_CLI_CONFIG_ERR ))); } + if self.no_wasmopt { + return Err(eyre::eyre!(format!( + "`{}` {}", + "--no-wasmopt ", + Self::BUILD_COMMAND_CLI_CONFIG_ERR + ))); + } if self.features.is_some() { return Err(eyre::eyre!(format!( "`{}` {}", diff --git a/cargo-near-build/src/types/near/build/input/mod.rs b/cargo-near-build/src/types/near/build/input/mod.rs index e5d4bd81..c9fb7a29 100644 --- a/cargo-near-build/src/types/near/build/input/mod.rs +++ b/cargo-near-build/src/types/near/build/input/mod.rs @@ -30,6 +30,8 @@ pub struct Opts { pub no_embed_abi: bool, /// Do not include rustdocs in the embedded ABI pub no_doc: bool, + /// do not run `wasm-opt -O` on the generated output as a post-step + pub no_wasmopt: bool, /// Copy final artifacts to this directory pub out_dir: Option, /// Path to the `Cargo.toml` of the contract to build @@ -94,6 +96,9 @@ impl Opts { if self.no_doc { cargo_args.push("--no-doc"); } + if self.no_wasmopt { + cargo_args.push("--no-wasmopt"); + } if let Some(ref out_dir) = self.out_dir { cargo_args.extend_from_slice(&["--out-dir", out_dir.as_str()]); } diff --git a/cargo-near/src/commands/build_command/mod.rs b/cargo-near/src/commands/build_command/mod.rs index 18970ddf..559e87c7 100644 --- a/cargo-near/src/commands/build_command/mod.rs +++ b/cargo-near/src/commands/build_command/mod.rs @@ -24,6 +24,9 @@ pub struct BuildCommand { /// Do not include rustdocs in the embedded ABI #[interactive_clap(long)] pub no_doc: bool, + /// Do not run `wasm-opt -O` on the generated output as a post-step + #[interactive_clap(long)] + pub no_wasmopt: bool, /// Copy final artifacts to this directory #[interactive_clap(long)] #[interactive_clap(skip_interactive_input)] @@ -93,6 +96,7 @@ impl From for BuildCommand { no_abi: value.no_abi, no_embed_abi: value.no_embed_abi, no_doc: value.no_doc, + no_wasmopt: value.no_wasmopt, features: value.features, no_default_features: value.no_default_features, out_dir: value.out_dir, @@ -125,6 +129,7 @@ impl From for BuildOpts { no_abi: value.no_abi, no_embed_abi: value.no_embed_abi, no_doc: value.no_doc, + no_wasmopt: value.no_wasmopt, features: value.features, no_default_features: value.no_default_features, out_dir: value.out_dir.map(Into::into), @@ -150,6 +155,7 @@ impl BuildCommandlContext { no_abi: scope.no_abi, no_embed_abi: scope.no_embed_abi, no_doc: scope.no_doc, + no_wasmopt: scope.no_wasmopt, out_dir: scope.out_dir.clone(), manifest_path: scope.manifest_path.clone(), features: scope.features.clone(),