platforms/platform.rs
1//! Rust platforms
2
3mod platforms;
4
5#[cfg(feature = "std")]
6mod req;
7mod tier;
8
9pub use self::tier::Tier;
10
11#[cfg(feature = "std")]
12pub use self::req::PlatformReq;
13
14use self::platforms::ALL;
15use crate::target::*;
16use core::fmt;
17
18/// Rust platforms supported by mainline rustc
19///
20/// Sourced from <https://doc.rust-lang.org/nightly/rustc/platform-support.html>
21/// as well as the latest nightly version of `rustc`
22#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
23#[non_exhaustive]
24pub struct Platform {
25 /// "Target triple" string uniquely identifying the platform. See:
26 /// <https://github.com/rust-lang/rfcs/blob/master/text/0131-target-specification.md>
27 ///
28 /// These are defined in the `rustc_target` crate of the Rust compiler:
29 /// <https://github.com/rust-lang/rust/blob/master/src/librustc_target/spec/mod.rs>
30 pub target_triple: &'static str,
31
32 /// Target architecture `cfg` attribute (i.e. `cfg(target_arch)`)
33 pub target_arch: Arch,
34
35 /// Target OS `cfg` attribute (i.e. `cfg(target_os)`).
36 pub target_os: OS,
37
38 /// Target environment `cfg` attribute (i.e. `cfg(target_env)`).
39 /// Only used when needed for disambiguation, e.g. on many GNU platforms
40 /// this value will be `None`.
41 pub target_env: Env,
42
43 /// Target pointer width `cfg` attribute, in bits (i.e. `cfg(target_pointer_width)`).
44 /// Typically 64 on modern platforms, 32 on older platforms, 16 on some microcontrollers.
45 pub target_pointer_width: PointerWidth,
46
47 /// Target [endianness](https://en.wikipedia.org/wiki/Endianness) `cfg` attribute (i.e. `cfg(target_endian)`).
48 /// Set to "little" on the vast majority of modern platforms.
49 pub target_endian: Endian,
50
51 /// Tier of this platform:
52 ///
53 /// - `Tier::One`: guaranteed to work
54 /// - `Tier::Two`: guaranteed to build
55 /// - `Tier::Three`: unofficially supported with no guarantees
56 pub tier: Tier,
57}
58
59impl Platform {
60 /// All valid Rust platforms usable from the mainline compiler.
61 ///
62 /// Note that this list will evolve over time, and platforms will be both added and removed.
63 pub const ALL: &'static [Platform] = ALL;
64
65 /// Find a Rust platform by its "target triple", e.g. `i686-apple-darwin`
66 pub fn find(target_triple: &str) -> Option<&'static Platform> {
67 Self::ALL
68 .iter()
69 .find(|platform| platform.target_triple == target_triple)
70 }
71}
72
73impl fmt::Display for Platform {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 f.write_str(self.target_triple)
76 }
77}
78
79#[cfg(all(test, feature = "std"))]
80mod tests {
81 use super::Platform;
82 use std::collections::HashSet;
83
84 /// Ensure there are no duplicate target triples in the platforms list
85 #[test]
86 fn no_dupes_test() {
87 let mut target_triples = HashSet::new();
88
89 for platform in Platform::ALL {
90 assert!(
91 target_triples.insert(platform.target_triple),
92 "duplicate target triple: {}",
93 platform.target_triple
94 );
95 }
96 }
97
98 use std::collections::HashMap;
99
100 use super::*;
101
102 /// `platforms` v2.0 used to provide various constants passed as `cfg` values,
103 /// and attempted to detect the target triple based on that.
104 /// This test is meant to check whether such detection can be accurate.
105 ///
106 /// Turns out that as of v3.0 this is infeasible,
107 /// even though the list of supported cfg values was expanded.
108 ///
109 /// I have also verified that no possible expansion of the supported cfg fields
110 /// will lets uniquely identify the platform based on cfg values using a shell script:
111 /// `rustc --print=target-list | parallel 'rustc --print=cfg --target={} > ./{}'; fdupes`
112 #[test]
113 #[ignore]
114 fn test_detection_feasibility() {
115 let mut all_platforms = HashMap::new();
116 for p in ALL {
117 if let Some(other_p) = all_platforms.insert(
118 (
119 p.target_arch,
120 p.target_os,
121 p.target_env,
122 p.target_endian,
123 p.target_pointer_width,
124 ),
125 p.target_triple,
126 ) {
127 panic!("{} and {} have identical properties, and cannot be distinguished based on properties alone", p.target_triple, other_p);
128 }
129 }
130 }
131}