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