1// rustc-cfg emitted by the build script:
2//
3// "wrap_proc_macro"
4// Wrap types from libproc_macro rather than polyfilling the whole API.
5// Enabled on rustc 1.29+ as long as procmacro2_semver_exempt is not set,
6// because we can't emulate the unstable API without emulating everything
7// else. Also enabled unconditionally on nightly, in which case the
8// procmacro2_semver_exempt surface area is implemented by using the
9// nightly-only proc_macro API.
10//
11// "hygiene"
12// Enable Span::mixed_site() and non-dummy behavior of Span::resolved_at
13// and Span::located_at. Enabled on Rust 1.45+.
14//
15// "proc_macro_span"
16// Enable non-dummy behavior of Span::start and Span::end methods which
17// requires an unstable compiler feature. Enabled when building with
18// nightly, unless `-Z allow-feature` in RUSTFLAGS disallows unstable
19// features.
20//
21// "super_unstable"
22// Implement the semver exempt API in terms of the nightly-only proc_macro
23// API. Enabled when using procmacro2_semver_exempt on a nightly compiler.
24//
25// "span_locations"
26// Provide methods Span::start and Span::end which give the line/column
27// location of a token. Enabled by procmacro2_semver_exempt or the
28// "span-locations" Cargo cfg. This is behind a cfg because tracking
29// location inside spans is a performance hit.
30//
31// "is_available"
32// Use proc_macro::is_available() to detect if the proc macro API is
33// available or needs to be polyfilled instead of trying to use the proc
34// macro API and catching a panic if it isn't available. Enabled on Rust
35// 1.57+.
36
37use std::env;
38use std::process::Command;
39use std::str;
40use std::u32;
41
42fn main() {
43 println!("cargo:rerun-if-changed=build.rs");
44
45 let version = rustc_version().unwrap_or(RustcVersion {
46 minor: u32::MAX,
47 nightly: false,
48 });
49
50 let docs_rs = env::var_os("DOCS_RS").is_some();
51 let semver_exempt = cfg!(procmacro2_semver_exempt) || docs_rs;
52 if semver_exempt {
53 // https://github.com/dtolnay/proc-macro2/issues/147
54 println!("cargo:rustc-cfg=procmacro2_semver_exempt");
55 }
56
57 if semver_exempt || cfg!(feature = "span-locations") {
58 println!("cargo:rustc-cfg=span_locations");
59 }
60
61 if version.minor < 57 {
62 println!("cargo:rustc-cfg=no_is_available");
63 }
64
65 if version.minor < 66 {
66 println!("cargo:rustc-cfg=no_source_text");
67 }
68
69 if !cfg!(feature = "proc-macro") {
70 return;
71 }
72
73 if version.nightly || !semver_exempt {
74 println!("cargo:rustc-cfg=wrap_proc_macro");
75 }
76
77 if version.nightly && feature_allowed("proc_macro_span") {
78 println!("cargo:rustc-cfg=proc_macro_span");
79 }
80
81 if semver_exempt && version.nightly {
82 println!("cargo:rustc-cfg=super_unstable");
83 }
84}
85
86struct RustcVersion {
87 minor: u32,
88 nightly: bool,
89}
90
91fn rustc_version() -> Option<RustcVersion> {
92 let rustc = env::var_os("RUSTC")?;
93 let output = Command::new(rustc).arg("--version").output().ok()?;
94 let version = str::from_utf8(&output.stdout).ok()?;
95 let nightly = version.contains("nightly") || version.contains("dev");
96 let mut pieces = version.split('.');
97 if pieces.next() != Some("rustc 1") {
98 return None;
99 }
100 let minor = pieces.next()?.parse().ok()?;
101 Some(RustcVersion { minor, nightly })
102}
103
104fn feature_allowed(feature: &str) -> bool {
105 // Recognized formats:
106 //
107 // -Z allow-features=feature1,feature2
108 //
109 // -Zallow-features=feature1,feature2
110
111 let flags_var;
112 let flags_var_string;
113 let flags = if let Some(encoded_rustflags) = env::var_os("CARGO_ENCODED_RUSTFLAGS") {
114 flags_var = encoded_rustflags;
115 flags_var_string = flags_var.to_string_lossy();
116 flags_var_string.split('\x1f')
117 } else {
118 return true;
119 };
120
121 for mut flag in flags {
122 if flag.starts_with("-Z") {
123 flag = &flag["-Z".len()..];
124 }
125 if flag.starts_with("allow-features=") {
126 flag = &flag["allow-features=".len()..];
127 return flag.split(',').any(|allowed| allowed == feature);
128 }
129 }
130
131 // No allow-features= flag, allowed by default.
132 true
133}
134