1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/*!
Common types used by the `build-info` and `build-info-build` crates.

User code should not depend on this crate directly, but rather depend on `build-info` (as a `[dependency]`) and `build-info-build` (as a `[build-dependency]`).
The types provided herein are reexported by `build-info` and should be used that way.
For example, `build_info_common::BuildInfo` should be used as `build_info::BuildInfo` instead.
*/

#![forbid(unsafe_code)]

pub use chrono;
use chrono::{DateTime, NaiveDate, Utc};
use derive_more::Display;
pub use semver;
use semver::Version;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

#[cfg(feature = "serde")]
mod versioned_string;
#[cfg(feature = "serde")]
pub use versioned_string::VersionedString;

mod display;

/// Gets the version of the `build-info-common` crate (this crate)
pub fn crate_version() -> Version {
	Version::parse(env!("CARGO_PKG_VERSION")).unwrap()
}

/// Information about the current build
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct BuildInfo {
	/// Updated whenever `build.rs` is rerun.
	pub timestamp: DateTime<Utc>,

	/// Cargo currently supports two different build types: `"Release"` and `"Debug"`
	pub profile: String,

	/// The optimization level can be set in `Cargo.toml` for each profile
	pub optimization_level: OptimizationLevel,

	/// Information about the current crate
	pub crate_info: CrateInfo,

	/// Information about the target system
	pub target: TargetInfo,

	/// Information about the compiler used
	pub compiler: CompilerInfo,

	/// `Some` if the project is inside a check-out of a supported version control system
	pub version_control: Option<VersionControl>,
}

/// The various possible optimization levels
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum OptimizationLevel {
	O0,
	O1,
	O2,
	O3,
	Os,
	Oz,
}

/// Information about the current crate (i.e., the crate for which build information has been generated)
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct CrateInfo {
	/// The name, as defined in `Cargo.toml`.
	pub name: String,

	/// The version, as defined in `Cargo.toml`.
	pub version: Version,

	/// The authors, as defined in `Cargo.toml`.
	pub authors: Vec<String>,

	/// The license string, as defined in `Cargo.toml`.
	pub license: Option<String>,

	/// The features of this crate that are currently enabled in this configuration.
	pub enabled_features: Vec<String>,

	/// All features that are available from this crate.
	pub available_features: Vec<String>,

	/// Dependencies of this crate.
	/// Will only be filled with data if `collect_dependencies(true)` was called on `build_script()`.
	pub dependencies: Vec<CrateInfo>,
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct TargetInfo {
	/// Identifies the target architecture for which the crate is being compiled
	pub triple: String,
	/// A generic description of the target, e.g., `"unix"` or `"wasm"`
	pub family: String,
	/// The target OS
	pub os: String,
	/// The target CPU
	pub cpu: CpuInfo,
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct CpuInfo {
	/// The CPU target architecture
	pub arch: String,
	/// The CPU pointer width
	pub pointer_width: u64,
	/// The CPU target endianness
	pub endianness: Endianness,
	///  List of CPU target features enabled
	pub features: Vec<String>,
}

/// CPU Endianness
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Display, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum Endianness {
	Big,
	Little,
}

/// `rustc` version and configuration
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct CompilerInfo {
	/// Version of the current `rustc`
	pub version: Version,

	/// Commit hash from which `rustc` was built
	pub commit_id: Option<String>,

	/// Date on which `rustc` was built
	pub commit_date: Option<NaiveDate>,

	/// Channel which was configured for this version of `rustc`
	pub channel: CompilerChannel,

	/// Identifies the host on which `rustc` was running
	pub host_triple: String,
}

/// `rustc` distribution channel (some compiler features are only available on specific channels)
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Display, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum CompilerChannel {
	Dev,
	Nightly,
	Beta,
	Stable,
}

/// Support for different version control systems
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum VersionControl {
	Git(GitInfo),
}

impl VersionControl {
	pub fn git(&self) -> Option<&GitInfo> {
		match self {
			VersionControl::Git(git) => Some(git),
			// _ => None, // Pattern currently unreachable
		}
	}
}

/**
Information about a git repository

If a git repository is detected (and, thereby, this information included), the build script will be rerun whenever the
currently checked out commit changes.
*/
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct GitInfo {
	/// Full commit hash for the currently checked out commit
	pub commit_id: String,

	/// Short commit hash for the currently checked out commit
	///
	/// The length of this string depends on the effective value of the git configuration variable `core.abbrev`, and is
	/// extended to the minimum length required for the id to be unique (at the time it was computed).
	pub commit_short_id: String,

	/// Timestamp of the currently checked out commit
	pub commit_timestamp: DateTime<Utc>,

	/// `true` iff the repository had uncommitted changes when building the project.
	pub dirty: bool,

	/// Names the branch that is currently checked out, if any
	pub branch: Option<String>,

	/// All tags that point to the current commit (e.g., `["v0.0.10", "sample@v0.0.10"]`)
	pub tags: Vec<String>,
}