1 // Copyright (c) The camino Contributors
2 // SPDX-License-Identifier: MIT OR Apache-2.0
3 
4 //! Adapted from
5 //! https://github.com/dtolnay/syn/blob/a54fb0098c6679f1312113ae2eec0305c51c7390/build.rs.
6 
7 use std::{env, process::Command, str};
8 
9 // The rustc-cfg strings below are *not* public API. Please let us know by
10 // opening a GitHub issue if your build environment requires some way to enable
11 // these cfgs other than by executing our build script.
main()12 fn main() {
13     println!("cargo:rerun-if-changed=build.rs");
14 
15     // Required by Rust 1.79+.
16     println!("cargo:rustc-check-cfg=cfg(doc_cfg)");
17     println!("cargo:rustc-check-cfg=cfg(path_buf_deref_mut)");
18     println!("cargo:rustc-check-cfg=cfg(path_buf_capacity)");
19     println!("cargo:rustc-check-cfg=cfg(shrink_to)");
20     println!("cargo:rustc-check-cfg=cfg(try_reserve_2)");
21     println!("cargo:rustc-check-cfg=cfg(os_str_bytes)");
22     println!("cargo:rustc-check-cfg=cfg(absolute_path)");
23 
24     let compiler = match rustc_version() {
25         Some(compiler) => compiler,
26         None => return,
27     };
28 
29     // NOTE:
30     // Adding a new cfg gated by Rust version MUST be accompanied by an addition to the matrix in
31     // .github/workflows/ci.yml.
32     if compiler.minor >= 44 {
33         println!("cargo:rustc-cfg=path_buf_capacity");
34     }
35     if compiler.minor >= 56 {
36         println!("cargo:rustc-cfg=shrink_to");
37     }
38     // NOTE: the below checks use == rather than `matches!`. This is because `matches!` isn't stable
39     // on Rust 1.34.
40     // try_reserve_2 was added in a 1.63 nightly.
41     if (compiler.minor >= 63
42         && (compiler.channel == ReleaseChannel::Stable || compiler.channel == ReleaseChannel::Beta))
43         || compiler.minor >= 64
44     {
45         println!("cargo:rustc-cfg=try_reserve_2");
46     }
47     // path_buf_deref_mut was added in a 1.68 nightly.
48     if (compiler.minor >= 68
49         && (compiler.channel == ReleaseChannel::Stable || compiler.channel == ReleaseChannel::Beta))
50         || compiler.minor >= 69
51     {
52         println!("cargo:rustc-cfg=path_buf_deref_mut");
53     }
54     // os_str_bytes was added in 1.74.
55     if (compiler.minor >= 74 && compiler.channel == ReleaseChannel::Stable) || compiler.minor >= 75
56     {
57         println!("cargo:rustc-cfg=os_str_bytes");
58     }
59     // absolute_path was added in 1.79.
60     if (compiler.minor >= 79 && compiler.channel == ReleaseChannel::Stable) || compiler.minor >= 80
61     {
62         println!("cargo:rustc-cfg=absolute_path");
63     }
64 
65     // Catch situations where the actual features aren't enabled. Currently, they're only shown with
66     // `-vv` output, but maybe that will be noticed.
67     #[cfg(all(feature = "proptest", not(feature = "proptest1")))]
68     {
69         println!(
70             "cargo:warning=proptest feature is enabled, but proptest1 isn't -- this won't do anything"
71         );
72     }
73     #[cfg(all(feature = "serde", not(feature = "serde1")))]
74     {
75         println!(
76             "cargo:warning=serde feature is enabled, but serde1 isn't -- this won't do anything"
77         );
78     }
79 }
80 
81 struct Compiler {
82     minor: u32,
83     channel: ReleaseChannel,
84 }
85 
86 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
87 enum ReleaseChannel {
88     Stable,
89     Beta,
90     Nightly,
91 }
92 
rustc_version() -> Option<Compiler>93 fn rustc_version() -> Option<Compiler> {
94     let rustc = env::var_os("RUSTC")?;
95     let output = Command::new(rustc).arg("--version").output().ok()?;
96     let version = str::from_utf8(&output.stdout).ok()?;
97     let mut pieces = version.split('.');
98     if pieces.next() != Some("rustc 1") {
99         return None;
100     }
101     let minor = pieces.next()?.parse().ok()?;
102     let channel = if version.contains("nightly") {
103         ReleaseChannel::Nightly
104     } else if version.contains("beta") {
105         ReleaseChannel::Beta
106     } else {
107         ReleaseChannel::Stable
108     };
109     Some(Compiler { minor, channel })
110 }
111