cxx_build/
error.rs

1use crate::cfg::CFG;
2use crate::gen::fs;
3use std::error::Error as StdError;
4use std::ffi::OsString;
5use std::fmt::{self, Display};
6use std::path::Path;
7
8pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
9
10#[derive(Debug)]
11pub(super) enum Error {
12    NoEnv(OsString),
13    Fs(fs::Error),
14    ExportedDirNotAbsolute(&'static Path),
15    ExportedEmptyPrefix,
16    ExportedDirsWithoutLinks,
17    ExportedPrefixesWithoutLinks,
18    ExportedLinksWithoutLinks,
19    UnusedExportedPrefix(&'static str),
20    UnusedExportedLinks(&'static str),
21}
22
23macro_rules! expr {
24    ($expr:expr) => {{
25        let _ = $expr; // ensure it doesn't fall out of sync with CFG definition
26        stringify!($expr)
27    }};
28}
29
30const LINKS_DOCUMENTATION: &str =
31    "https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key";
32
33impl Display for Error {
34    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35        match self {
36            Error::NoEnv(var) => {
37                write!(f, "missing {} environment variable", var.to_string_lossy())
38            }
39            Error::Fs(err) => err.fmt(f),
40            Error::ExportedDirNotAbsolute(path) => write!(
41                f,
42                "element of {} must be absolute path, but was: `{}`",
43                expr!(CFG.exported_header_dirs),
44                path.display(),
45            ),
46            Error::ExportedEmptyPrefix => write!(
47                f,
48                "element of {} must not be empty string",
49                expr!(CFG.exported_header_prefixes),
50            ),
51            Error::ExportedDirsWithoutLinks => write!(
52                f,
53                "if {} is nonempty then `links` needs to be set in Cargo.toml; see {}",
54                expr!(CFG.exported_header_dirs),
55                LINKS_DOCUMENTATION,
56            ),
57            Error::ExportedPrefixesWithoutLinks => write!(
58                f,
59                "if {} is nonempty then `links` needs to be set in Cargo.toml; see {}",
60                expr!(CFG.exported_header_prefixes),
61                LINKS_DOCUMENTATION,
62            ),
63            Error::ExportedLinksWithoutLinks => write!(
64                f,
65                "if {} is nonempty then `links` needs to be set in Cargo.toml; see {}",
66                expr!(CFG.exported_header_links),
67                LINKS_DOCUMENTATION,
68            ),
69            Error::UnusedExportedPrefix(unused) => write!(
70                f,
71                "unused element in {}: {:?} does not match the include prefix of any direct dependency",
72                expr!(CFG.exported_header_prefixes),
73                unused,
74            ),
75            Error::UnusedExportedLinks(unused) => write!(
76                f,
77                "unused element in {}: {:?} does not match the `links` attribute any direct dependency",
78                expr!(CFG.exported_header_links),
79                unused,
80            ),
81        }
82    }
83}
84
85impl StdError for Error {
86    fn source(&self) -> Option<&(dyn StdError + 'static)> {
87        match self {
88            Error::Fs(err) => err.source(),
89            _ => None,
90        }
91    }
92}
93
94impl From<fs::Error> for Error {
95    fn from(err: fs::Error) -> Self {
96        Error::Fs(err)
97    }
98}