1use crate::{
5 Error, TargetSpec,
6 platform::{Platform, TargetFeatures},
7};
8
9pub fn eval(spec_or_triple: &str, platform: &str) -> Result<Option<bool>, Error> {
19 let target_spec = spec_or_triple.parse::<TargetSpec>()?;
20 let platform = Platform::new(platform.to_owned(), TargetFeatures::Unknown)?;
21 Ok(target_spec.eval(&platform))
22}
23
24#[cfg(test)]
25mod tests {
26 use super::*;
27
28 #[test]
29 fn test_windows() {
30 assert_eq!(
31 eval("cfg(windows)", "x86_64-pc-windows-msvc").unwrap(),
32 Some(true),
33 );
34 }
35
36 #[test]
37 fn test_not_target_os() {
38 assert_eq!(
39 eval(
40 "cfg(not(target_os = \"windows\"))",
41 "x86_64-unknown-linux-gnu"
42 )
43 .unwrap(),
44 Some(true),
45 );
46 }
47
48 #[test]
49 fn test_not_target_os_false() {
50 assert_eq!(
51 eval(
52 "cfg(not(target_os = \"windows\"))",
53 "x86_64-pc-windows-msvc"
54 )
55 .unwrap(),
56 Some(false),
57 );
58 }
59
60 #[test]
61 fn test_exact_triple() {
62 assert_eq!(
63 eval("x86_64-unknown-linux-gnu", "x86_64-unknown-linux-gnu").unwrap(),
64 Some(true),
65 );
66 }
67
68 #[test]
69 fn test_redox() {
70 assert_eq!(
71 eval(
72 "cfg(any(unix, target_os = \"redox\"))",
73 "x86_64-unknown-linux-gnu"
74 )
75 .unwrap(),
76 Some(true),
77 );
78 }
79
80 #[test]
81 fn test_bogus_families() {
82 for family in &["test", "debug_assertions", "proc_macro"] {
84 let cfg = format!("cfg({})", family);
85 let cfg_not = format!("cfg(not({}))", family);
86 assert_eq!(eval(&cfg, "x86_64-unknown-linux-gnu").unwrap(), Some(false));
87 assert_eq!(
88 eval(&cfg_not, "x86_64-unknown-linux-gnu").unwrap(),
89 Some(true)
90 );
91 }
92
93 let platform = Platform::new("x86_64-unknown-linux-gnu", TargetFeatures::Unknown).unwrap();
95 let mut platform_with_flags = platform.clone();
96 platform_with_flags.add_flags(["foo", "bar"].iter().copied());
97
98 for family in &["foo", "bar"] {
99 let cfg = format!("cfg({})", family);
100 let cfg_not = format!("cfg(not({}))", family);
101
102 assert_eq!(eval(&cfg, "x86_64-unknown-linux-gnu").unwrap(), Some(false));
104 assert_eq!(
105 eval(&cfg_not, "x86_64-unknown-linux-gnu").unwrap(),
106 Some(true)
107 );
108
109 let spec: TargetSpec = cfg.parse().unwrap();
110 let spec_not: TargetSpec = cfg_not.parse().unwrap();
111
112 assert_eq!(spec.eval(&platform), Some(false));
114 assert_eq!(spec_not.eval(&platform), Some(true));
115
116 assert_eq!(spec.eval(&platform_with_flags), Some(true));
118 assert_eq!(spec_not.eval(&platform_with_flags), Some(false));
119 }
120
121 for family in &["baz", "nonsense"] {
122 let cfg = format!("cfg({})", family);
123 let cfg_not = format!("cfg(not({}))", family);
124
125 assert_eq!(eval(&cfg, "x86_64-unknown-linux-gnu").unwrap(), Some(false));
127 assert_eq!(
128 eval(&cfg_not, "x86_64-unknown-linux-gnu").unwrap(),
129 Some(true)
130 );
131
132 let spec: TargetSpec = cfg.parse().unwrap();
133 let spec_not: TargetSpec = cfg_not.parse().unwrap();
134
135 assert_eq!(spec.eval(&platform), Some(false));
137 assert_eq!(spec_not.eval(&platform), Some(true));
138
139 assert_eq!(spec.eval(&platform_with_flags), Some(false));
141 assert_eq!(spec_not.eval(&platform_with_flags), Some(true));
142 }
143 }
144
145 #[test]
146 fn test_target_feature() {
147 assert_eq!(
149 eval("cfg(target_feature = \"sse\")", "x86_64-unknown-linux-gnu").unwrap(),
150 None,
151 );
152 assert_eq!(
153 eval(
154 "cfg(target_feature = \"atomics\")",
155 "x86_64-unknown-linux-gnu",
156 )
157 .unwrap(),
158 None,
159 );
160 assert_eq!(
161 eval(
162 "cfg(not(target_feature = \"fxsr\"))",
163 "x86_64-unknown-linux-gnu",
164 )
165 .unwrap(),
166 None,
167 );
168
169 fn eval_unknown(spec: &str, platform: &str) -> Option<bool> {
170 let platform = Platform::new(
171 platform.to_owned(),
172 TargetFeatures::features(["sse", "sse2"].iter().copied()),
173 )
174 .expect("platform should be found");
175 let spec: TargetSpec = spec.parse().unwrap();
176 spec.eval(&platform)
177 }
178
179 assert_eq!(
180 eval_unknown("cfg(target_feature = \"sse\")", "x86_64-unknown-linux-gnu"),
181 Some(true),
182 );
183 assert_eq!(
184 eval_unknown(
185 "cfg(not(target_feature = \"sse\"))",
186 "x86_64-unknown-linux-gnu",
187 ),
188 Some(false),
189 );
190 assert_eq!(
191 eval_unknown("cfg(target_feature = \"fxsr\")", "x86_64-unknown-linux-gnu"),
192 Some(false),
193 );
194 assert_eq!(
195 eval_unknown(
196 "cfg(not(target_feature = \"fxsr\"))",
197 "x86_64-unknown-linux-gnu",
198 ),
199 Some(true),
200 );
201
202 fn eval_all(spec: &str, platform: &str) -> Option<bool> {
203 let platform = Platform::new(platform.to_owned(), TargetFeatures::All)
204 .expect("platform should be found");
205 let spec: TargetSpec = spec.parse().unwrap();
206 spec.eval(&platform)
207 }
208
209 assert_eq!(
210 eval_all("cfg(target_feature = \"sse\")", "x86_64-unknown-linux-gnu"),
211 Some(true),
212 );
213 assert_eq!(
214 eval_all(
215 "cfg(not(target_feature = \"sse\"))",
216 "x86_64-unknown-linux-gnu",
217 ),
218 Some(false),
219 );
220 assert_eq!(
221 eval_all("cfg(target_feature = \"fxsr\")", "x86_64-unknown-linux-gnu"),
222 Some(true),
223 );
224 assert_eq!(
225 eval_all(
226 "cfg(not(target_feature = \"fxsr\"))",
227 "x86_64-unknown-linux-gnu",
228 ),
229 Some(false),
230 );
231 }
232}