From d9a62864c95b4b16803626b23ec1f580ece0b4f3 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 30 Oct 2020 16:40:44 +0100 Subject: [PATCH 1/4] Use binaryen-rs as dep instead of manual install of wasm-opt --- Cargo.lock | 22 ++++++++++++++++++++ Cargo.toml | 1 + README.md | 3 ++- src/cmd/build.rs | 53 ++++++++++++++++++++---------------------------- 4 files changed, 47 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a23798c6..c98ab05e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -301,6 +301,27 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +[[package]] +name = "binaryen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a51ad23b3c7ab468d9daa948201921879ef0052e561c250fd0b326e6f000f2dd" +dependencies = [ + "binaryen-sys", +] + +[[package]] +name = "binaryen-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df5829a7c89f7827e58866704e4dfdf48a635d73c6e5449c1a8a0ba5a319d28a" +dependencies = [ + "cc", + "cmake", + "heck", + "regex", +] + [[package]] name = "bitflags" version = "1.2.1" @@ -477,6 +498,7 @@ dependencies = [ "anyhow", "assert_matches", "async-std", + "binaryen", "blake2", "cargo-xbuild", "cargo_metadata 0.11.4", diff --git a/Cargo.toml b/Cargo.toml index 0c56fba7..1252866c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,6 +41,7 @@ serde = { version = "1.0.115", default-features = false, features = ["derive"] } serde_json = "1.0.57" tempfile = "3.1.0" url = { version = "2.1.1", features = ["serde"] } +binaryen = "0.10.0" # dependencies for optional extrinsics feature async-std = { version = "1.6.2", optional = true } diff --git a/README.md b/README.md index e5c0f101..c3d97847 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ A CLI tool for helping setting up and managing WebAssembly smart contracts writt - **Prerequisites** - **rust-src**: `rustup component add rust-src` - - **wasm-opt**: https://github.com/WebAssembly/binaryen#tools + - A C++14 compiler is required for building the [binaryen](https://github.com/WebAssembly/binaryen) + dependency. `binaryen` is build automatically during the `cargo-contract` build process. - **Install latest version from [crates.io](https://crates.io/crates/cargo-contract)** - `cargo install cargo-contract` diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 4fa2011b..9c8cfec2 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -15,10 +15,9 @@ // along with cargo-contract. If not, see . use std::{ - fs::metadata, - io::{self, Write}, + fs::{metadata, File}, + io::{Read, Write}, path::PathBuf, - process::Command, }; use crate::{ @@ -189,42 +188,34 @@ fn post_process_wasm(crate_metadata: &CrateMetadata) -> Result<()> { Ok(()) } -/// Attempts to perform optional wasm optimization using `wasm-opt`. +/// Attempts to perform optional wasm optimization using `binaryen`. /// /// The intention is to reduce the size of bloated wasm binaries as a result of missing /// optimizations (or bugs?) between Rust and Wasm. -/// -/// This step depends on the `wasm-opt` tool being installed. If it is not the build will still -/// succeed, and the user will be encouraged to install it for further optimizations. fn optimize_wasm(crate_metadata: &CrateMetadata) -> Result<()> { - // check `wasm-opt` installed - if which::which("wasm-opt").is_err() { - println!( - "{}", - "wasm-opt is not installed. Install this tool on your system in order to \n\ - reduce the size of your contract's Wasm binary. \n\ - See https://github.com/WebAssembly/binaryen#tools" - .bright_yellow() - ); - return Ok(()); - } - let mut optimized = crate_metadata.dest_wasm.clone(); optimized.set_file_name(format!("{}-opt.wasm", crate_metadata.package_name)); - let output = Command::new("wasm-opt") - .arg(crate_metadata.dest_wasm.as_os_str()) - .arg("-O3") // execute -O3 optimization passes (spends potentially a lot of time optimizing) - .arg("-o") - .arg(optimized.as_os_str()) - .output()?; + let codegen_config = binaryen::CodegenConfig { + // execute -O3 optimization passes (spends potentially a lot of time optimizing) + optimization_level: 3, + // the default + shrink_level: 1, + // the default + debug_info: false, + }; - if !output.status.success() { - // Dump the output streams produced by wasm-opt into the stdout/stderr. - io::stdout().write_all(&output.stdout)?; - io::stderr().write_all(&output.stderr)?; - anyhow::bail!("wasm-opt optimization failed"); - } + let mut dest_wasm_file = File::open(crate_metadata.dest_wasm.as_os_str())?; + let mut dest_wasm_file_content = Vec::new(); + dest_wasm_file.read_to_end(&mut dest_wasm_file_content)?; + + let mut module = binaryen::Module::read(&dest_wasm_file_content) + .map_err(|_| anyhow::anyhow!("binaryen failed to read file content"))?; + module.optimize(&codegen_config); + let optimized_wasm = module.write(); + + let mut optimized_wasm_file = File::create(optimized.as_os_str())?; + optimized_wasm_file.write_all(&optimized_wasm)?; let original_size = metadata(&crate_metadata.dest_wasm)?.len() as f64 / 1000.0; let optimized_size = metadata(&optimized)?.len() as f64 / 1000.0; -- GitLab From 7eee232f6c15744d775ead11c30ee4493f6d9fc2 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 30 Oct 2020 19:50:49 +0100 Subject: [PATCH 2/4] Get CI to build binaryen-sys --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 33edc5fd..4c853265 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,6 +16,7 @@ variables: CARGO_HOME: "/ci-cache/${CI_PROJECT_NAME}/cargo/${CI_COMMIT_REF_NAME}/${CI_JOB_NAME}" CARGO_TARGET_DIR: "/ci-cache/${CI_PROJECT_NAME}/targets/${CI_COMMIT_REF_NAME}/${CI_JOB_NAME}" RUST_LIB_BACKTRACE: "0" + CXX: "/usr/bin/clang++-8" workflow: rules: -- GitLab From be1c1b43c641d6d5ec6a95ff0a5d21ad64b428e5 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Sat, 31 Oct 2020 15:49:55 +0100 Subject: [PATCH 3/4] Add explanatory comment --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4c853265..1c8e2eb4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,6 +16,8 @@ variables: CARGO_HOME: "/ci-cache/${CI_PROJECT_NAME}/cargo/${CI_COMMIT_REF_NAME}/${CI_JOB_NAME}" CARGO_TARGET_DIR: "/ci-cache/${CI_PROJECT_NAME}/targets/${CI_COMMIT_REF_NAME}/${CI_JOB_NAME}" RUST_LIB_BACKTRACE: "0" + + # Necessary for building binaryen-sys, which is part of the binaryen dependency CXX: "/usr/bin/clang++-8" workflow: -- GitLab From 8735b85b714c9b2e4a5df2e08e4ac04268dec409 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 2 Nov 2020 13:07:44 +0100 Subject: [PATCH 4/4] Remove CXX export, will be set in docker instead --- .gitlab-ci.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1c8e2eb4..33edc5fd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -17,9 +17,6 @@ variables: CARGO_TARGET_DIR: "/ci-cache/${CI_PROJECT_NAME}/targets/${CI_COMMIT_REF_NAME}/${CI_JOB_NAME}" RUST_LIB_BACKTRACE: "0" - # Necessary for building binaryen-sys, which is part of the binaryen dependency - CXX: "/usr/bin/clang++-8" - workflow: rules: - if: $CI_COMMIT_TAG -- GitLab