canic_testkit/artifacts/
wasm.rs1use super::workspace::prebuilt_wasm_dir;
2use std::{
3 fs,
4 path::{Path, PathBuf},
5 process::Command,
6};
7
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
13pub enum WasmBuildProfile {
14 Debug,
15 Release,
16}
17
18impl WasmBuildProfile {
19 #[must_use]
21 pub const fn cargo_flag(self) -> Option<&'static str> {
22 match self {
23 Self::Debug => None,
24 Self::Release => Some("--release"),
25 }
26 }
27
28 #[must_use]
30 pub const fn target_dir_name(self) -> &'static str {
31 match self {
32 Self::Debug => "debug",
33 Self::Release => "release",
34 }
35 }
36
37 #[must_use]
39 pub const fn dfx_release_value(self) -> &'static str {
40 match self {
41 Self::Debug => "0",
42 Self::Release => "1",
43 }
44 }
45}
46
47#[must_use]
49pub fn wasm_path(
50 target_dir: &Path,
51 crate_name: &str,
52 profile: WasmBuildProfile,
53 prebuilt_env_var: &str,
54) -> PathBuf {
55 if let Some(dir) = prebuilt_wasm_dir(prebuilt_env_var) {
56 return dir.join(format!("{crate_name}.wasm"));
57 }
58
59 target_dir
60 .join("wasm32-unknown-unknown")
61 .join(profile.target_dir_name())
62 .join(format!("{crate_name}.wasm"))
63}
64
65#[must_use]
67pub fn wasm_artifacts_ready(
68 target_dir: &Path,
69 canisters: &[&str],
70 profile: WasmBuildProfile,
71 prebuilt_env_var: &str,
72) -> bool {
73 canisters
74 .iter()
75 .all(|name| wasm_path(target_dir, name, profile, prebuilt_env_var).is_file())
76}
77
78#[must_use]
80pub fn read_wasm(
81 target_dir: &Path,
82 crate_name: &str,
83 profile: WasmBuildProfile,
84 prebuilt_env_var: &str,
85) -> Vec<u8> {
86 let path = wasm_path(target_dir, crate_name, profile, prebuilt_env_var);
87 fs::read(&path).unwrap_or_else(|err| panic!("failed to read {crate_name} wasm: {err}"))
88}
89
90pub fn build_wasm_canisters(
92 workspace_root: &Path,
93 target_dir: &Path,
94 packages: &[&str],
95 profile: WasmBuildProfile,
96 extra_env: &[(&str, &str)],
97) {
98 let mut cmd = Command::new("cargo");
99 cmd.current_dir(workspace_root);
100 cmd.env("CARGO_TARGET_DIR", target_dir);
101 cmd.env("DFX_NETWORK", "local");
102 cmd.args(["build", "--target", "wasm32-unknown-unknown"]);
103
104 if let Some(flag) = profile.cargo_flag() {
105 cmd.arg(flag);
106 }
107
108 for (key, value) in extra_env {
109 cmd.env(key, value);
110 }
111
112 for name in packages {
113 cmd.args(["-p", name]);
114 }
115
116 let output = cmd.output().expect("failed to run cargo build");
117 assert!(
118 output.status.success(),
119 "cargo build failed: {}",
120 String::from_utf8_lossy(&output.stderr)
121 );
122}