xref: /wasmtime-44.0.1/src/commands/explore.rs (revision b81ef46c)
1 //! The module that implements the `wasmtime explore` command.
2 
3 use anyhow::{Context, Result};
4 use clap::Parser;
5 use std::{borrow::Cow, path::PathBuf};
6 use tempfile::tempdir;
7 use wasmtime::Strategy;
8 use wasmtime_cli_flags::CommonOptions;
9 
10 /// Explore the compilation of a WebAssembly module to native code.
11 #[derive(Parser, PartialEq)]
12 pub struct ExploreCommand {
13     #[command(flatten)]
14     common: CommonOptions,
15 
16     /// The target triple; default is the host triple
17     #[arg(long, value_name = "TARGET")]
18     target: Option<String>,
19 
20     /// The path of the WebAssembly module to compile
21     #[arg(required = true, value_name = "MODULE")]
22     module: PathBuf,
23 
24     /// The path of the explorer output (derived from the MODULE name if none
25     /// provided)
26     #[arg(short, long)]
27     output: Option<PathBuf>,
28 }
29 
30 impl ExploreCommand {
31     /// Executes the command.
32     pub fn execute(mut self) -> Result<()> {
33         self.common.init_logging()?;
34 
35         let mut config = self.common.config(self.target.as_deref(), None)?;
36 
37         let bytes =
38             Cow::Owned(std::fs::read(&self.module).with_context(|| {
39                 format!("failed to read Wasm module: {}", self.module.display())
40             })?);
41         #[cfg(feature = "wat")]
42         let bytes = wat::parse_bytes(&bytes).map_err(|mut e| {
43             e.set_path(&self.module);
44             e
45         })?;
46 
47         let output = self
48             .output
49             .clone()
50             .unwrap_or_else(|| self.module.with_extension("explore.html"));
51         let output_file = std::fs::File::create(&output)
52             .with_context(|| format!("failed to create file: {}", output.display()))?;
53         let mut output_file = std::io::BufWriter::new(output_file);
54 
55         let clif_dir = if let Some(Strategy::Cranelift) | None = self.common.codegen.compiler {
56             let clif_dir = tempdir()?;
57             config.emit_clif(clif_dir.path());
58             config.disable_cache(); // cache does not emit clif
59             Some(clif_dir)
60         } else {
61             None
62         };
63 
64         wasmtime_explorer::generate(
65             &config,
66             self.target.as_deref(),
67             clif_dir.as_ref().map(|tmp_dir| tmp_dir.path()),
68             &bytes,
69             &mut output_file,
70         )?;
71 
72         println!("Exploration written to {}", output.display());
73         Ok(())
74     }
75 }
76