Skip to main content

ic_testkit/artifacts/
wasm.rs

1use std::{
2    fs,
3    path::{Path, PathBuf},
4    process::Command,
5};
6
7/// Resolve one crate's Wasm artifact under a caller-selected Cargo target directory.
8#[must_use]
9pub fn wasm_path(target_dir: &Path, crate_name: &str, profile_target_dir: &str) -> PathBuf {
10    target_dir
11        .join("wasm32-unknown-unknown")
12        .join(profile_target_dir)
13        .join(format!("{crate_name}.wasm"))
14}
15
16/// Check whether every requested Wasm artifact is a regular file.
17#[must_use]
18pub fn wasm_artifacts_ready(
19    target_dir: &Path,
20    canisters: &[&str],
21    profile_target_dir: &str,
22) -> bool {
23    canisters
24        .iter()
25        .all(|name| wasm_path(target_dir, name, profile_target_dir).is_file())
26}
27
28/// Read a compiled Wasm artifact for one crate.
29///
30/// # Panics
31///
32/// Panics with the crate name when the artifact cannot be read.
33#[must_use]
34pub fn read_wasm(target_dir: &Path, crate_name: &str, profile_target_dir: &str) -> Vec<u8> {
35    let path = wasm_path(target_dir, crate_name, profile_target_dir);
36    fs::read(&path).unwrap_or_else(|err| panic!("failed to read {crate_name} wasm: {err}"))
37}
38
39/// Build one or more Wasm canisters into the provided target directory.
40///
41/// `cargo_profile_args` accepts Cargo flags such as `--release`. `extra_env`
42/// applies only to the child Cargo process and does not mutate the current
43/// process environment.
44///
45/// # Panics
46///
47/// Panics when Cargo cannot be launched or returns a failing status.
48pub fn build_wasm_canisters(
49    workspace_root: &Path,
50    target_dir: &Path,
51    packages: &[&str],
52    cargo_profile_args: &[&str],
53    extra_env: &[(&str, &str)],
54) {
55    let mut cmd = cargo_command();
56    cmd.current_dir(workspace_root);
57    cmd.env("CARGO_TARGET_DIR", target_dir);
58    cmd.args(["build", "--target", "wasm32-unknown-unknown"]);
59    cmd.args(cargo_profile_args);
60
61    for (key, value) in extra_env {
62        cmd.env(key, value);
63    }
64
65    for name in packages {
66        cmd.args(["-p", name]);
67    }
68
69    let output = cmd.output().expect("failed to run cargo build");
70    assert!(
71        output.status.success(),
72        "cargo build failed: {}",
73        String::from_utf8_lossy(&output.stderr)
74    );
75}
76
77fn cargo_command() -> Command {
78    let cargo = std::env::var_os("CARGO").unwrap_or_else(|| "cargo".into());
79    let mut command = Command::new(cargo);
80
81    if let Some(toolchain) = std::env::var_os("RUSTUP_TOOLCHAIN") {
82        command.env("RUSTUP_TOOLCHAIN", toolchain);
83    }
84
85    command
86}