123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- use crate::config::WasmOptLevel;
- use crate::{Result, WasmOptConfig};
- use std::path::Path;
- /// Write these wasm bytes with a particular set of optimizations
- pub async fn write_wasm(bytes: &[u8], output_path: &Path, cfg: &WasmOptConfig) -> Result<()> {
- tokio::fs::write(output_path, bytes).await?;
- optimize(output_path, output_path, cfg).await?;
- Ok(())
- }
- #[allow(unreachable_code)]
- pub async fn optimize(input_path: &Path, output_path: &Path, cfg: &WasmOptConfig) -> Result<()> {
- #[cfg(feature = "optimizations")]
- return run_from_lib(input_path, output_path, cfg).await;
- // It's okay not to run wasm-opt but we should *really* try it
- if which::which("wasm-opt").is_err() {
- tracing::warn!("wasm-opt not found and CLI is compiled without optimizations. Skipping optimization for {}", input_path.display());
- return Ok(());
- }
- run_locally(input_path, output_path, cfg).await?;
- Ok(())
- }
- async fn run_locally(input_path: &Path, output_path: &Path, cfg: &WasmOptConfig) -> Result<()> {
- let mut args = vec![
- // needed by wasm-bindgen
- "--enable-reference-types",
- ];
- if cfg.memory_packing {
- // needed for our current approach to bundle splitting to work properly
- // todo(jon): emit the main module's data section in chunks instead of all at once
- args.push("--memory-packing");
- }
- if !cfg.debug {
- args.push("--strip-debug");
- } else {
- args.push("--debuginfo");
- }
- let level = match cfg.level {
- WasmOptLevel::Z => "-Oz",
- WasmOptLevel::S => "-Os",
- WasmOptLevel::Zero => "-O0",
- WasmOptLevel::One => "-O1",
- WasmOptLevel::Two => "-O2",
- WasmOptLevel::Three => "-O3",
- WasmOptLevel::Four => "-O4",
- };
- tokio::process::Command::new("wasm-opt")
- .arg(input_path)
- .arg(level)
- .arg("-o")
- .arg(output_path)
- .args(args)
- .output()
- .await?;
- Ok(())
- }
- /// Use the `wasm_opt` crate
- #[cfg(feature = "optimizations")]
- async fn run_from_lib(
- input_path: &Path,
- output_path: &Path,
- options: &WasmOptConfig,
- ) -> Result<()> {
- let mut level = match options.level {
- WasmOptLevel::Z => wasm_opt::OptimizationOptions::new_optimize_for_size_aggressively(),
- WasmOptLevel::S => wasm_opt::OptimizationOptions::new_optimize_for_size(),
- WasmOptLevel::Zero => wasm_opt::OptimizationOptions::new_opt_level_0(),
- WasmOptLevel::One => wasm_opt::OptimizationOptions::new_opt_level_1(),
- WasmOptLevel::Two => wasm_opt::OptimizationOptions::new_opt_level_2(),
- WasmOptLevel::Three => wasm_opt::OptimizationOptions::new_opt_level_3(),
- WasmOptLevel::Four => wasm_opt::OptimizationOptions::new_opt_level_4(),
- };
- level
- .enable_feature(wasm_opt::Feature::ReferenceTypes)
- .add_pass(wasm_opt::Pass::MemoryPacking)
- .debug_info(options.debug)
- .run(input_path, output_path)
- .map_err(|err| crate::Error::Other(anyhow::anyhow!(err)))?;
- Ok(())
- }
|