1 | //! Very basic parsing of `rustc` target triples. |
2 | //! |
3 | //! See the `target-lexicon` crate for a more principled approach to this. |
4 | |
5 | use std::str::FromStr; |
6 | |
7 | use crate::{Error, ErrorKind}; |
8 | |
9 | mod apple; |
10 | mod generated; |
11 | mod llvm; |
12 | mod parser; |
13 | |
14 | pub(crate) use parser::TargetInfoParser; |
15 | |
16 | /// Information specific to a `rustc` target. |
17 | /// |
18 | /// See <https://doc.rust-lang.org/cargo/appendix/glossary.html#target>. |
19 | #[derive (Debug, PartialEq, Clone)] |
20 | pub(crate) struct TargetInfo<'a> { |
21 | /// The full architecture, including the subarchitecture. |
22 | /// |
23 | /// This differs from `cfg!(target_arch)`, which only specifies the |
24 | /// overall architecture, which is too coarse for certain cases. |
25 | pub full_arch: &'a str, |
26 | /// The overall target architecture. |
27 | /// |
28 | /// This is the same as the value of `cfg!(target_arch)`. |
29 | pub arch: &'a str, |
30 | /// The target vendor. |
31 | /// |
32 | /// This is the same as the value of `cfg!(target_vendor)`. |
33 | pub vendor: &'a str, |
34 | /// The operating system, or `none` on bare-metal targets. |
35 | /// |
36 | /// This is the same as the value of `cfg!(target_os)`. |
37 | pub os: &'a str, |
38 | /// The environment on top of the operating system. |
39 | /// |
40 | /// This is the same as the value of `cfg!(target_env)`. |
41 | pub env: &'a str, |
42 | /// The ABI on top of the operating system. |
43 | /// |
44 | /// This is the same as the value of `cfg!(target_abi)`. |
45 | pub abi: &'a str, |
46 | /// The unversioned LLVM/Clang target triple. |
47 | /// |
48 | /// NOTE: You should never need to match on this explicitly, use the other |
49 | /// fields on [`TargetInfo`] instead. |
50 | pub llvm_target: &'a str, |
51 | } |
52 | |
53 | impl FromStr for TargetInfo<'_> { |
54 | type Err = Error; |
55 | |
56 | /// This will fail when using a custom target triple unknown to `rustc`. |
57 | fn from_str(target_triple: &str) -> Result<Self, Error> { |
58 | if let Ok(index) = |
59 | generated::LIST.binary_search_by_key(&target_triple, |(target_triple, _)| target_triple) |
60 | { |
61 | let (_, info) = &generated::LIST[index]; |
62 | Ok(info.clone()) |
63 | } else { |
64 | Err(Error::new( |
65 | ErrorKind::UnknownTarget, |
66 | format!( |
67 | "unknown target ` {target_triple}`. |
68 | |
69 | NOTE: `cc-rs` only supports a fixed set of targets when not in a build script. |
70 | - If adding a new target, you will need to fork of `cc-rs` until the target |
71 | has landed on nightly and the auto-generated list has been updated. See also |
72 | the `rustc` dev guide on adding a new target: |
73 | https://rustc-dev-guide.rust-lang.org/building/new-target.html |
74 | - If using a custom target, prefer to upstream it to `rustc` if possible, |
75 | otherwise open an issue with `cc-rs`: |
76 | https://github.com/rust-lang/cc-rs/issues/new |
77 | " |
78 | ), |
79 | )) |
80 | } |
81 | } |
82 | } |
83 | |
84 | #[cfg (test)] |
85 | mod tests { |
86 | use std::str::FromStr; |
87 | |
88 | use super::TargetInfo; |
89 | |
90 | // Test tier 1 targets |
91 | #[test ] |
92 | fn tier1() { |
93 | let targets = [ |
94 | "aarch64-unknown-linux-gnu" , |
95 | "aarch64-apple-darwin" , |
96 | "i686-pc-windows-gnu" , |
97 | "i686-pc-windows-msvc" , |
98 | "i686-unknown-linux-gnu" , |
99 | "x86_64-apple-darwin" , |
100 | "x86_64-pc-windows-gnu" , |
101 | "x86_64-pc-windows-msvc" , |
102 | "x86_64-unknown-linux-gnu" , |
103 | ]; |
104 | |
105 | for target in targets { |
106 | // Check that it parses |
107 | let _ = TargetInfo::from_str(target).unwrap(); |
108 | } |
109 | } |
110 | |
111 | // Various custom target triples not (or no longer) known by `rustc` |
112 | #[test ] |
113 | fn cannot_parse_extra() { |
114 | let targets = [ |
115 | "aarch64-unknown-none-gnu" , |
116 | "aarch64-uwp-windows-gnu" , |
117 | "arm-frc-linux-gnueabi" , |
118 | "arm-unknown-netbsd-eabi" , |
119 | "armv7neon-unknown-linux-gnueabihf" , |
120 | "armv7neon-unknown-linux-musleabihf" , |
121 | "thumbv7-unknown-linux-gnueabihf" , |
122 | "thumbv7-unknown-linux-musleabihf" , |
123 | "x86_64-rumprun-netbsd" , |
124 | "x86_64-unknown-linux" , |
125 | ]; |
126 | |
127 | for target in targets { |
128 | // Check that it does not parse |
129 | let _ = TargetInfo::from_str(target).unwrap_err(); |
130 | } |
131 | } |
132 | } |
133 | |