xtask/tasks/fmt/house_rules/
cfg_target_arch.rs1use anyhow::anyhow;
5use fs_err::File;
6use std::io::BufRead;
7use std::io::BufReader;
8use std::path::Path;
9
10const SUPPRESS: &str = "xtask-fmt allow-target-arch";
11
12const SUPPRESS_REASON_CPU_INTRINSIC: &str = "cpu-intrinsic";
14const SUPPRESS_REASON_SYS_CRATE: &str = "sys-crate";
17const SUPPRESS_REASON_DEPENDENCY: &str = "dependency";
19const SUPPRESS_REASON_ONEOFF_GUEST_ARCH_IMPL: &str = "oneoff-guest-arch-impl";
22const SUPPRESS_REASON_ONEOFF_VIRT_HVF: &str = "oneoff-virt-hvf";
25const SUPPRESS_REASON_ONEOFF_FLOWEY: &str = "oneoff-flowey";
27const SUPPRESS_REASON_ONEOFF_PETRI_NATIVE_TEST_DEPS: &str = "oneoff-petri-native-test-deps";
29const SUPPRESS_REASON_ONEOFF_PETRI_HOST_ARCH: &str = "oneoff-petri-host-arch";
31
32fn has_suppress(s: &str) -> bool {
33 let Some((_, after)) = s.split_once(SUPPRESS) else {
34 return false;
35 };
36
37 let after = after.trim();
38 let justification = after.split(' ').next().unwrap();
39
40 let ok = matches!(
41 justification,
42 SUPPRESS_REASON_CPU_INTRINSIC
43 | SUPPRESS_REASON_SYS_CRATE
44 | SUPPRESS_REASON_DEPENDENCY
45 | SUPPRESS_REASON_ONEOFF_GUEST_ARCH_IMPL
46 | SUPPRESS_REASON_ONEOFF_VIRT_HVF
47 | SUPPRESS_REASON_ONEOFF_FLOWEY
48 | SUPPRESS_REASON_ONEOFF_PETRI_NATIVE_TEST_DEPS
49 | SUPPRESS_REASON_ONEOFF_PETRI_HOST_ARCH
50 );
51
52 if !ok {
53 log::error!(
54 "invalid justification '{}' (must be one of [sys-crate, cpu-intrinsic]",
55 after.split(' ').next().unwrap()
56 );
57 }
58
59 ok
60}
61
62pub fn check_cfg_target_arch(path: &Path, _fix: bool) -> anyhow::Result<()> {
63 let ext = path
64 .extension()
65 .and_then(|e| e.to_str())
66 .unwrap_or_default();
67
68 if !matches!(ext, "rs") {
69 return Ok(());
70 }
71
72 if path == Path::new(file!()) || path == Path::new(super::PATH_TO_HOUSE_RULES_RS) {
75 return Ok(());
76 }
77
78 if path.starts_with("guest_test_uefi")
94 || path.starts_with("openhcl/openhcl_boot")
95 || path.starts_with("openhcl/minimal_rt")
96 || path.starts_with("openhcl/sidecar")
97 || path.starts_with("support/safe_intrinsics")
98 || path.starts_with("tmk/simple_tmk")
99 || path.starts_with("tmk/tmk_core")
100 || path.starts_with("vm/whp")
101 || path.starts_with("vm/kvm")
102 {
103 return Ok(());
104 }
105
106 let mut error = false;
107
108 let f = BufReader::new(File::open(path)?);
110 let mut prev_line = String::new();
111 for (i, line) in f.lines().enumerate() {
112 let line = line?;
113 if line.contains("target_arch =") || line.contains("CARGO_CFG_TARGET_ARCH") {
114 if !line.trim().starts_with("//") && !has_suppress(&line) && !has_suppress(&prev_line) {
116 error = true;
117 log::error!(
118 "unjustified `cfg(target_arch = ...)`: {}:{}",
119 path.display(),
120 i + 1
121 );
122 }
123 }
124 prev_line = line;
125 }
126
127 if error {
128 Err(anyhow!(
129 "found unjustified uses of `cfg(target_arch = ...)` in {}",
130 path.display()
131 ))
132 } else {
133 Ok(())
134 }
135}