1use crate::{config::Config, WasmEdgeResult};
4use std::path::{Path, PathBuf};
5use wasmedge_sys as sys;
6
7#[derive(Debug)]
9pub struct Compiler {
10 pub(crate) inner: sys::Compiler,
11}
12impl Compiler {
13 pub fn new(config: Option<&Config>) -> WasmEdgeResult<Self> {
19 let inner = match config {
20 Some(cfg) => sys::Compiler::create(Some(&cfg.inner))?,
21 None => sys::Compiler::create(None)?,
22 };
23
24 Ok(Self { inner })
25 }
26
27 pub fn compile_from_file(
41 &self,
42 wasm_file: impl AsRef<Path>,
43 filename: impl AsRef<str>,
44 out_dir: impl AsRef<Path>,
45 ) -> WasmEdgeResult<PathBuf> {
46 #[cfg(target_os = "linux")]
47 let extension = "so";
48 #[cfg(target_os = "macos")]
49 let extension = "dylib";
50 #[cfg(target_os = "windows")]
51 let extension = "dll";
52 let aot_file = out_dir
53 .as_ref()
54 .join(format!("{}.{}", filename.as_ref(), extension));
55 self.inner.compile_from_file(wasm_file, &aot_file)?;
56
57 Ok(aot_file)
58 }
59
60 pub fn compile_from_bytes(
74 &self,
75 bytes: impl AsRef<[u8]>,
76 filename: impl AsRef<str>,
77 out_dir: impl AsRef<Path>,
78 ) -> WasmEdgeResult<PathBuf> {
79 #[cfg(target_os = "linux")]
80 let extension = "so";
81 #[cfg(target_os = "macos")]
82 let extension = "dylib";
83 #[cfg(target_os = "windows")]
84 let extension = "dll";
85 let aot_file = out_dir
86 .as_ref()
87 .join(format!("{}.{}", filename.as_ref(), extension));
88 self.inner.compile_from_bytes(bytes, &aot_file)?;
89
90 Ok(aot_file)
91 }
92}
93
94#[cfg(not(feature = "async"))]
95#[cfg(test)]
96mod tests {
97 use super::*;
98 use crate::{
99 config::{CompilerConfigOptions, ConfigBuilder},
100 params, wat2wasm, CompilerOutputFormat, VmBuilder, WasmVal,
101 };
102 use std::io::Read;
103
104 #[test]
105 fn test_compiler_compile_from_file() -> Result<(), Box<dyn std::error::Error>> {
106 {
108 let config = ConfigBuilder::default()
109 .with_compiler_config(
110 CompilerConfigOptions::new().out_format(CompilerOutputFormat::Native),
111 )
112 .build()?;
113
114 let compiler = Compiler::new(Some(&config))?;
115 let wasm_file = std::env::current_dir()
116 .unwrap()
117 .join("examples/wasmedge-sys/data/fibonacci.wat");
118 let out_dir = std::env::current_dir()?;
119 let aot_filename = "aot_fibonacci_1";
120 let aot_file_path = compiler.compile_from_file(wasm_file, aot_filename, out_dir)?;
121 assert!(aot_file_path.exists());
122 #[cfg(target_os = "macos")]
123 assert!(aot_file_path.ends_with("aot_fibonacci_1.dylib"));
124 #[cfg(target_os = "linux")]
125 assert!(aot_file_path.ends_with("aot_fibonacci_1.so"));
126 #[cfg(target_os = "windows")]
127 assert!(aot_file_path.ends_with("aot_fibonacci_1.dll"));
128
129 let mut aot_file = std::fs::File::open(&aot_file_path)?;
131 let mut buffer = [0u8; 4];
132 aot_file.read_exact(&mut buffer)?;
133 let wasm_magic: [u8; 4] = [0x00, 0x61, 0x73, 0x6D];
134 assert_ne!(buffer, wasm_magic);
135
136 let res =
137 VmBuilder::new()
138 .build()?
139 .run_func_from_file(&aot_file_path, "fib", params!(5))?;
140 assert_eq!(res[0].to_i32(), 8);
141
142 assert!(std::fs::remove_file(aot_file_path).is_ok());
144 }
145
146 {
148 let wasm_bytes = wat2wasm(
149 br#"(module
150 (export "fib" (func $fib))
151 (func $fib (param $n i32) (result i32)
152 (if
153 (i32.lt_s
154 (local.get $n)
155 (i32.const 2)
156 )
157 (then
158 (return (i32.const 1))
159 )
160 )
161 (return
162 (i32.add
163 (call $fib
164 (i32.sub
165 (local.get $n)
166 (i32.const 2)
167 )
168 )
169 (call $fib
170 (i32.sub
171 (local.get $n)
172 (i32.const 1)
173 )
174 )
175 )
176 )
177 )
178 )
179 "#,
180 )?;
181
182 let config = ConfigBuilder::default()
184 .with_compiler_config(
185 CompilerConfigOptions::new().out_format(CompilerOutputFormat::Native),
186 )
187 .build()?;
188 let compiler = Compiler::new(Some(&config))?;
189
190 let out_dir = std::env::current_dir()?;
192 let aot_filename = "aot_fibonacci_2";
193 let aot_file_path = compiler.compile_from_bytes(wasm_bytes, aot_filename, out_dir)?;
194 assert!(aot_file_path.exists());
195 #[cfg(target_os = "macos")]
196 assert!(aot_file_path.ends_with("aot_fibonacci_2.dylib"));
197 #[cfg(target_os = "linux")]
198 assert!(aot_file_path.ends_with("aot_fibonacci_2.so"));
199 #[cfg(target_os = "windows")]
200 assert!(aot_file_path.ends_with("aot_fibonacci_2.dll"));
201
202 let mut aot_file = std::fs::File::open(&aot_file_path)?;
204 let mut buffer = [0u8; 4];
205 aot_file.read_exact(&mut buffer)?;
206 let wasm_magic: [u8; 4] = [0x00, 0x61, 0x73, 0x6D];
207 assert_ne!(buffer, wasm_magic);
208
209 let res =
210 VmBuilder::new()
211 .build()?
212 .run_func_from_file(&aot_file_path, "fib", params!(5))?;
213 assert_eq!(res[0].to_i32(), 8);
214
215 assert!(std::fs::remove_file(aot_file_path).is_ok());
217 }
218
219 Ok(())
220 }
221}