From 95bdbde930433bfa80e4e06819f4ec6a81c3ce10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Thu, 25 Jul 2024 10:32:30 +0200 Subject: [PATCH 1/9] Add `wasm-opt` to CLI build scripts. It will be used for automatic WASM optimization. --- Cargo.lock | 1 + kairos-cli/Cargo.toml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 758f6dfa..86e6e8a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2726,6 +2726,7 @@ dependencies = [ "tokio", "tracing", "tracing-subscriber", + "wasm-opt", ] [[package]] diff --git a/kairos-cli/Cargo.toml b/kairos-cli/Cargo.toml index 6c2021b8..4fa78dda 100644 --- a/kairos-cli/Cargo.toml +++ b/kairos-cli/Cargo.toml @@ -45,3 +45,6 @@ assert_cmd = "2" predicates = "3" kairos-test-utils = { path = "../kairos-test-utils" } casper-client-hashing.workspace = true + +[build-dependencies] +wasm-opt = "0.116" From 929c373f48b0f01623711535ea51651a73d17e22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Thu, 25 Jul 2024 10:34:46 +0200 Subject: [PATCH 2/9] CLI: Automatic WASM discovery and optimization. `PATH_TO_SESSION_BINARIES` no longer needs to be set :). --- kairos-cli/build.rs | 70 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 3 deletions(-) diff --git a/kairos-cli/build.rs b/kairos-cli/build.rs index 3bce4324..a7897edb 100644 --- a/kairos-cli/build.rs +++ b/kairos-cli/build.rs @@ -1,11 +1,10 @@ use std::env; use std::fs; -use std::path::Path; +use std::path::{Path, PathBuf}; fn main() { // Path - let session_binaries_dir = env::var("PATH_TO_SESSION_BINARIES") - .expect("PATH_TO_SESSION_BINARIES environment variable is not set"); + let session_binaries_dir = get_wasm_directory(); // Get the output directory set by Cargo. let out_dir = env::var("OUT_DIR").expect("OUT_DIR not set"); @@ -18,3 +17,68 @@ fn main() { // Print out a message to re-run this script if the source file changes. println!("cargo:rerun-if-changed={}", source_path.display()); } + +pub fn get_wasm_directory() -> PathBuf { + // Environment variable, or default path based on the project structure. + let base_path_session = if let Ok(custom_path) = env::var("PATH_TO_SESSION_BINARIES") { + PathBuf::from(custom_path) + } else { + let project_root = env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".to_string()); + PathBuf::from(project_root) + .join("../kairos-session-code/target/wasm32-unknown-unknown/release/") + }; + + if !base_path_session.exists() { + panic!("WASM directory does not exist: {}. Please build session code at `./kairos-session-code` with `cargo build --release`; or set `PATH_TO_SESSION_BINARIES` env variable.", base_path_session.display()); + } + + // Ensure all WASM files are optimized. + optimize_files(&base_path_session).expect("Unable to optimize WASM files"); + + base_path_session +} + +fn optimize_files(dir: &Path) -> Result<(), String> { + let entries = fs::read_dir(dir).map_err(|e| e.to_string())?; + + let mut found_wasm = false; + for entry in entries { + let entry = entry.map_err(|e| e.to_string())?; + let path = entry.path(); + if path.extension().and_then(|s| s.to_str()) == Some("wasm") { + found_wasm = true; + + // Skip already optimized files. + let file_name = path.file_name().unwrap().to_str().unwrap(); + if file_name.ends_with("-optimized.wasm") { + continue; + } + + // Skip if optimized file already exists. + let optimized_file_name = format!( + "{}-optimized.wasm", + file_name.strip_suffix(".wasm").unwrap() + ); + let optimized_file_path = dir.join(&optimized_file_name); + if optimized_file_path.exists() { + continue; + } + + // Optimize and save as new file. + let infile = path.to_str().unwrap().to_string(); + let outfile = optimized_file_path.to_str().unwrap().to_string(); + + let mut opts = wasm_opt::OptimizationOptions::new_optimize_for_size(); + opts.add_pass(wasm_opt::Pass::StripDebug); + opts.add_pass(wasm_opt::Pass::SignextLowering); + + opts.run(&infile, &outfile).map_err(|e| e.to_string())?; + } + } + + if !found_wasm { + return Err("No WASM files found in the directory. You should change directory to `./kairos-session-code` and build with `cargo build --release`.".to_string()); + } + + Ok(()) +} From df7f70f82a3bb36dc8f08f8a3f6081fb82523054 Mon Sep 17 00:00:00 2001 From: koxu1996 Date: Fri, 26 Jul 2024 12:19:00 +0200 Subject: [PATCH 3/9] Rerun build script when session binaries directory is modified. --- kairos-cli/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kairos-cli/build.rs b/kairos-cli/build.rs index a7897edb..3c233094 100644 --- a/kairos-cli/build.rs +++ b/kairos-cli/build.rs @@ -15,7 +15,7 @@ fn main() { fs::copy(&source_path, dest_path).expect("Failed to copy WASM file"); // Print out a message to re-run this script if the source file changes. - println!("cargo:rerun-if-changed={}", source_path.display()); + println!("cargo:rerun-if-changed={}", session_binaries_dir.display()); } pub fn get_wasm_directory() -> PathBuf { From 278c7013d20dfd8ce71f5f85bfa1165f90e41518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Fri, 26 Jul 2024 12:40:05 +0200 Subject: [PATCH 4/9] Fix clippy error. --- kairos-cli/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kairos-cli/build.rs b/kairos-cli/build.rs index 3c233094..12f4422b 100644 --- a/kairos-cli/build.rs +++ b/kairos-cli/build.rs @@ -12,7 +12,7 @@ fn main() { let dest_path = Path::new(&out_dir).join("deposit-session-optimized.wasm"); // Copy the file from the source to the destination - fs::copy(&source_path, dest_path).expect("Failed to copy WASM file"); + fs::copy(source_path, dest_path).expect("Failed to copy WASM file"); // Print out a message to re-run this script if the source file changes. println!("cargo:rerun-if-changed={}", session_binaries_dir.display()); From d5fd874c500a554ea8ecc569b829cd219bb13883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 30 Jul 2024 10:09:56 +0200 Subject: [PATCH 5/9] Automatically run `cargo build` for session code dependency. --- kairos-cli/build.rs | 50 ++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/kairos-cli/build.rs b/kairos-cli/build.rs index 12f4422b..8b1e61cd 100644 --- a/kairos-cli/build.rs +++ b/kairos-cli/build.rs @@ -1,10 +1,38 @@ use std::env; use std::fs; use std::path::{Path, PathBuf}; +use std::process::Command; fn main() { - // Path - let session_binaries_dir = get_wasm_directory(); + // Rerun the build script if the environment variable changes. + println!("cargo:rerun-if-env-changed=PATH_TO_SESSION_BINARIES"); + + // Determine the session binaries directory. + let session_binaries_dir = if let Ok(session_code_dir) = env::var("PATH_TO_SESSION_BINARIES") { + PathBuf::from(session_code_dir) + } else { + // Run `cargo build --release` if the environment variable is not set. + println!("cargo:warning=Building session code dependency."); + let project_root = env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".to_string()); + let status = Command::new("cargo") + .arg("build") + .arg("--release") + .current_dir(Path::new(&project_root).join("../kairos-session-code")) + .status() + .expect("Failed to execute cargo build --release"); + + if !status.success() { + panic!("cargo build --release failed"); + } + + get_default_wasm_directory(&project_root) + }; + + // Rerun the build script if the session binaries directory changes. + println!("cargo:rerun-if-changed={}", session_binaries_dir.display()); + + // Ensure all WASM files are optimized. + optimize_files(&session_binaries_dir).expect("Unable to optimize WASM files"); // Get the output directory set by Cargo. let out_dir = env::var("OUT_DIR").expect("OUT_DIR not set"); @@ -13,28 +41,16 @@ fn main() { // Copy the file from the source to the destination fs::copy(source_path, dest_path).expect("Failed to copy WASM file"); - - // Print out a message to re-run this script if the source file changes. - println!("cargo:rerun-if-changed={}", session_binaries_dir.display()); } -pub fn get_wasm_directory() -> PathBuf { - // Environment variable, or default path based on the project structure. - let base_path_session = if let Ok(custom_path) = env::var("PATH_TO_SESSION_BINARIES") { - PathBuf::from(custom_path) - } else { - let project_root = env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".to_string()); - PathBuf::from(project_root) - .join("../kairos-session-code/target/wasm32-unknown-unknown/release/") - }; +fn get_default_wasm_directory(project_root: &str) -> PathBuf { + let base_path_session = PathBuf::from(project_root) + .join("../kairos-session-code/target/wasm32-unknown-unknown/release/"); if !base_path_session.exists() { panic!("WASM directory does not exist: {}. Please build session code at `./kairos-session-code` with `cargo build --release`; or set `PATH_TO_SESSION_BINARIES` env variable.", base_path_session.display()); } - // Ensure all WASM files are optimized. - optimize_files(&base_path_session).expect("Unable to optimize WASM files"); - base_path_session } From cf27bab3a3320067306d38c53d4bf54520ba3075 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 30 Jul 2024 10:10:17 +0200 Subject: [PATCH 6/9] Overwrite already existing WASM files during optimization. --- kairos-cli/build.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kairos-cli/build.rs b/kairos-cli/build.rs index 8b1e61cd..b9b10deb 100644 --- a/kairos-cli/build.rs +++ b/kairos-cli/build.rs @@ -70,14 +70,15 @@ fn optimize_files(dir: &Path) -> Result<(), String> { continue; } - // Skip if optimized file already exists. + // Warn about file that will be overwritten. let optimized_file_name = format!( "{}-optimized.wasm", file_name.strip_suffix(".wasm").unwrap() ); let optimized_file_path = dir.join(&optimized_file_name); if optimized_file_path.exists() { - continue; + println!("cargo:warning=Overwriting {}", optimized_file_name); + //continue; // NOTE: Uncomment to disable overwrite. } // Optimize and save as new file. From d09e6c7dd67235ee0fdb65edec9b6f44970819f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 30 Jul 2024 10:10:25 +0200 Subject: [PATCH 7/9] Update error message. --- kairos-cli/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kairos-cli/build.rs b/kairos-cli/build.rs index b9b10deb..dff9d0b0 100644 --- a/kairos-cli/build.rs +++ b/kairos-cli/build.rs @@ -94,7 +94,7 @@ fn optimize_files(dir: &Path) -> Result<(), String> { } if !found_wasm { - return Err("No WASM files found in the directory. You should change directory to `./kairos-session-code` and build with `cargo build --release`.".to_string()); + return Err("No WASM files found.".to_string()); } Ok(()) From 92f9ae5818d32ec43050abfb81e527aa1a9db2dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 30 Jul 2024 11:04:45 +0200 Subject: [PATCH 8/9] Skip files optimization in Nix. --- kairos-cli/build.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/kairos-cli/build.rs b/kairos-cli/build.rs index dff9d0b0..b3a8971b 100644 --- a/kairos-cli/build.rs +++ b/kairos-cli/build.rs @@ -8,8 +8,8 @@ fn main() { println!("cargo:rerun-if-env-changed=PATH_TO_SESSION_BINARIES"); // Determine the session binaries directory. - let session_binaries_dir = if let Ok(session_code_dir) = env::var("PATH_TO_SESSION_BINARIES") { - PathBuf::from(session_code_dir) + let (is_automatic_path, session_binaries_dir) = if let Ok(session_code_dir) = env::var("PATH_TO_SESSION_BINARIES") { + (false, PathBuf::from(session_code_dir)) } else { // Run `cargo build --release` if the environment variable is not set. println!("cargo:warning=Building session code dependency."); @@ -25,14 +25,17 @@ fn main() { panic!("cargo build --release failed"); } - get_default_wasm_directory(&project_root) + (true, get_default_wasm_directory(&project_root)) }; // Rerun the build script if the session binaries directory changes. println!("cargo:rerun-if-changed={}", session_binaries_dir.display()); // Ensure all WASM files are optimized. - optimize_files(&session_binaries_dir).expect("Unable to optimize WASM files"); + // NOTE: We skip it for Nix (it relies on env variable), as files are already optimized and read-only. + if is_automatic_path { + optimize_files(&session_binaries_dir).expect("Unable to optimize WASM files"); + } // Get the output directory set by Cargo. let out_dir = env::var("OUT_DIR").expect("OUT_DIR not set"); From 2eda67a59d3ca1210749711493cc4639220bb8ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 30 Jul 2024 11:16:32 +0200 Subject: [PATCH 9/9] Code formatting. --- kairos-cli/build.rs | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/kairos-cli/build.rs b/kairos-cli/build.rs index b3a8971b..b4cd7bf8 100644 --- a/kairos-cli/build.rs +++ b/kairos-cli/build.rs @@ -8,25 +8,26 @@ fn main() { println!("cargo:rerun-if-env-changed=PATH_TO_SESSION_BINARIES"); // Determine the session binaries directory. - let (is_automatic_path, session_binaries_dir) = if let Ok(session_code_dir) = env::var("PATH_TO_SESSION_BINARIES") { - (false, PathBuf::from(session_code_dir)) - } else { - // Run `cargo build --release` if the environment variable is not set. - println!("cargo:warning=Building session code dependency."); - let project_root = env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".to_string()); - let status = Command::new("cargo") - .arg("build") - .arg("--release") - .current_dir(Path::new(&project_root).join("../kairos-session-code")) - .status() - .expect("Failed to execute cargo build --release"); - - if !status.success() { - panic!("cargo build --release failed"); - } + let (is_automatic_path, session_binaries_dir) = + if let Ok(session_code_dir) = env::var("PATH_TO_SESSION_BINARIES") { + (false, PathBuf::from(session_code_dir)) + } else { + // Run `cargo build --release` if the environment variable is not set. + println!("cargo:warning=Building session code dependency."); + let project_root = env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".to_string()); + let status = Command::new("cargo") + .arg("build") + .arg("--release") + .current_dir(Path::new(&project_root).join("../kairos-session-code")) + .status() + .expect("Failed to execute cargo build --release"); + + if !status.success() { + panic!("cargo build --release failed"); + } - (true, get_default_wasm_directory(&project_root)) - }; + (true, get_default_wasm_directory(&project_root)) + }; // Rerun the build script if the session binaries directory changes. println!("cargo:rerun-if-changed={}", session_binaries_dir.display());