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}