cabin_core/compiler/
validation.rs1use thiserror::Error;
4
5use super::capabilities::{ArchiverCapabilities, CompilerCapabilities};
6use super::identity::{ArchiverIdentity, ArchiverKind, CompilerIdentity, CompilerKind};
7
8#[derive(Debug, Error, Clone, PartialEq, Eq)]
11pub enum ToolDetectionError {
12 #[error("selected C++ compiler `{spec}` cannot be matched to a supported C++ backend")]
13 UnsupportedCxxBackend { spec: String },
14
15 #[error(
16 "selected C++ compiler `{spec}` could not be identified and the current backend requires GCC-style flags"
17 )]
18 UnknownCxxRequiresGccStyle { spec: String },
19
20 #[error(
21 "selected C++ compiler `{spec}` ({kind}) does not support the required C++17 standard flag"
22 )]
23 CxxLacksStdCxx17 { spec: String, kind: CompilerKind },
24
25 #[error(
26 "selected C++ compiler `{spec}` ({kind}) does not support the depfile flags required by the Ninja backend"
27 )]
28 CxxLacksDepfile { spec: String, kind: CompilerKind },
29
30 #[error("selected C compiler `{spec}` cannot be matched to a supported C backend")]
31 UnsupportedCBackend { spec: String },
32
33 #[error(
34 "selected C compiler `{spec}` could not be identified and the current backend requires GCC-style flags"
35 )]
36 UnknownCRequiresGccStyle { spec: String },
37
38 #[error(
39 "selected C compiler `{spec}` ({kind}) does not support the depfile flags required by the Ninja backend"
40 )]
41 CLacksDepfile { spec: String, kind: CompilerKind },
42
43 #[error(
44 "selected C compiler `{spec}` ({kind}) does not support the required C11 standard flag (MSVC `/std:c11` needs VS2019 16.8 / `cl` 19.28 or newer)"
45 )]
46 CLacksStdC11 { spec: String, kind: CompilerKind },
47
48 #[error("selected archiver `{spec}` is not supported by the static-library backend")]
49 UnsupportedArchiver { spec: String },
50
51 #[error(
52 "selected archiver `{spec}` could not be identified and the current backend requires `ar crs`-compatible behavior"
53 )]
54 UnknownArchiverRequiresArCompatible { spec: String },
55}
56
57pub fn validate_cxx_for_backend(
74 spec_display: &str,
75 identity: &CompilerIdentity,
76 capabilities: &CompilerCapabilities,
77) -> Result<(), ToolDetectionError> {
78 if identity.kind.speaks_msvc_dialect() {
84 if !capabilities.msvc_style_flags.supported {
85 return Err(ToolDetectionError::UnsupportedCxxBackend {
86 spec: spec_display.to_owned(),
87 });
88 }
89 if !capabilities.cxx_standard_17.supported {
90 return Err(ToolDetectionError::CxxLacksStdCxx17 {
91 spec: spec_display.to_owned(),
92 kind: identity.kind,
93 });
94 }
95 return Ok(());
96 }
97 if !capabilities.gcc_style_flags.supported {
98 if identity.kind == CompilerKind::Unknown {
99 return Err(ToolDetectionError::UnknownCxxRequiresGccStyle {
100 spec: spec_display.to_owned(),
101 });
102 }
103 return Err(ToolDetectionError::UnsupportedCxxBackend {
104 spec: spec_display.to_owned(),
105 });
106 }
107 if !capabilities.depfile_mmd_mf.supported {
108 return Err(ToolDetectionError::CxxLacksDepfile {
109 spec: spec_display.to_owned(),
110 kind: identity.kind,
111 });
112 }
113 if !capabilities.cxx_standard_17.supported {
114 return Err(ToolDetectionError::CxxLacksStdCxx17 {
115 spec: spec_display.to_owned(),
116 kind: identity.kind,
117 });
118 }
119 Ok(())
120}
121
122pub fn validate_cc_for_backend(
138 spec_display: &str,
139 identity: &CompilerIdentity,
140 capabilities: &CompilerCapabilities,
141) -> Result<(), ToolDetectionError> {
142 if identity.kind.speaks_msvc_dialect() {
148 if !capabilities.msvc_style_flags.supported {
149 return Err(ToolDetectionError::UnsupportedCBackend {
150 spec: spec_display.to_owned(),
151 });
152 }
153 if !capabilities.c_standard_11.supported {
154 return Err(ToolDetectionError::CLacksStdC11 {
155 spec: spec_display.to_owned(),
156 kind: identity.kind,
157 });
158 }
159 return Ok(());
160 }
161 if !capabilities.gcc_style_flags.supported {
162 if identity.kind == CompilerKind::Unknown {
163 return Err(ToolDetectionError::UnknownCRequiresGccStyle {
164 spec: spec_display.to_owned(),
165 });
166 }
167 return Err(ToolDetectionError::UnsupportedCBackend {
168 spec: spec_display.to_owned(),
169 });
170 }
171 if !capabilities.depfile_mmd_mf.supported {
172 return Err(ToolDetectionError::CLacksDepfile {
173 spec: spec_display.to_owned(),
174 kind: identity.kind,
175 });
176 }
177 Ok(())
178}
179
180pub fn validate_ar_for_backend(
191 spec_display: &str,
192 identity: &ArchiverIdentity,
193 capabilities: &ArchiverCapabilities,
194) -> Result<(), ToolDetectionError> {
195 if identity.kind == ArchiverKind::Lib {
198 return Ok(());
199 }
200 if !capabilities.ar_crs.supported {
201 if identity.kind == ArchiverKind::Unknown {
202 return Err(ToolDetectionError::UnknownArchiverRequiresArCompatible {
203 spec: spec_display.to_owned(),
204 });
205 }
206 return Err(ToolDetectionError::UnsupportedArchiver {
207 spec: spec_display.to_owned(),
208 });
209 }
210 Ok(())
211}