soroban_cli/commands/contract/
optimize.rs1use clap::{arg, Parser};
2use std::{fmt::Debug, path::PathBuf};
3#[cfg(feature = "additional-libs")]
4use wasm_opt::{Feature, OptimizationError, OptimizationOptions};
5
6use crate::wasm;
7
8#[derive(Parser, Debug, Clone)]
9#[group(skip)]
10pub struct Cmd {
11 #[arg(long, num_args = 1.., required = true)]
13 wasm: Vec<PathBuf>,
14
15 #[arg(long)]
17 wasm_out: Option<std::path::PathBuf>,
18}
19
20#[derive(thiserror::Error, Debug)]
21pub enum Error {
22 #[error(transparent)]
23 Wasm(#[from] wasm::Error),
24
25 #[cfg(feature = "additional-libs")]
26 #[error("optimization error: {0}")]
27 OptimizationError(OptimizationError),
28
29 #[cfg(not(feature = "additional-libs"))]
30 #[error("must install with \"additional-libs\" feature.")]
31 Install,
32
33 #[error("--wasm-out cannot be used with --wasm option when passing multiple files")]
34 MultipleFilesOutput,
35}
36
37impl Cmd {
38 #[cfg(not(feature = "additional-libs"))]
39 pub fn run(&self) -> Result<(), Error> {
40 Err(Error::Install)
41 }
42
43 #[cfg(feature = "additional-libs")]
44 pub fn run(&self) -> Result<(), Error> {
45 optimize(false, self.wasm.clone(), self.wasm_out.clone())
46 }
47}
48
49#[cfg(feature = "additional-libs")]
50pub fn optimize(
51 quiet: bool,
52 wasm: Vec<PathBuf>,
53 wasm_out: Option<std::path::PathBuf>,
54) -> Result<(), Error> {
55 if wasm.len() > 1 && wasm_out.is_some() {
56 return Err(Error::MultipleFilesOutput);
57 }
58
59 for wasm_path in &wasm {
60 let wasm_arg = wasm::Args {
61 wasm: wasm_path.into(),
62 };
63
64 if !quiet {
65 println!(
66 "Reading: {path} ({wasm_size} bytes)",
67 path = wasm_arg.wasm.to_string_lossy(),
68 wasm_size = wasm_arg.len()?
69 );
70 }
71
72 let wasm_out = wasm_out.clone().unwrap_or_else(|| {
73 let mut wasm_out = wasm_arg.wasm.clone();
74 wasm_out.set_extension("optimized.wasm");
75 wasm_out
76 });
77
78 let mut options = OptimizationOptions::new_optimize_for_size_aggressively();
79 options.converge = true;
80
81 options.mvp_features_only();
89 options.enable_feature(Feature::MutableGlobals);
90 options.enable_feature(Feature::SignExt);
91
92 options
93 .run(&wasm_arg.wasm, &wasm_out)
94 .map_err(Error::OptimizationError)?;
95
96 if !quiet {
97 println!(
98 "Optimized: {path} ({size} bytes)",
99 path = wasm_out.to_string_lossy(),
100 size = wasm::len(&wasm_out)?
101 );
102 }
103 }
104
105 Ok(())
106}