Skip to main content

canic_host/canister_build/
context.rs

1use std::{env, fs, path::PathBuf};
2
3use crate::{
4    icp_environment_from_env,
5    release_set::{icp_root, workspace_root},
6};
7
8use super::{
9    CanisterBuildProfile,
10    process::{icp_ancestor_process_id, parent_process_id},
11};
12
13/// WorkspaceBuildContext
14///
15
16#[derive(Clone, Debug, Eq, PartialEq)]
17pub struct WorkspaceBuildContext {
18    pub profile: String,
19    pub requested_profile: String,
20    pub network: String,
21    pub workspace_root: PathBuf,
22    pub icp_root: PathBuf,
23}
24
25impl WorkspaceBuildContext {
26    #[must_use]
27    pub fn lines(&self) -> Vec<String> {
28        let mut lines = vec![
29            "Canic build:".to_string(),
30            format!("profile: {}", self.profile),
31            format!("network: {}", self.network),
32            format!("workspace: {}", self.workspace_root.display()),
33        ];
34
35        if self.requested_profile != "unset" {
36            lines.push(format!("requested profile: {}", self.requested_profile));
37        }
38        if self.icp_root != self.workspace_root {
39            lines.push(format!("icp root: {}", self.icp_root.display()));
40        }
41
42        lines
43    }
44}
45
46// Print the current build context once per caller session so caller builds
47// stay readable without repeating root/profile diagnostics for every canister.
48pub fn print_current_workspace_build_context_once(
49    profile: CanisterBuildProfile,
50) -> Result<(), Box<dyn std::error::Error>> {
51    if let Some(context) = current_workspace_build_context_once(profile)? {
52        eprintln!("{}", context.lines().join("\n"));
53    }
54
55    Ok(())
56}
57
58// Return the current build context once per caller session.
59pub fn current_workspace_build_context_once(
60    profile: CanisterBuildProfile,
61) -> Result<Option<WorkspaceBuildContext>, Box<dyn std::error::Error>> {
62    let workspace_root = workspace_root()?;
63    let icp_root = icp_root()?;
64    let marker_dir = icp_root.join(".icp");
65    fs::create_dir_all(&marker_dir)?;
66
67    let requested_profile = env::var("CANIC_WASM_PROFILE").unwrap_or_else(|_| "unset".to_string());
68    let network = icp_environment_from_env();
69    let marker_key = icp_ancestor_process_id()
70        .or_else(parent_process_id)
71        .unwrap_or_else(std::process::id)
72        .to_string();
73    let marker_file = marker_dir.join(format!(".canic-build-context-{marker_key}"));
74
75    if marker_file.exists() {
76        return Ok(None);
77    }
78
79    fs::write(&marker_file, [])?;
80    Ok(Some(WorkspaceBuildContext {
81        profile: profile.target_dir_name().to_string(),
82        requested_profile,
83        network,
84        workspace_root,
85        icp_root,
86    }))
87}