wasmer_compiler_cli/commands/
compile.rs1use crate::store::StoreOptions;
2use crate::warning;
3use anyhow::{Context, Result};
4use clap::Parser;
5use std::fs;
6use std::path::{Path, PathBuf};
7use wasmer_compiler::{ArtifactBuild, ArtifactCreate, ModuleEnvironment};
8use wasmer_types::entity::PrimaryMap;
9use wasmer_types::target::{Architecture, CpuFeature, Target, Triple};
10use wasmer_types::{CompileError, MemoryIndex, MemoryStyle, TableIndex, TableStyle};
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 store: StoreOptions,
29
30 #[clap(short = 'm')]
31 cpu_features: Vec<CpuFeature>,
32}
33
34impl Compile {
35 pub fn execute(&self) -> Result<()> {
37 self.inner_execute()
38 .context(format!("failed to compile `{}`", self.path.display()))
39 }
40
41 fn inner_execute(&self) -> Result<()> {
42 let target = self
43 .target_triple
44 .as_ref()
45 .map(|target_triple| {
46 let mut features = self
47 .cpu_features
48 .clone()
49 .into_iter()
50 .fold(CpuFeature::set(), |a, b| a | b);
51 if target_triple.architecture == Architecture::X86_64 {
54 features |= CpuFeature::SSE2;
55 }
56 Target::new(target_triple.clone(), features)
57 })
58 .unwrap_or_default();
59 let (engine_builder, compiler_type) = self.store.get_engine_for_target(target.clone())?;
60 let engine = engine_builder
61 .set_hash_algorithm(Some(wasmer_types::HashAlgorithm::Sha256))
62 .engine();
63 let output_filename = self
64 .output
65 .file_stem()
66 .map(|osstr| osstr.to_string_lossy().to_string())
67 .unwrap_or_default();
68 let recommended_extension = "wasmu";
71 match self.output.extension() {
72 Some(ext) => {
73 if ext != recommended_extension {
74 warning!(
75 "the output file has a wrong extension. We recommend using `{}.{}` for the chosen target",
76 &output_filename,
77 &recommended_extension
78 )
79 }
80 }
81 None => {
82 warning!(
83 "the output file has no extension. We recommend using `{}.{}` for the chosen target",
84 &output_filename,
85 &recommended_extension
86 )
87 }
88 }
89 let tunables = self.store.get_tunables_for_target(&target)?;
90
91 println!("Compiler: {compiler_type}");
92 println!("Target: {}", target.triple());
93
94 let path: &Path = self.path.as_ref();
96 let wasm_bytes = std::fs::read(path)?;
97 let environ = ModuleEnvironment::new();
98 let translation = environ.translate(&wasm_bytes).map_err(CompileError::Wasm)?;
99 let module = translation.module;
100 let memory_styles: PrimaryMap<MemoryIndex, MemoryStyle> = module
101 .memories
102 .values()
103 .map(|memory_type| tunables.memory_style(memory_type))
104 .collect();
105 let table_styles: PrimaryMap<TableIndex, TableStyle> = module
106 .tables
107 .values()
108 .map(|table_type| tunables.table_style(table_type))
109 .collect();
110 let artifact = ArtifactBuild::new(
111 &mut engine.inner_mut(),
112 &wasm_bytes,
113 &target,
114 memory_styles,
115 table_styles,
116 engine.hash_algorithm(),
117 )?;
118 let serialized = artifact.serialize()?;
119 fs::write(output_filename, serialized)?;
120 eprintln!(
121 "✔ File compiled successfully to `{}`.",
122 self.output.display(),
123 );
124
125 Ok(())
126 }
127}