vergen_lib/entries.rs
1use crate::VergenKey;
2
3use anyhow::{Error, Result};
4use std::collections::BTreeMap;
5
6/// The map used to emit `cargo:rustc-env=NAME=VALUE` cargo instructions
7pub type CargoRustcEnvMap = BTreeMap<VergenKey, String>;
8/// The vector of strings used to emit `cargo:rerun-if-changed=VALUE` cargo instructions
9pub type CargoRerunIfChanged = Vec<String>;
10/// The vector of strings used to emit `cargo:warning=VALUE` cargo instructions
11pub type CargoWarning = Vec<String>;
12
13/// The default configuration to use when an issue has occured generating instructions
14#[derive(Debug)]
15pub struct DefaultConfig {
16 /// Should we fail if an error occurs or output idempotent values on error?
17 fail_on_error: bool,
18 /// The error that caused us to try default instruction output.
19 error: Error,
20}
21
22impl DefaultConfig {
23 /// Create a new [`DefaultConfig`] struct with the given values.
24 #[must_use]
25 pub fn new(fail_on_error: bool, error: Error) -> Self {
26 Self {
27 fail_on_error,
28 error,
29 }
30 }
31 /// Should we fail if an error occurs or output idempotent values on error?
32 #[must_use]
33 pub fn fail_on_error(&self) -> &bool {
34 &self.fail_on_error
35 }
36 /// The error that caused us to try default instruction output.
37 #[must_use]
38 pub fn error(&self) -> &Error {
39 &self.error
40 }
41}
42
43/// This trait should be implemented to allow the `vergen` emitter
44/// to properly emit instructions for your feature.
45pub trait Add {
46 /// Try to add instructions entries to the various given arguments.
47 ///
48 /// * Write to the `cargo_rustc_env` map to emit 'cargo:rustc-env=NAME=VALUE' instructions.
49 /// * Write to the `cargo_rerun_if_changed` vector to emit 'cargo:rerun-if-changed=VALUE' instructions.
50 /// * Write to the `cargo_warning` vector to emit 'cargo:warning=VALUE' instructions.
51 ///
52 /// # Errors
53 ///
54 /// If an error occurs, the `vergen` emitter will use `add_default_entries` to generate output.
55 /// This assumes generating instructions may fail in some manner so a [`anyhow::Result`] is returned.
56 ///
57 fn add_map_entries(
58 &self,
59 idempotent: bool,
60 cargo_rustc_env: &mut CargoRustcEnvMap,
61 cargo_rerun_if_changed: &mut CargoRerunIfChanged,
62 cargo_warning: &mut CargoWarning,
63 ) -> Result<()>;
64
65 /// Based on the given configuration, emit either default idempotent output or generate a failue.
66 ///
67 /// * Write to the `cargo_rustc_env` map to emit 'cargo:rustc-env=NAME=VALUE' instructions.
68 /// * Write to the `cargo_rerun_if_changed` vector to emit 'cargo:rerun-if-changed=VALUE' instructions.
69 /// * Write to the `cargo_warning` vector to emit 'cargo:warning=VALUE' instructions.
70 ///
71 /// # Errors
72 ///
73 /// This assumes generating instructions may fail in some manner so a [`anyhow::Result`] is returned.
74 ///
75 fn add_default_entries(
76 &self,
77 config: &DefaultConfig,
78 cargo_rustc_env_map: &mut CargoRustcEnvMap,
79 cargo_rerun_if_changed: &mut CargoRerunIfChanged,
80 cargo_warning: &mut CargoWarning,
81 ) -> Result<()>;
82}
83
84/// This trait should be implemented to allow the `vergen` emitter to properly emit your custom instructions.
85///
86/// # Example
87/// ```
88/// # use anyhow::Result;
89/// # use std::collections::BTreeMap;
90/// # use vergen_lib::{AddCustomEntries, CargoRerunIfChanged, CargoWarning, DefaultConfig};
91/// #[derive(Default)]
92/// struct Custom {}
93///
94/// impl AddCustomEntries<&str, &str> for Custom {
95/// fn add_calculated_entries(
96/// &self,
97/// _idempotent: bool,
98/// cargo_rustc_env_map: &mut BTreeMap<&str, &str>,
99/// _cargo_rerun_if_changed: &mut CargoRerunIfChanged,
100/// cargo_warning: &mut CargoWarning,
101/// ) -> Result<()> {
102/// cargo_rustc_env_map.insert("vergen-cl", "custom_instruction");
103/// cargo_warning.push("custom instruction generated".to_string());
104/// Ok(())
105/// }
106///
107/// fn add_default_entries(
108/// &self,
109/// _config: &DefaultConfig,
110/// _cargo_rustc_env_map: &mut BTreeMap<&str, &str>,
111/// _cargo_rerun_if_changed: &mut CargoRerunIfChanged,
112/// _cargo_warning: &mut CargoWarning,
113/// ) -> Result<()> {
114/// Ok(())
115/// }
116/// }
117/// ```
118/// ## Then in [`build.rs`]
119///
120/// ```will_not_compile
121/// let build = BuildBuilder::all_build()?;
122/// let cargo = CargoBuilder::all_cargo()?;
123/// let gix = GixBuilder::all_git()?;
124/// let rustc = RustcBuilder::all_rustc()?;
125/// let si = SysinfoBuilder::all_sysinfo()?;
126/// Emitter::default()
127/// .add_instructions(&build)?
128/// .add_instructions(&cargo)?
129/// .add_instructions(&gix)?
130/// .add_instructions(&rustc)?
131/// .add_instructions(&si)?
132/// .add_custom_instructions(&Custom::default())?
133/// .emit()
134/// ```
135pub trait AddCustom<K: Into<String> + Ord, V: Into<String>> {
136 /// Try to add instructions entries to the various given arguments.
137 ///
138 /// * Write to the `cargo_rustc_env` map to emit 'cargo:rustc-env=NAME=VALUE' instructions.
139 /// * Write to the `cargo_rerun_if_changed` vector to emit 'cargo:rerun-if-changed=VALUE' instructions.
140 /// * Write to the `cargo_warning` vector to emit 'cargo:warning=VALUE' instructions.
141 ///
142 /// # Errors
143 ///
144 /// If an error occurs, the `vergen` emitter will use `add_default_entries` to generate output.
145 /// This assumes generating instructions may fail in some manner so a [`anyhow::Result`] is returned.
146 ///
147 fn add_calculated_entries(
148 &self,
149 idempotent: bool,
150 cargo_rustc_env_map: &mut BTreeMap<K, V>,
151 cargo_rerun_if_changed: &mut CargoRerunIfChanged,
152 cargo_warning: &mut CargoWarning,
153 ) -> Result<()>;
154
155 /// Based on the given configuration, emit either default idempotent output or generate a failue.
156 ///
157 /// * Write to the `cargo_rustc_env` map to emit 'cargo:rustc-env=NAME=VALUE' instructions.
158 /// * Write to the `cargo_rerun_if_changed` vector to emit 'cargo:rerun-if-changed=VALUE' instructions.
159 /// * Write to the `cargo_warning` vector to emit 'cargo:warning=VALUE' instructions.
160 ///
161 /// # Errors
162 ///
163 /// This assumes generating instructions may fail in some manner so a [`anyhow::Result`] is returned.
164 ///
165 fn add_default_entries(
166 &self,
167 config: &DefaultConfig,
168 cargo_rustc_env_map: &mut BTreeMap<K, V>,
169 cargo_rerun_if_changed: &mut CargoRerunIfChanged,
170 cargo_warning: &mut CargoWarning,
171 ) -> Result<()>;
172}
173
174#[doc(hidden)]
175pub(crate) mod test_gen {
176 use crate::{AddCustomEntries, CargoRerunIfChanged, CargoWarning};
177 use anyhow::{anyhow, Result};
178 use derive_builder::Builder;
179 use std::collections::BTreeMap;
180
181 #[doc(hidden)]
182 #[derive(Builder, Clone, Copy, Debug, Default)]
183 pub struct CustomInsGen {
184 fail: bool,
185 }
186
187 impl AddCustomEntries<&str, &str> for CustomInsGen {
188 fn add_calculated_entries(
189 &self,
190 idempotent: bool,
191 cargo_rustc_env_map: &mut BTreeMap<&str, &str>,
192 _cargo_rerun_if_changed: &mut CargoRerunIfChanged,
193 _cargo_warning: &mut CargoWarning,
194 ) -> Result<()> {
195 if self.fail {
196 Err(anyhow!("We have failed"))
197 } else {
198 if idempotent {
199 let _ = cargo_rustc_env_map.insert("test", "VERGEN_IDEMPOTENT_OUTPUT");
200 } else {
201 let _ = cargo_rustc_env_map.insert("test", "value");
202 }
203 Ok(())
204 }
205 }
206
207 fn add_default_entries(
208 &self,
209 config: &crate::DefaultConfig,
210 cargo_rustc_env_map: &mut BTreeMap<&str, &str>,
211 _cargo_rerun_if_changed: &mut CargoRerunIfChanged,
212 _cargo_warning: &mut CargoWarning,
213 ) -> Result<()> {
214 if *config.fail_on_error() {
215 let error = anyhow!(format!("{}", config.error()));
216 Err(error)
217 } else {
218 let _ = cargo_rustc_env_map.insert("test", "VERGEN_IDEMPOTENT_OUTPUT");
219 Ok(())
220 }
221 }
222 }
223}
224
225#[cfg(test)]
226mod test {
227 use super::DefaultConfig;
228 use anyhow::{anyhow, Result};
229 use std::io::Write;
230
231 #[test]
232 fn default_config_debug() -> Result<()> {
233 let config = DefaultConfig::new(true, anyhow!("blah"));
234 let mut buf = vec![];
235 write!(buf, "{config:?}")?;
236 assert!(!buf.is_empty());
237 Ok(())
238 }
239}