canic_core/macros/
build.rs

1//! Build-script helpers that embed and validate `canic.toml`.
2
3/// Embed the shared Canic configuration into a canister crate's build script.
4///
5/// Reads the provided TOML file (relative to the crate manifest dir), validates it
6/// using [`Config`](crate::config::Config), and sets `CANIC_CONFIG_PATH` for
7/// later use by `include_str!`. Canister crates typically invoke this from
8/// `build.rs`.
9#[macro_export]
10macro_rules! build {
11    ($file:expr) => {{
12        $crate::__canic_build_internal! {
13            $file,
14            |cfg_str, cfg_path, cfg| {
15                let _ = (&cfg_str, &cfg_path, &cfg);
16            }
17        }
18    }};
19}
20
21/// Embed the shared configuration for the root orchestrator canister.
22///
23/// Performs the same validation as [`macro@build`].
24#[macro_export]
25macro_rules! build_root {
26    ($file:expr) => {{
27        $crate::__canic_build_internal! {
28            $file,
29            |_cfg_str, _cfg_path, _cfg| {}
30        }
31    }};
32}
33
34/// Internal helper shared by [`macro@build`] and [`macro@build_root`].
35#[doc(hidden)]
36#[macro_export]
37macro_rules! __canic_build_internal {
38    ($file:expr, |$cfg_str:ident, $cfg_path:ident, $cfg:ident| $body:block) => {{
39        let manifest_dir =
40            std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR must be set");
41        let $cfg_path = std::path::PathBuf::from(manifest_dir).join($file);
42        println!("cargo:rerun-if-changed={}", $cfg_path.display());
43        if let Some(parent) = $cfg_path.parent() {
44            println!("cargo:rerun-if-changed={}", parent.display());
45        }
46
47        let $cfg_str = match std::fs::read_to_string(&$cfg_path) {
48            Ok(s) => s,
49            Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
50                panic!("Missing Canic config at {}", $cfg_path.display())
51            }
52            Err(e) => panic!("Failed to read {}: {}", $cfg_path.display(), e),
53        };
54
55        // Init Config
56        let $cfg = canic::core::config::Config::init_from_toml(&$cfg_str)
57            .expect("Invalid Canic config");
58
59        // Run the extra body (per-canister or nothing)
60        $body
61
62        let abs = $cfg_path.canonicalize().expect("canonicalize canic config path");
63        println!("cargo:rustc-env=CANIC_CONFIG_PATH={}", abs.display());
64        println!("cargo:rerun-if-changed={}", abs.display());
65    }};
66}