scrypto_test/ledger_simulator/
compile.rs1use crate::prelude::*;
2use scrypto_compiler::*;
3use std::path::Path;
4
5pub enum CompileProfile {
6 Standard,
9 StandardWithTraceLogs,
11 Fast,
13 FastWithTraceLogs,
15 FastWithNoLogs,
17}
18
19pub struct Compile;
20
21impl Compile {
22 pub fn compile<P: AsRef<Path>>(
23 package_dir: P,
24 compile_profile: CompileProfile,
25 ) -> (Vec<u8>, PackageDefinition) {
26 Self::compile_with_env_vars(
27 package_dir,
28 DEFAULT_ENVIRONMENT_VARIABLES
29 .clone()
30 .into_iter()
31 .filter_map(|(key, value)| match value {
32 EnvironmentVariableAction::Set(value) => Some((key, value)),
33 EnvironmentVariableAction::Unset => None,
34 })
35 .collect(),
36 compile_profile,
37 true,
38 )
39 }
40
41 pub fn compile_with_env_vars<P: AsRef<Path>>(
43 package_dir: P,
44 env_vars: sbor::rust::collections::BTreeMap<String, String>,
45 compile_profile: CompileProfile,
46 _use_coverage: bool,
47 ) -> (Vec<u8>, PackageDefinition) {
48 let mut compiler_builder = ScryptoCompiler::builder();
50 compiler_builder.manifest_path(package_dir.as_ref());
51
52 match compile_profile {
53 CompileProfile::Standard => (),
54 CompileProfile::StandardWithTraceLogs => {
55 compiler_builder.log_level(Level::Trace); }
57 CompileProfile::Fast => {
58 compiler_builder.optimize_with_wasm_opt(None);
59 }
60 CompileProfile::FastWithTraceLogs => {
61 compiler_builder.optimize_with_wasm_opt(None);
62 compiler_builder.log_level(Level::Trace); }
64 CompileProfile::FastWithNoLogs => {
65 compiler_builder.optimize_with_wasm_opt(None);
66 compiler_builder.disable_logs();
67 }
68 }
69
70 env_vars.iter().for_each(|(name, value)| {
71 compiler_builder.env(name, EnvironmentVariableAction::Set(value.clone()));
72 });
73
74 #[cfg(feature = "coverage")]
75 if _use_coverage {
76 compiler_builder.coverage();
77
78 let coverage_dir = std::path::PathBuf::from(package_dir.as_ref())
79 .join("target")
80 .join("coverage");
81 compiler_builder.target_directory(coverage_dir);
82 }
83
84 let mut compiler = compiler_builder
85 .build()
86 .unwrap_or_else(|err| panic!("Failed to initialize Scrypto Compiler {:?}", err));
87
88 #[cfg(feature = "coverage")]
89 if _use_coverage {
91 let manifest = compiler.get_main_manifest_definition();
92 if manifest.target_output_binary_rpd_path.exists()
93 && manifest.target_phase_2_build_wasm_output_path.exists()
94 {
95 let code = std::fs::read(&manifest.target_phase_2_build_wasm_output_path)
96 .unwrap_or_else(|err| {
97 panic!(
98 "Failed to read built WASM from path {:?} - {:?}",
99 &manifest.target_phase_2_build_wasm_output_path, err
100 )
101 });
102 let definition = std::fs::read(&manifest.target_output_binary_rpd_path)
103 .unwrap_or_else(|err| {
104 panic!(
105 "Failed to read package definition from path {:?} - {:?}",
106 &manifest.target_output_binary_rpd_path, err
107 )
108 });
109 let definition = manifest_decode::<ManifestPackageDefinition>(&definition)
110 .unwrap_or_else(|err| {
111 panic!(
112 "Failed to parse package definition from path {:?} - {:?}",
113 &manifest.target_output_binary_rpd_path, err
114 )
115 })
116 .try_into_typed()
117 .unwrap_or_else(|err| {
118 panic!(
119 "Failed to parse package definition from path {:?} - {:?}",
120 &manifest.target_output_binary_rpd_path, err
121 )
122 });
123 return (code, definition);
124 }
125 }
126
127 let mut build_artifacts = compiler.compile().unwrap_or_else(|error| {
129 if let ScryptoCompilerError::CargoBuildFailure(exit_code) = &error {
130 eprintln!("Package compilation error:\n{:?}", exit_code)
131 }
132
133 panic!(
134 "Failed to compile package: {:?}, error: {:?}",
135 package_dir.as_ref(),
136 error
137 );
138 });
139
140 if !build_artifacts.is_empty() {
141 let build_artifact = build_artifacts.remove(0); (
143 build_artifact.wasm.content,
144 build_artifact.package_definition.content,
145 )
146 } else {
147 panic!("Build artifacts list is empty: {:?}", package_dir.as_ref(),);
148 }
149 }
150}
151
152#[cfg(test)]
153mod tests {
154 use super::{Compile, CompileProfile};
155 use std::process::Command;
156
157 fn compile_blueprint(additional_args: &[&str]) -> Vec<u8> {
158 Command::new("cargo")
160 .arg("build")
161 .arg("--release")
162 .arg("--bin")
163 .arg("scrypto")
164 .current_dir(concat!(env!("CARGO_MANIFEST_DIR"), "/../radix-clis"))
165 .output()
166 .inspect_err(|e| println!("Scrypto cli build failed: {}", e))
167 .unwrap();
168
169 Command::new(concat!(
171 env!("CARGO_MANIFEST_DIR"),
172 "/../target/release/scrypto"
173 ))
174 .arg("build")
175 .args(additional_args)
176 .current_dir(concat!(
177 env!("CARGO_MANIFEST_DIR"),
178 "/tests/blueprints/tuple-return"
179 ))
180 .output()
181 .inspect_err(|e| println!("Blueprint compilation falied: {}", e))
182 .unwrap();
183
184 let output_file = concat!(
185 env!("CARGO_MANIFEST_DIR"),
186 "/tests/blueprints/target/wasm32-unknown-unknown/release/tuple_return.wasm"
187 );
188 std::fs::read(output_file)
189 .inspect_err(|e| println!("Failed to load file: {}, error: {}", output_file, e))
190 .unwrap()
191 }
192
193 #[test]
194 fn validate_compile_profile_standard() {
195 let output_file_content = compile_blueprint(&[]);
197
198 let (bin, _) = Compile::compile(
200 concat!(env!("CARGO_MANIFEST_DIR"), "/tests/blueprints/tuple-return"),
201 CompileProfile::Standard,
202 );
203
204 assert_eq!(
206 output_file_content.len(),
207 bin.len(),
208 "Wasm files should have same size."
209 );
210 assert_eq!(
211 output_file_content, bin,
212 "Wasm files should have same content."
213 )
214 }
215
216 #[test]
217 fn validate_compile_profile_standard_with_logs() {
218 let output_file_content = compile_blueprint(&[]);
220
221 let (bin, _) = Compile::compile(
223 concat!(env!("CARGO_MANIFEST_DIR"), "/tests/blueprints/tuple-return"),
224 CompileProfile::StandardWithTraceLogs,
225 );
226
227 assert!(
229 output_file_content.len() < bin.len(),
230 "Size of Wasm file compiled by `scrypto build` command should be smaller."
231 );
232 }
233
234 #[test]
235 fn validate_compile_profile_fast() {
236 let output_file_content = compile_blueprint(&[]);
238
239 let (bin, _) = Compile::compile(
241 concat!(env!("CARGO_MANIFEST_DIR"), "/tests/blueprints/tuple-return"),
242 CompileProfile::Fast,
243 );
244
245 assert!(
247 output_file_content.len() < bin.len(),
248 "Size of Wasm file compiled by `scrypto build` command should be smaller."
249 );
250 }
251
252 #[test]
253 fn validate_compile_profile_fast_with_logs() {
254 let output_file_content = compile_blueprint(&[]);
256
257 let (bin, _) = Compile::compile(
259 concat!(env!("CARGO_MANIFEST_DIR"), "/tests/blueprints/tuple-return"),
260 CompileProfile::FastWithTraceLogs,
261 );
262
263 assert!(
265 output_file_content.len() < bin.len(),
266 "Size of Wasm file compiled by `scrypto build` command should be smaller."
267 );
268 }
269
270 #[test]
271 fn verify_scrypto_build_with_args_for_compile_profile_standard_with_logs() {
272 let output_file_content = compile_blueprint(&["--log-level", "TRACE"]);
274
275 let (bin, _) = Compile::compile(
277 concat!(env!("CARGO_MANIFEST_DIR"), "/tests/blueprints/tuple-return"),
278 CompileProfile::StandardWithTraceLogs,
279 );
280
281 assert_eq!(
283 output_file_content.len(),
284 bin.len(),
285 "Wasm files should have same size."
286 );
287 assert_eq!(
288 output_file_content, bin,
289 "Wasm files should have same content."
290 )
291 }
292
293 #[test]
294 fn verify_scrypto_build_with_args_for_compile_profile_fast() {
295 let output_file_content = compile_blueprint(&["--disable-wasm-opt"]);
297
298 let (bin, _) = Compile::compile(
300 concat!(env!("CARGO_MANIFEST_DIR"), "/tests/blueprints/tuple-return"),
301 CompileProfile::Fast,
302 );
303
304 assert_eq!(
306 output_file_content.len(),
307 bin.len(),
308 "Wasm files should have same size."
309 );
310 assert_eq!(
311 output_file_content, bin,
312 "Wasm files should have same content."
313 )
314 }
315
316 #[test]
317 fn verify_scrypto_build_with_args_for_compile_profile_fast_with_logs() {
318 let output_file_content =
320 compile_blueprint(&["--disable-wasm-opt", "--log-level", "TRACE"]);
321
322 let (bin, _) = Compile::compile(
324 concat!(env!("CARGO_MANIFEST_DIR"), "/tests/blueprints/tuple-return"),
325 CompileProfile::FastWithTraceLogs,
326 );
327
328 assert_eq!(
330 output_file_content.len(),
331 bin.len(),
332 "Wasm files should have same size."
333 );
334 assert_eq!(
335 output_file_content, bin,
336 "Wasm files should have same content."
337 )
338 }
339}