devela/build/
utils.rs

1// devela build::utils
2//
3//! build script utility functions
4//
5// TOC
6// - directories
7// - print
8// - other
9//
10// TODO
11// - show compilation date
12// - embed to be able to make docima work
13//   - how can I depend on external crates?
14//   - optional build-dependencies?
15
16#![allow(dead_code)]
17
18use std::{env, path::PathBuf};
19
20// TODO
21// pub use devela_imports::*;
22// /// These are re-imports from devela
23// mod devela_imports {
24//     #![allow(unused)]
25//
26//     // macros copied from `devela::src::code`
27//     macro_rules! include_from {
28//         ($module_name:ident) => {
29//             include!(concat!(std::env!("CARGO_MANIFEST_DIR"), "/", stringify!($module_name), ".rs"));
30//         };
31//         ($module_path_str:literal) => {
32//             include!(concat!(std::env!("CARGO_MANIFEST_DIR"), "/", $module_path_str));
33//         };
34//     }
35//     macro_rules! mod_from {
36//         ($vis:vis $module_name:ident) => {
37//             $vis mod $module_name { include_from!($module_name); }
38//         };
39//         ($vis:vis $module_name:ident, $module_path_str:literal) => {
40//             $vis mod $module_name { include_from!($module_path_str); }
41//         };
42//     }
43//
44//     // TODO: need: base64
45//     // include_from!{ "src/code/util/docima.rs" }
46//     mod_from!{ docima, "src/code/util/docima.rs" }
47//     pub use docima::*;
48// }
49
50/* directories */
51
52/// Retuns the path of `OUT_DIR`.
53pub(crate) fn out_dir() -> PathBuf {
54    PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR not set"))
55}
56
57/// Retuns the path of `CARGO_MANIFEST_DIR`.
58pub(crate) fn manifest_dir() -> PathBuf {
59    PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"))
60}
61
62/// Retuns the path of `CARGO_MANIFEST_PATH`.
63pub(crate) fn manifest_path() -> PathBuf {
64    PathBuf::from(env::var("CARGO_MANIFEST_PATH").expect("CARGO_MANIFEST_PATH not set"))
65}
66
67/* print */
68
69/// Prints a message to *stdout* from the build script.
70#[cfg(feature = "__dbg")]
71#[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "__dbg")))]
72pub(crate) fn println(msg: &str) {
73    println!("cargo:warning={}", msg);
74}
75
76/// Prints a heading message to *stdout*, underlined.
77#[cfg(feature = "__dbg")]
78#[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "__dbg")))]
79pub(crate) fn println_heading(msg: &str) {
80    println("");
81    println(msg);
82    println(&"-".repeat(msg.len()));
83}
84
85/// Prints the value of an environment variable.
86#[cfg(feature = "__dbg")]
87#[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "__dbg")))]
88pub(crate) fn println_var(var: &str) {
89    if let Ok(v) = env::var(var) {
90        println(&format!["· {var}: {v}"]);
91    } else {
92        // println(&format!["Environment variable `{var}` not set"]);
93        println(&format!["x {var}:"]);
94    }
95}
96/// Prints the value of an encoded environment variable,
97/// replacing unit separator characters `'0x1f'` with spaces.
98///
99/// It accepts a new name to show for the decoded variable.
100#[cfg(feature = "__dbg")]
101#[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "__dbg")))]
102pub(crate) fn println_var_encoded(var: &str, new_var_name: &str) {
103    if let Ok(ev) = env::var(var) {
104        let v = ev.replace('\x1f', " ");
105        println(&format!["· {new_var_name}(*): {v}"]);
106    } else {
107        // println(&format!["Environment variable `{var}` not set"]);
108        println(&format!["x {new_var_name}:"]);
109    }
110}
111
112/// Prints the build script `start` or end message to *stdout*.
113#[cfg(feature = "__dbg")]
114#[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "__dbg")))]
115pub(crate) fn println_start_end(start: bool) {
116    let msg = if start {
117        "~ Start of build script ~"
118    } else {
119        println("");
120        "~ End of build script ~"
121    };
122    let line = "~".repeat(msg.len());
123    println(&line);
124    println(msg);
125    println(&line);
126}
127
128/* other */
129
130// EMBED date
131// - https://users.rust-lang.org/t/how-can-i-include-the-build-date-in-an-executable/102024
132// - https://reproducible-builds.org/docs/source-date-epoch/#rust
133// - https://chatgpt.com/g/g-p-675d4e88ef7881919667bbc6666f0e5c-devela/c/67a48a9c-96c8-8007-85dc-25e17a72caf5
134//
135//   println!("cargo:rustc-env=DATE={}", date); in build.rs
136//   env!("DATE") in main.rs or something
137//
138//
139// EMBED GIT COMMIT
140// - https://stackoverflow.com/questions/43753491/include-git-commit-hash-as-string-into-rust-program/44407625#44407625
141
142// skip formatting macro.
143macro_rules! sf { ( $($line:tt)+ ) => { $($line)+ }; }
144
145sf! {
146#[doc = "0 tabs, 0 spaces."]  pub(crate) const TAB0: &str = "";
147#[doc = "1 tabs, 4 spaces."]  pub(crate) const TAB1: &str = "    ";
148#[doc = "2 tabs, 8 spaces."]  pub(crate) const TAB2: &str = "        ";
149#[doc = "3 tabs, 12 spaces."] pub(crate) const TAB3: &str = "            ";
150#[doc = "4 tabs, 16 spaces."] pub(crate) const TAB4: &str = "                ";
151#[doc = "5 tabs, 20 spaces."] pub(crate) const TAB5: &str = "                    ";
152#[doc = "6 tabs, 24 spaces."] pub(crate) const TAB6: &str = "                        ";
153#[doc = "7 tabs, 28 spaces."] pub(crate) const TAB7: &str = "                            ";
154#[doc = "8 tabs, 32 spaces."] pub(crate) const TAB8: &str = "                                ";
155#[doc = "9 tabs, 36 spaces."] pub(crate) const TAB9: &str = "                                    ";
156}