use thiserror::Error;
use super::capabilities::{ArchiverCapabilities, CompilerCapabilities};
use super::identity::{ArchiverIdentity, ArchiverKind, CompilerIdentity, CompilerKind};
#[derive(Debug, Error, Clone, PartialEq, Eq)]
pub enum ToolDetectionError {
#[error("selected C++ compiler `{spec}` cannot be matched to a supported C++ backend")]
UnsupportedCxxBackend { spec: String },
#[error(
"selected C++ compiler `{spec}` could not be identified and the current backend requires GCC-style flags"
)]
UnknownCxxRequiresGccStyle { spec: String },
#[error(
"selected C++ compiler `{spec}` ({kind}) does not support the required C++17 standard flag"
)]
CxxLacksStdCxx17 { spec: String, kind: CompilerKind },
#[error(
"selected C++ compiler `{spec}` ({kind}) does not support the depfile flags required by the Ninja backend"
)]
CxxLacksDepfile { spec: String, kind: CompilerKind },
#[error("selected C compiler `{spec}` cannot be matched to a supported C backend")]
UnsupportedCBackend { spec: String },
#[error(
"selected C compiler `{spec}` could not be identified and the current backend requires GCC-style flags"
)]
UnknownCRequiresGccStyle { spec: String },
#[error(
"selected C compiler `{spec}` ({kind}) does not support the depfile flags required by the Ninja backend"
)]
CLacksDepfile { spec: String, kind: CompilerKind },
#[error(
"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)"
)]
CLacksStdC11 { spec: String, kind: CompilerKind },
#[error("selected archiver `{spec}` is not supported by the static-library backend")]
UnsupportedArchiver { spec: String },
#[error(
"selected archiver `{spec}` could not be identified and the current backend requires `ar crs`-compatible behavior"
)]
UnknownArchiverRequiresArCompatible { spec: String },
}
pub fn validate_cxx_for_backend(
spec_display: &str,
identity: &CompilerIdentity,
capabilities: &CompilerCapabilities,
) -> Result<(), ToolDetectionError> {
if identity.kind.speaks_msvc_dialect() {
if !capabilities.msvc_style_flags.supported {
return Err(ToolDetectionError::UnsupportedCxxBackend {
spec: spec_display.to_owned(),
});
}
if !capabilities.cxx_standard_17.supported {
return Err(ToolDetectionError::CxxLacksStdCxx17 {
spec: spec_display.to_owned(),
kind: identity.kind,
});
}
return Ok(());
}
if !capabilities.gcc_style_flags.supported {
if identity.kind == CompilerKind::Unknown {
return Err(ToolDetectionError::UnknownCxxRequiresGccStyle {
spec: spec_display.to_owned(),
});
}
return Err(ToolDetectionError::UnsupportedCxxBackend {
spec: spec_display.to_owned(),
});
}
if !capabilities.depfile_mmd_mf.supported {
return Err(ToolDetectionError::CxxLacksDepfile {
spec: spec_display.to_owned(),
kind: identity.kind,
});
}
if !capabilities.cxx_standard_17.supported {
return Err(ToolDetectionError::CxxLacksStdCxx17 {
spec: spec_display.to_owned(),
kind: identity.kind,
});
}
Ok(())
}
pub fn validate_cc_for_backend(
spec_display: &str,
identity: &CompilerIdentity,
capabilities: &CompilerCapabilities,
) -> Result<(), ToolDetectionError> {
if identity.kind.speaks_msvc_dialect() {
if !capabilities.msvc_style_flags.supported {
return Err(ToolDetectionError::UnsupportedCBackend {
spec: spec_display.to_owned(),
});
}
if !capabilities.c_standard_11.supported {
return Err(ToolDetectionError::CLacksStdC11 {
spec: spec_display.to_owned(),
kind: identity.kind,
});
}
return Ok(());
}
if !capabilities.gcc_style_flags.supported {
if identity.kind == CompilerKind::Unknown {
return Err(ToolDetectionError::UnknownCRequiresGccStyle {
spec: spec_display.to_owned(),
});
}
return Err(ToolDetectionError::UnsupportedCBackend {
spec: spec_display.to_owned(),
});
}
if !capabilities.depfile_mmd_mf.supported {
return Err(ToolDetectionError::CLacksDepfile {
spec: spec_display.to_owned(),
kind: identity.kind,
});
}
Ok(())
}
pub fn validate_ar_for_backend(
spec_display: &str,
identity: &ArchiverIdentity,
capabilities: &ArchiverCapabilities,
) -> Result<(), ToolDetectionError> {
if identity.kind == ArchiverKind::Lib {
return Ok(());
}
if !capabilities.ar_crs.supported {
if identity.kind == ArchiverKind::Unknown {
return Err(ToolDetectionError::UnknownArchiverRequiresArCompatible {
spec: spec_display.to_owned(),
});
}
return Err(ToolDetectionError::UnsupportedArchiver {
spec: spec_display.to_owned(),
});
}
Ok(())
}