build_info/lib.rs
1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Provides build metadata
5
6#![expect(missing_docs)]
7
8use inspect::Inspect;
9
10#[derive(Debug, Inspect)]
11pub struct BuildInfo {
12 #[inspect(safe)]
13 crate_name: &'static str,
14 #[inspect(safe, rename = "scm_revision")]
15 revision: &'static str,
16 #[inspect(safe, rename = "scm_branch")]
17 branch: &'static str,
18 #[inspect(safe)]
19 internal_scm_revision: &'static str,
20 #[inspect(safe)]
21 internal_scm_branch: &'static str,
22 #[inspect(safe)]
23 openhcl_version: &'static str,
24}
25
26impl BuildInfo {
27 pub const fn new() -> Self {
28 // TODO: Once Option::unwrap_or() is stable in the const context
29 // can replace the if statements with it.
30 // Deliberately not storing `Option` to the build information
31 // structure to be closer to PODs.
32 Self {
33 crate_name: env!("CARGO_PKG_NAME"),
34 revision: if let Some(r) = option_env!("VERGEN_GIT_SHA") {
35 r
36 } else {
37 ""
38 },
39 branch: if let Some(b) = option_env!("VERGEN_GIT_BRANCH") {
40 b
41 } else {
42 ""
43 },
44 internal_scm_revision: if let Some(r) = option_env!("INTERNAL_GIT_SHA") {
45 r
46 } else {
47 ""
48 },
49 internal_scm_branch: if let Some(r) = option_env!("INTERNAL_GIT_BRANCH") {
50 r
51 } else {
52 ""
53 },
54 openhcl_version: if let Some(r) = option_env!("OPENHCL_VERSION") {
55 r
56 } else {
57 ""
58 },
59 }
60 }
61
62 pub fn crate_name(&self) -> &'static str {
63 self.crate_name
64 }
65
66 pub fn scm_revision(&self) -> &'static str {
67 self.revision
68 }
69
70 pub fn scm_branch(&self) -> &'static str {
71 self.branch
72 }
73}
74
75// Placing into a separate section to make easier to discover
76// the build information even without a debugger.
77//
78// The #[used] attribute is not used as the static is reachable
79// via a public function.
80//
81// The #[external_name] attribute is used to give the static
82// an unmangled name and again be easily discoverable even without
83// a debugger. With a debugger, the non-mangled name is easier
84// to use.
85
86// UNSAFETY: link_section and export_name are unsafe.
87#[expect(unsafe_code)]
88// SAFETY: The build_info section is custom and carries no safety requirements.
89#[unsafe(link_section = ".build_info")]
90// SAFETY: The name "BUILD_INFO" is only declared here in OpenHCL and shouldn't
91// collide with any other symbols. It is a special symbol intended for
92// post-mortem debugging, and no runtime functionality should depend on it.
93#[unsafe(export_name = "BUILD_INFO")]
94static BUILD_INFO: BuildInfo = BuildInfo::new();
95
96pub fn get() -> &'static BuildInfo {
97 // Without `black_box`, BUILD_INFO is optimized away
98 // in the release builds with `fat` LTO.
99 std::hint::black_box(&BUILD_INFO)
100}