1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
//! The module that implements the `wasmtime explore` command.

use anyhow::{Context, Result};
use clap::Parser;
use std::{borrow::Cow, path::PathBuf};
use wasmtime_cli_flags::CommonOptions;

/// Explore the compilation of a WebAssembly module to native code.
#[derive(Parser, PartialEq)]
pub struct ExploreCommand {
    #[command(flatten)]
    common: CommonOptions,

    /// The target triple; default is the host triple
    #[arg(long, value_name = "TARGET")]
    target: Option<String>,

    /// The path of the WebAssembly module to compile
    #[arg(required = true, value_name = "MODULE")]
    module: PathBuf,

    /// The path of the explorer output (derived from the MODULE name if none
    /// provided)
    #[arg(short, long)]
    output: Option<PathBuf>,
}

impl ExploreCommand {
    /// Executes the command.
    pub fn execute(mut self) -> Result<()> {
        self.common.init_logging()?;

        let config = self.common.config(self.target.as_deref(), None)?;

        let bytes =
            Cow::Owned(std::fs::read(&self.module).with_context(|| {
                format!("failed to read Wasm module: {}", self.module.display())
            })?);
        #[cfg(feature = "wat")]
        let bytes = wat::parse_bytes(&bytes).map_err(|mut e| {
            e.set_path(&self.module);
            e
        })?;

        let output = self
            .output
            .clone()
            .unwrap_or_else(|| self.module.with_extension("explore.html"));
        let output_file = std::fs::File::create(&output)
            .with_context(|| format!("failed to create file: {}", output.display()))?;
        let mut output_file = std::io::BufWriter::new(output_file);

        wasmtime_explorer::generate(&config, self.target.as_deref(), &bytes, &mut output_file)?;
        println!("Exploration written to {}", output.display());
        Ok(())
    }
}