wasmer_cli/commands/
compile.rs1use std::path::PathBuf;
2
3use anyhow::{Context, Result, bail};
4use clap::Parser;
5use wasmer::{
6 sys::{engine::NativeEngineExt, *},
7 *,
8};
9
10use crate::{backend::RuntimeOptions, common::HashAlgorithm, warning};
11
12#[derive(Debug, Parser)]
13pub struct Compile {
15 #[clap(name = "FILE")]
17 path: PathBuf,
18
19 #[clap(name = "OUTPUT PATH", short = 'o')]
21 output: PathBuf,
22
23 #[clap(long = "target")]
25 target_triple: Option<Triple>,
26
27 #[clap(flatten)]
28 rt: RuntimeOptions,
29
30 #[clap(short = 'm')]
31 cpu_features: Vec<CpuFeature>,
32
33 #[clap(long, value_enum)]
35 hash_algorithm: Option<HashAlgorithm>,
36}
37
38impl Compile {
39 pub fn execute(&self) -> Result<()> {
41 self.inner_execute()
42 .context(format!("failed to compile `{}`", self.path.display()))
43 }
44
45 fn inner_execute(&self) -> Result<()> {
46 let target = self
47 .target_triple
48 .as_ref()
49 .map(|target_triple| {
50 let mut features = self
51 .cpu_features
52 .clone()
53 .into_iter()
54 .fold(CpuFeature::set(), |a, b| a | b);
55 if target_triple.architecture == Architecture::X86_64 {
58 features |= CpuFeature::SSE2;
59 }
60 Target::new(target_triple.clone(), features)
61 })
62 .unwrap_or_default();
63
64 let module_contents = std::fs::read(&self.path)?;
65 if !is_wasm(&module_contents) {
66 bail!("`wasmer compile` only compiles WebAssembly files");
67 }
68
69 let mut engine = self.rt.get_engine_for_module(&module_contents, &target)?;
70
71 let hash_algorithm = self.hash_algorithm.unwrap_or_default().into();
72 engine.set_hash_algorithm(Some(hash_algorithm));
73
74 let output_filename = self
75 .output
76 .file_stem()
77 .map(|osstr| osstr.to_string_lossy().to_string())
78 .unwrap_or_default();
79 let recommended_extension = "wasmu";
81 match self.output.extension() {
82 Some(ext) => {
83 if ext != recommended_extension {
84 warning!(
85 "the output file has a wrong extension. We recommend using `{}.{}` for the chosen target",
86 &output_filename,
87 &recommended_extension
88 )
89 }
90 }
91 None => {
92 warning!(
93 "the output file has no extension. We recommend using `{}.{}` for the chosen target",
94 &output_filename,
95 &recommended_extension
96 )
97 }
98 }
99 println!("Compiler: {}", engine.deterministic_id());
100 println!("Target: {}", target.triple());
101
102 let module = Module::new(&engine, &module_contents)?;
103 module.serialize_to_file(&self.output)?;
104 eprintln!(
105 "✔ File compiled successfully to `{}`.",
106 self.output.display(),
107 );
108
109 Ok(())
110 }
111}