1 | // MIT License |
2 | // |
3 | // Copyright (c) Lukas Lueg <lukas.lueg@gmail.com> |
4 | // |
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy |
6 | // of this software and associated documentation files (the "Software"), to deal |
7 | // in the Software without restriction, including without limitation the rights |
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
9 | // copies of the Software, and to permit persons to whom the Software is |
10 | // furnished to do so, subject to the following conditions: |
11 | // |
12 | // The above copyright notice and this permission notice shall be included in all |
13 | // copies or substantial portions of the Software. |
14 | // |
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
21 | // SOFTWARE. |
22 | // |
23 | |
24 | #![allow (clippy::needless_doctest_main)] |
25 | |
26 | //! Provides a crate with information from the time it was built. |
27 | //! |
28 | //! `built` is used as a build-time dependency to collect various information |
29 | //! about the build-environment, serialize this information into Rust-code and |
30 | //! provide that to the crate. The information collected by `built` include: |
31 | //! |
32 | //! * Various metadata like version, authors, homepage etc. as set by `Cargo.toml` |
33 | //! * The tag or commit id if the crate was being compiled from within a Git repository. |
34 | //! * The values of `CARGO_CFG_*` build script environment variables, like `CARGO_CFG_TARGET_OS` and `CARGO_CFG_TARGET_ARCH`. |
35 | //! * The features the crate was compiled with. |
36 | //! * The various dependencies, dependencies of dependencies and their versions Cargo ultimately chose to compile. |
37 | //! * The presence of a CI-platform like `Github Actions`, `Travis CI` and `AppVeyor`. |
38 | //! * The compiler and it's version; the documentation-generator and it's version. |
39 | //! |
40 | //! `built` does not add any further runtime-dependencies to a crate; all information |
41 | //! is serialized as types from `stdlib`. One can include `built` as a |
42 | //! runtime-dependency and use it's convenience functions. |
43 | //! |
44 | //! To add `built` to a crate, add it as a build-time dependency, use a build-script |
45 | //! to collect and serialize the build-time information, and `include!` the generated code. |
46 | //! |
47 | //! Add this to `Cargo.toml`: |
48 | //! |
49 | //! ```toml |
50 | //! [package] |
51 | //! build = "build.rs" |
52 | //! |
53 | //! [build-dependencies] |
54 | //! built = "0.7" |
55 | //! ``` |
56 | //! |
57 | //! Add or modify a build-script. In `build.rs`: |
58 | //! |
59 | //! ```rust,no_run |
60 | //! fn main() { |
61 | //! built::write_built_file().expect("Failed to acquire build-time information" ); |
62 | //! } |
63 | //! ``` |
64 | //! |
65 | //! The build-script will by default write a file named `built.rs` into Cargo's output |
66 | //! directory. It can be picked up in `main.rs` (or anywhere else) like this: |
67 | //! |
68 | //! ```rust,ignore |
69 | //! // Use of a mod or pub mod is not actually necessary. |
70 | //! pub mod built_info { |
71 | //! // The file has been placed there by the build script. |
72 | //! include!(concat!(env!("OUT_DIR" ), "/built.rs" )); |
73 | //! } |
74 | //! ``` |
75 | //! |
76 | //! ...and then used somewhere in the crate's code: |
77 | //! |
78 | //! ```rust |
79 | //! # mod built_info { |
80 | //! # pub static PKG_VERSION_PRE: &str = "" ; |
81 | //! # pub static CI_PLATFORM: Option<&str> = None; |
82 | //! # pub static GIT_VERSION: Option<&str> = None; |
83 | //! # pub static DEPENDENCIES: [(&str, &str); 0] = []; |
84 | //! # pub static BUILT_TIME_UTC: &str = "Tue, 14 Feb 2017 05:21:41 GMT" ; |
85 | //! # } |
86 | //! # |
87 | //! # enum LogLevel { TRACE, ERROR }; |
88 | //! /// Determine if current version is a pre-release or was built from a git-repo |
89 | //! fn release_is_unstable() -> bool { |
90 | //! return !built_info::PKG_VERSION_PRE.is_empty() || built_info::GIT_VERSION.is_some() |
91 | //! } |
92 | //! |
93 | //! /// Default log-level, enhanced on CI |
94 | //! fn default_log_level() -> LogLevel { |
95 | //! if built_info::CI_PLATFORM.is_some() { |
96 | //! LogLevel::TRACE |
97 | //! } else { |
98 | //! LogLevel::ERROR |
99 | //! } |
100 | //! } |
101 | //! |
102 | //! /// The time this crate was built |
103 | //! #[cfg(feature = "chrono" )] |
104 | //! fn built_time() -> built::chrono::DateTime<built::chrono::Local> { |
105 | //! built::util::strptime(built_info::BUILT_TIME_UTC) |
106 | //! .with_timezone(&built::chrono::offset::Local) |
107 | //! } |
108 | //! |
109 | //! /// If another crate pulls in a dependency we don't like, print a warning |
110 | //! #[cfg(feature = "semver" )] |
111 | //! fn check_sane_dependencies() { |
112 | //! if built::util::parse_versions(&built_info::DEPENDENCIES) |
113 | //! .any(|(name, ver)| name == "DeleteAllMyFiles" |
114 | //! && ver < built::semver::Version::parse("1.1.4" ).unwrap()) { |
115 | //! eprintln!("DeleteAllMyFiles < 1.1.4 may not delete all your files. Beware!" ); |
116 | //! } |
117 | //! } |
118 | //! ``` |
119 | //! |
120 | //! --- |
121 | //! |
122 | //! ## Feature flags |
123 | //! The information that `built` collects and makes available in `built.rs` depends |
124 | //! on the features that were enabled on the build-time dependency. |
125 | //! |
126 | //! ### Always available |
127 | //! The following information is available regardless of feature-flags. |
128 | //! |
129 | //! ``` |
130 | //! /// The Continuous Integration platform detected during compilation. |
131 | //! pub static CI_PLATFORM: Option<&str> = None; |
132 | //! |
133 | //! /// The full version. |
134 | //! pub static PKG_VERSION: &str = "0.1.0" ; |
135 | //! /// The major version. |
136 | //! pub static PKG_VERSION_MAJOR: &str = "0" ; |
137 | //! /// The minor version. |
138 | //! pub static PKG_VERSION_MINOR: &str = "1" ; |
139 | //! /// "The patch version. |
140 | //! pub static PKG_VERSION_PATCH: &str = "0" ; |
141 | //! /// "The pre-release version. |
142 | //! pub static PKG_VERSION_PRE: &str = "" ; |
143 | //! |
144 | //! /// "A colon-separated list of authors. |
145 | //! pub static PKG_AUTHORS: &str = "Lukas Lueg <lukas.lueg@gmail.com>" ; |
146 | //! |
147 | //! /// The name of the package. |
148 | //! pub static PKG_NAME: &str = "example_project" ; |
149 | //! /// "The description. |
150 | //! pub static PKG_DESCRIPTION: &str = "" ; |
151 | //! /// "The homepage. |
152 | //! pub static PKG_HOMEPAGE: &str = "" ; |
153 | //! /// "The license. |
154 | //! pub static PKG_LICENSE: &str = "MIT" ; |
155 | //! /// The source repository as advertised in Cargo.toml. |
156 | //! pub static PKG_REPOSITORY: &str = "" ; |
157 | //! |
158 | //! /// The target triple that was being compiled for. |
159 | //! pub static TARGET: &str = "x86_64-unknown-linux-gnu" ; |
160 | //! /// The host triple of the rust compiler. |
161 | //! pub static HOST: &str = "x86_64-unknown-linux-gnu" ; |
162 | //! /// `release` for release builds, `debug` for other builds. |
163 | //! pub static PROFILE: &str = "debug" ; |
164 | //! |
165 | //! /// The compiler that cargo resolved to use. |
166 | //! pub static RUSTC: &str = "rustc" ; |
167 | //! /// The documentation-generator that cargo resolved to use. |
168 | //! pub static RUSTDOC: &str = "rustdoc" ; |
169 | //! /// The output of `rustc -V` |
170 | //! pub static RUSTC_VERSION: &str = "rustc 1.43.1 (8d69840ab 2020-05-04)" ; |
171 | //! /// The output of `rustdoc -V` |
172 | //! pub static RUSTDOC_VERSION: &str = "rustdoc 1.43.1 (8d69840ab 2020-05-04)" ; |
173 | //! |
174 | //! /// Value of OPT_LEVEL for the profile used during compilation. |
175 | //! pub static OPT_LEVEL: &str = "0" ; |
176 | //! /// The parallelism that was specified during compilation. |
177 | //! pub static NUM_JOBS: u32 = 8; |
178 | //! /// "Value of DEBUG for the profile used during compilation. |
179 | //! pub static DEBUG: bool = true; |
180 | //! |
181 | //! /// The features that were enabled during compilation. |
182 | //! pub static FEATURES: [&str; 0] = []; |
183 | //! /// The features as a comma-separated string. |
184 | //! pub static FEATURES_STR: &str = "" ; |
185 | //! /// The features as above, as lowercase strings. |
186 | //! pub static FEATURES_LOWERCASE: [&str; 0] = []; |
187 | //! /// The feature-string as above, from lowercase strings. |
188 | //! pub static FEATURES_LOWERCASE_STR: &str = "" ; |
189 | //! |
190 | //! /// The target architecture, given by `CARGO_CFG_TARGET_ARCH`. |
191 | //! pub static CFG_TARGET_ARCH: &str = "x86_64" ; |
192 | //! /// The endianness, given by `CARGO_CFG_TARGET_ENDIAN`. |
193 | //! pub static CFG_ENDIAN: &str = "little" ; |
194 | //! /// The toolchain-environment, given by `CARGO_CFG_TARGET_ENV`. |
195 | //! pub static CFG_ENV: &str = "gnu" ; |
196 | //! /// The OS-family, given by `CARGO_CFG_TARGET_FAMILY`. |
197 | //! pub static CFG_FAMILY: &str = "unix" ; |
198 | //! /// The operating system, given by `CARGO_CFG_TARGET_OS`. |
199 | //! pub static CFG_OS: &str = "linux" ; |
200 | //! /// The pointer width, given by `CARGO_CFG_TARGET_POINTER_WIDTH`. |
201 | //! pub static CFG_POINTER_WIDTH: &str = "64" ; |
202 | //! ``` |
203 | //! |
204 | //! ### `cargo-lock` |
205 | //! Parses `Cargo.lock`and generates representations of dependencies and their versions. |
206 | //! |
207 | //! For this to work, `Cargo.lock` needs to actually be there; this is (usually) |
208 | //! only true for executables and not for libraries. Cargo will only create a |
209 | //! `Cargo.lock` for the top-level crate in a dependency-tree. In case |
210 | //! of a library, the top-level crate will decide which crate/version |
211 | //! combination to compile and there will be no `Cargo.lock` while the library |
212 | //! gets compiled as a dependency. |
213 | //! |
214 | //! Parsing `Cargo.lock` instead of `Cargo.toml` allows to serialize the |
215 | //! precise versions Cargo chose to compile. One can't, however, distinguish |
216 | //! `build-dependencies`, `dev-dependencies` and `dependencies`. Furthermore, |
217 | //! some dependencies never show up if Cargo had not been forced to |
218 | //! actually use them (e.g. `dev-dependencies` with `cargo test` never |
219 | //! having been executed). |
220 | //! |
221 | //! Note that if the `dependency-tree`-feature is not active, the list of dependencies |
222 | //! contains the root-package(s) as well. |
223 | //! |
224 | //! ``` |
225 | //! /// An array of effective dependencies as documented by `Cargo.lock`. |
226 | //! pub static DEPENDENCIES: [(&str, &str); 37] = [("autocfg" , "1.0.0" ), ("bitflags" , "1.2.1" ), ("built" , "0.4.1" ), ("cargo-lock" , "4.0.1" ), ("cc" , "1.0.54" ), ("cfg-if" , "0.1.10" ), ("chrono" , "0.4.11" ), ("example_project" , "0.1.0" ), ("git2" , "0.13.6" ), ("idna" , "0.2.0" ), ("jobserver" , "0.1.21" ), ("libc" , "0.2.71" ), ("libgit2-sys" , "0.12.6+1.0.0" ), ("libz-sys" , "1.0.25" ), ("log" , "0.4.8" ), ("matches" , "0.1.8" ), ("num-integer" , "0.1.42" ), ("num-traits" , "0.2.11" ), ("percent-encoding" , "2.1.0" ), ("pkg-config" , "0.3.17" ), ("proc-macro2" , "1.0.17" ), ("quote" , "1.0.6" ), ("semver" , "1.0.0" ), ("serde" , "1.0.110" ), ("serde_derive" , "1.0.110" ), ("smallvec" , "1.4.0" ), ("syn" , "1.0.25" ), ("time" , "0.1.43" ), ("toml" , "0.5.6" ), ("unicode-bidi" , "0.3.4" ), ("unicode-normalization" , "0.1.12" ), ("unicode-xid" , "0.2.0" ), ("url" , "2.1.1" ), ("vcpkg" , "0.2.8" ), ("winapi" , "0.3.8" ), ("winapi-i686-pc-windows-gnu" , "0.4.0" ), ("winapi-x86_64-pc-windows-gnu" , "0.4.0" )]; |
227 | //! /// The effective dependencies as a comma-separated string. |
228 | //! pub static DEPENDENCIES_STR: &str = "autocfg 1.0.0, bitflags 1.2.1, built 0.4.1, cargo-lock 4.0.1, cc 1.0.54, cfg-if 0.1.10, chrono 0.4.11, example_project 0.1.0, git2 0.13.6, idna 0.2.0, jobserver 0.1.21, libc 0.2.71, libgit2-sys 0.12.6+1.0.0, libz-sys 1.0.25, log 0.4.8, matches 0.1.8, num-integer 0.1.42, num-traits 0.2.11, percent-encoding 2.1.0, pkg-config 0.3.17, proc-macro2 1.0.17, quote 1.0.6, semver 1.0.0, serde 1.0.110, serde_derive 1.0.110, smallvec 1.4.0, syn 1.0.25, time 0.1.43, toml 0.5.6, unicode-bidi 0.3.4, unicode-normalization 0.1.12, unicode-xid 0.2.0, url 2.1.1, vcpkg 0.2.8, winapi 0.3.8, winapi-i686-pc-windows-gnu 0.4.0, winapi-x86_64-pc-windows-gnu 0.4.0" ; |
229 | //! ``` |
230 | //! |
231 | //! ### `dependency-tree` (implies `cargo-lock`) |
232 | //! Solve the dependency-graph in `Cargo.lock` to discern direct and indirect |
233 | //! dependencies. |
234 | //! |
235 | //! "Direct" dependencies are those which the root-package(s) depends on. |
236 | //! "Indirect" dependencies are those which are not direct dependencies. |
237 | //! |
238 | //! ``` |
239 | //! /// An array of direct dependencies as documented by `Cargo.lock`. |
240 | //! pub static DIRECT_DEPENDENCIES: [(&str, &str); 1] = [("built" , "0.6.1" )]; |
241 | //! /// The direct dependencies as a comma-separated string. |
242 | //! pub static DIRECT_DEPENDENCIES_STR: &str = r"built 0.6.1" ; |
243 | //! |
244 | //! /// An array of indirect dependencies as documented by `Cargo.lock`. |
245 | //! pub static INDIRECT_DEPENDENCIES: [(&str, &str); 64] = [("android-tzdata" , "0.1.1" ), ("android_system_properties" , "0.1.5" ), ("autocfg" , "1.1.0" ), ("bitflags" , "2.4.0" ), ("bumpalo" , "3.13.0" ), ("cargo-lock" , "9.0.0" ), ("cc" , "1.0.83" ), ("cfg-if" , "1.0.0" ), ("chrono" , "0.4.29" ), ("core-foundation-sys" , "0.8.4" ), ("equivalent" , "1.0.1" ), ("example_project" , "0.1.0" ), ("fixedbitset" , "0.4.2" ), ("form_urlencoded" , "1.2.0" ), ("git2" , "0.18.0" ), ("hashbrown" , "0.14.0" ), ("iana-time-zone" , "0.1.57" ), ("iana-time-zone-haiku" , "0.1.2" ), ("idna" , "0.4.0" ), ("indexmap" , "2.0.0" ), ("jobserver" , "0.1.26" ), ("js-sys" , "0.3.64" ), ("libc" , "0.2.147" ), ("libgit2-sys" , "0.16.1+1.7.1" ), ("libz-sys" , "1.1.12" ), ("log" , "0.4.20" ), ("memchr" , "2.6.3" ), ("num-traits" , "0.2.16" ), ("once_cell" , "1.18.0" ), ("percent-encoding" , "2.3.0" ), ("petgraph" , "0.6.4" ), ("pkg-config" , "0.3.27" ), ("proc-macro2" , "1.0.66" ), ("quote" , "1.0.33" ), ("semver" , "1.0.18" ), ("serde" , "1.0.188" ), ("serde_derive" , "1.0.188" ), ("serde_spanned" , "0.6.3" ), ("syn" , "2.0.31" ), ("tinyvec" , "1.6.0" ), ("tinyvec_macros" , "0.1.1" ), ("toml" , "0.7.6" ), ("toml_datetime" , "0.6.3" ), ("toml_edit" , "0.19.14" ), ("unicode-bidi" , "0.3.13" ), ("unicode-ident" , "1.0.11" ), ("unicode-normalization" , "0.1.22" ), ("url" , "2.4.1" ), ("vcpkg" , "0.2.15" ), ("wasm-bindgen" , "0.2.87" ), ("wasm-bindgen-backend" , "0.2.87" ), ("wasm-bindgen-macro" , "0.2.87" ), ("wasm-bindgen-macro-support" , "0.2.87" ), ("wasm-bindgen-shared" , "0.2.87" ), ("windows" , "0.48.0" ), ("windows-targets" , "0.48.5" ), ("windows_aarch64_gnullvm" , "0.48.5" ), ("windows_aarch64_msvc" , "0.48.5" ), ("windows_i686_gnu" , "0.48.5" ), ("windows_i686_msvc" , "0.48.5" ), ("windows_x86_64_gnu" , "0.48.5" ), ("windows_x86_64_gnullvm" , "0.48.5" ), ("windows_x86_64_msvc" , "0.48.5" ), ("winnow" , "0.5.15" )]; |
246 | //! /// The indirect dependencies as a comma-separated string. |
247 | //! pub static INDIRECT_DEPENDENCIES_STR: &str = r"android-tzdata 0.1.1, android_system_properties 0.1.5, autocfg 1.1.0, bitflags 2.4.0, bumpalo 3.13.0, cargo-lock 9.0.0, cc 1.0.83, cfg-if 1.0.0, chrono 0.4.29, core-foundation-sys 0.8.4, equivalent 1.0.1, example_project 0.1.0, fixedbitset 0.4.2, form_urlencoded 1.2.0, git2 0.18.0, hashbrown 0.14.0, iana-time-zone 0.1.57, iana-time-zone-haiku 0.1.2, idna 0.4.0, indexmap 2.0.0, jobserver 0.1.26, js-sys 0.3.64, libc 0.2.147, libgit2-sys 0.16.1+1.7.1, libz-sys 1.1.12, log 0.4.20, memchr 2.6.3, num-traits 0.2.16, once_cell 1.18.0, percent-encoding 2.3.0, petgraph 0.6.4, pkg-config 0.3.27, proc-macro2 1.0.66, quote 1.0.33, semver 1.0.18, serde 1.0.188, serde_derive 1.0.188, serde_spanned 0.6.3, syn 2.0.31, tinyvec 1.6.0, tinyvec_macros 0.1.1, toml 0.7.6, toml_datetime 0.6.3, toml_edit 0.19.14, unicode-bidi 0.3.13, unicode-ident 1.0.11, unicode-normalization 0.1.22, url 2.4.1, vcpkg 0.2.15, wasm-bindgen 0.2.87, wasm-bindgen-backend 0.2.87, wasm-bindgen-macro 0.2.87, wasm-bindgen-macro-support 0.2.87, wasm-bindgen-shared 0.2.87, windows 0.48.0, windows-targets 0.48.5, windows_aarch64_gnullvm 0.48.5, windows_aarch64_msvc 0.48.5, windows_i686_gnu 0.48.5, windows_i686_msvc 0.48.5, windows_x86_64_gnu 0.48.5, windows_x86_64_gnullvm 0.48.5, windows_x86_64_msvc 0.48.5, winnow 0.5.15" ; |
248 | //! ``` |
249 | //! |
250 | //! ### `git2` |
251 | //! Try to open the git-repository at `manifest_location` and retrieve `HEAD` |
252 | //! tag or commit id. |
253 | //! |
254 | //! Notice that `GIT_HEAD_REF` is `None` if `HEAD` is detached or not valid UTF-8. |
255 | //! |
256 | //! Continuous Integration platforms like `Travis` and `AppVeyor` will |
257 | //! do shallow clones, causing `libgit2` to be unable to get a meaningful |
258 | //! result. `GIT_VERSION` and `GIT_DIRTY` will therefore always be `None` if |
259 | //! a CI-platform is detected. |
260 | //! ``` |
261 | //! /// If the crate was compiled from within a git-repository, |
262 | //! /// `GIT_VERSION` contains HEAD's tag. The short commit id is used |
263 | //! /// if HEAD is not tagged. |
264 | //! pub static GIT_VERSION: Option<&str> = Some("0.4.1-10-gca2af4f" ); |
265 | //! |
266 | //! /// If the repository had dirty/staged files. |
267 | //! pub static GIT_DIRTY: Option<bool> = Some(true); |
268 | //! |
269 | //! /// If the crate was compiled from within a git-repository, |
270 | //! /// `GIT_HEAD_REF` contains full name to the reference pointed to by |
271 | //! /// HEAD (e.g.: `refs/heads/master`). If HEAD is detached or the branch |
272 | //! /// name is not valid UTF-8 `None` will be stored. |
273 | //! pub static GIT_HEAD_REF: Option<&str> = Some("refs/heads/master" ); |
274 | //! |
275 | //! /// If the crate was compiled from within a git-repository, |
276 | //! /// `GIT_COMMIT_HASH` contains HEAD's full commit SHA-1 hash. |
277 | //! pub static GIT_COMMIT_HASH: Option<&str> = Some("ca2af4f11bb8f4f6421c4cccf428bf4862573daf" ); |
278 | //! |
279 | //! /// If the crate was compiled from within a git-repository, |
280 | //! /// `GIT_COMMIT_HASH_SHORT` contains HEAD's short commit SHA-1 hash. |
281 | //! pub static GIT_COMMIT_HASH_SHORT: Option<&str> = Some("ca2af4f" ); |
282 | //! ``` |
283 | //! |
284 | //! ### `chrono` |
285 | //! |
286 | //! The build-time is recorded as `BUILT_TIME_UTC`. If `built` is included as a runtime-dependency, |
287 | //! it can parse the string-representation into a `time:Tm` with the help of |
288 | //! `built::util::strptime()`. |
289 | //! |
290 | //! `built` honors the environment variable `SOURCE_DATE_EPOCH`. If the variable is defined and |
291 | //! parses to a valid UTC timestamp, that build-time is used instead of the current local time. |
292 | //! The variable is silently ignored if defined but but does not parse to a valid UTC timestamp. |
293 | //! |
294 | //! ``` |
295 | //! /// The built-time in RFC2822, UTC |
296 | //! pub static BUILT_TIME_UTC: &str = "Wed, 27 May 2020 18:12:39 +0000" ; |
297 | //! ``` |
298 | |
299 | #[cfg (feature = "cargo-lock" )] |
300 | mod dependencies; |
301 | mod environment; |
302 | #[cfg (feature = "git2" )] |
303 | mod git; |
304 | #[cfg (feature = "chrono" )] |
305 | mod krono; |
306 | pub mod util; |
307 | |
308 | use std::{env, fmt, fs, io, io::Write, path}; |
309 | |
310 | #[cfg (feature = "semver" )] |
311 | pub use semver; |
312 | |
313 | #[cfg (feature = "chrono" )] |
314 | pub use chrono; |
315 | |
316 | pub use environment::CIPlatform; |
317 | |
318 | #[doc = include_str!("../README.md" )] |
319 | #[allow (dead_code)] |
320 | type _READMETEST = (); |
321 | |
322 | /// If `SOURCE_DATE_EPOCH` is defined, it's value is used instead of |
323 | /// `chrono::..::now()` as `BUILT_TIME_UTC`. |
324 | /// The presence of `SOURCE_DATE_EPOCH` also soft-indicates that a |
325 | /// reproducible build is desired, which we may or may not be able |
326 | /// to honor. |
327 | const SOURCE_DATE_EPOCH: &str = "SOURCE_DATE_EPOCH" ; |
328 | |
329 | macro_rules! write_variable { |
330 | ($writer:expr, $name:expr, $datatype:expr, $value:expr, $doc:expr) => { |
331 | writeln!( |
332 | $writer, |
333 | "#[doc=r# \"{} \"#] \n#[allow(dead_code)] \npub static {}: {} = {};" , |
334 | $doc, $name, $datatype, $value |
335 | )?; |
336 | }; |
337 | } |
338 | pub(crate) use write_variable; |
339 | |
340 | macro_rules! write_str_variable { |
341 | ($writer:expr, $name:expr, $value:expr, $doc:expr) => { |
342 | write_variable!( |
343 | $writer, |
344 | $name, |
345 | "&str" , |
346 | format_args!(" \"{} \"" , $value.escape_default()), |
347 | $doc |
348 | ); |
349 | }; |
350 | } |
351 | pub(crate) use write_str_variable; |
352 | |
353 | pub(crate) fn fmt_option_str<S: fmt::Display>(o: Option<S>) -> String { |
354 | match o { |
355 | Some(s: S) => format!("Some( \"{s}\")" ), |
356 | None => "None" .to_owned(), |
357 | } |
358 | } |
359 | |
360 | /// Writes rust-code describing the crate at `manifest_location` to a new file named `dst`. |
361 | /// |
362 | /// # Errors |
363 | /// The function returns an error if the file at `dst` already exists or can't |
364 | /// be written to. This should not be a concern if the filename points to |
365 | /// `OUR_DIR`. |
366 | pub fn write_built_file_with_opts( |
367 | #[cfg (any(feature = "cargo-lock" , feature = "git2" ))] manifest_location: Option<&path::Path>, |
368 | dst: &path::Path, |
369 | ) -> io::Result<()> { |
370 | let mut built_file = fs::File::create(dst)?; |
371 | built_file.write_all( |
372 | r#"// |
373 | // EVERYTHING BELOW THIS POINT WAS AUTO-GENERATED DURING COMPILATION. DO NOT MODIFY. |
374 | // |
375 | "# |
376 | .as_ref(), |
377 | )?; |
378 | |
379 | let envmap = environment::EnvironmentMap::new(); |
380 | envmap.write_ci(&built_file)?; |
381 | envmap.write_env(&built_file)?; |
382 | envmap.write_features(&built_file)?; |
383 | envmap.write_compiler_version(&built_file)?; |
384 | envmap.write_cfg(&built_file)?; |
385 | |
386 | #[cfg (feature = "git2" )] |
387 | { |
388 | if let Some(manifest_location) = manifest_location { |
389 | git::write_git_version(manifest_location, &built_file)?; |
390 | } |
391 | } |
392 | |
393 | #[cfg (feature = "cargo-lock" )] |
394 | if let Some(manifest_location) = manifest_location { |
395 | dependencies::write_dependencies(manifest_location, &built_file)?; |
396 | } |
397 | |
398 | #[cfg (feature = "chrono" )] |
399 | krono::write_time(&built_file)?; |
400 | |
401 | built_file.write_all( |
402 | r#"// |
403 | // EVERYTHING ABOVE THIS POINT WAS AUTO-GENERATED DURING COMPILATION. DO NOT MODIFY. |
404 | // |
405 | "# |
406 | .as_ref(), |
407 | )?; |
408 | Ok(()) |
409 | } |
410 | |
411 | /// A shorthand for calling `write_built_file_with_opts()` with `CARGO_MANIFEST_DIR` and |
412 | /// `[OUT_DIR]/built.rs`. |
413 | /// |
414 | /// # Errors |
415 | /// Same as `write_built_file_with_opts()`. |
416 | /// |
417 | /// # Panics |
418 | /// If `CARGO_MANIFEST_DIR` or `OUT_DIR` are not set. |
419 | pub fn write_built_file() -> io::Result<()> { |
420 | let dst: PathBuf = path::Path::new(&env::var("OUT_DIR" ).expect("OUT_DIR not set" )).join(path:"built.rs" ); |
421 | write_built_file_with_opts( |
422 | #[cfg (any(feature = "cargo-lock" , feature = "git2" ))] |
423 | Some( |
424 | env::var("CARGO_MANIFEST_DIR" ) |
425 | .expect("CARGO_MANIFEST_DIR" ) |
426 | .as_ref(), |
427 | ), |
428 | &dst, |
429 | )?; |
430 | Ok(()) |
431 | } |
432 | |