blob: 187255f2fca5eb3219d020c2c24f96595ae7851f [file] [log] [blame]
David Tolnay17eb0702019-01-05 12:23:17 -08001// rustc-cfg emitted by the build script:
2//
3// "u128"
4// Include u128 and i128 constructors for proc_macro2::Literal. Enabled on
5// any compiler 1.26+.
6//
7// "use_proc_macro"
8// Link to extern crate proc_macro. Available on any compiler and any target
9// except wasm32. Requires "proc-macro" Cargo cfg to be enabled (default is
10// enabled). On wasm32 we never link to proc_macro even if "proc-macro" cfg
11// is enabled.
12//
13// "wrap_proc_macro"
14// Wrap types from libproc_macro rather than polyfilling the whole API.
15// Enabled on rustc 1.29+ as long as procmacro2_semver_exempt is not set,
16// because we can't emulate the unstable API without emulating everything
17// else. Also enabled unconditionally on nightly, in which case the
18// procmacro2_semver_exempt surface area is implemented by using the
19// nightly-only proc_macro API.
20//
21// "slow_extend"
22// Fallback when `impl Extend for TokenStream` is not available. These impls
23// were added one version later than the rest of the proc_macro token API.
24// Enabled on rustc 1.29 only.
25//
David Tolnayb455dd72019-04-28 13:50:51 -070026// "proc_macro_span"
27// Enable non-dummy behavior of Span::start and Span::end methods which
28// requires an unstable compiler feature. Enabled when building with
29// nightly, unless `-Z allow-feature` in RUSTFLAGS disallows unstable
30// features.
Wim Looman099db2a2019-04-28 11:55:09 +020031//
David Tolnay17eb0702019-01-05 12:23:17 -080032// "super_unstable"
33// Implement the semver exempt API in terms of the nightly-only proc_macro
34// API. Enabled when using procmacro2_semver_exempt on a nightly compiler.
David Tolnay3b1f7d22019-01-28 12:22:11 -080035//
36// "span_locations"
37// Provide methods Span::start and Span::end which give the line/column
38// location of a token. Enabled by procmacro2_semver_exempt or the
39// "span-locations" Cargo cfg. This is behind a cfg because tracking
40// location inside spans is a performance hit.
David Tolnay17eb0702019-01-05 12:23:17 -080041
Alex Crichton53548482018-08-11 21:54:05 -070042use std::env;
Alex Crichtonce0904d2018-08-27 17:29:49 -070043use std::process::Command;
44use std::str;
Alex Crichton53548482018-08-11 21:54:05 -070045
46fn main() {
47 println!("cargo:rerun-if-changed=build.rs");
48
49 let target = env::var("TARGET").unwrap();
50
David Tolnay17eb0702019-01-05 12:23:17 -080051 let version = match rustc_version() {
52 Some(version) => version,
Alex Crichtonce0904d2018-08-27 17:29:49 -070053 None => return,
54 };
55
David Tolnay17eb0702019-01-05 12:23:17 -080056 if version.minor >= 26 {
Alex Crichton69385662018-11-08 06:30:04 -080057 println!("cargo:rustc-cfg=u128");
58 }
59
David Tolnay17eb0702019-01-05 12:23:17 -080060 let semver_exempt = cfg!(procmacro2_semver_exempt);
61 if semver_exempt {
62 // https://github.com/alexcrichton/proc-macro2/issues/147
63 println!("cargo:rustc-cfg=procmacro2_semver_exempt");
David Tolnaye839e4f2018-09-06 09:36:43 -070064 }
65
David Tolnay3b1f7d22019-01-28 12:22:11 -080066 if semver_exempt || cfg!(feature = "span-locations") {
67 println!("cargo:rustc-cfg=span_locations");
68 }
69
70 if !enable_use_proc_macro(&target) {
71 return;
72 }
73
74 println!("cargo:rustc-cfg=use_proc_macro");
75
David Tolnay17eb0702019-01-05 12:23:17 -080076 // Rust 1.29 stabilized the necessary APIs in the `proc_macro` crate
77 if version.nightly || version.minor >= 29 && !semver_exempt {
78 println!("cargo:rustc-cfg=wrap_proc_macro");
79 }
80
81 if version.minor == 29 {
David Tolnaye839e4f2018-09-06 09:36:43 -070082 println!("cargo:rustc-cfg=slow_extend");
Alex Crichtonce0904d2018-08-27 17:29:49 -070083 }
David Tolnay17eb0702019-01-05 12:23:17 -080084
David Tolnayce12a482019-04-28 13:56:13 -070085 if version.nightly && feature_allowed("proc_macro_span") {
David Tolnayb455dd72019-04-28 13:50:51 -070086 println!("cargo:rustc-cfg=proc_macro_span");
David Tolnay17eb0702019-01-05 12:23:17 -080087 }
88
89 if semver_exempt && version.nightly {
90 println!("cargo:rustc-cfg=super_unstable");
91 }
Alex Crichton53548482018-08-11 21:54:05 -070092}
93
Alex Crichtonce0904d2018-08-27 17:29:49 -070094fn enable_use_proc_macro(target: &str) -> bool {
Alex Crichton53548482018-08-11 21:54:05 -070095 // wasm targets don't have the `proc_macro` crate, disable this feature.
96 if target.contains("wasm32") {
Alex Crichtonce0904d2018-08-27 17:29:49 -070097 return false;
Alex Crichton53548482018-08-11 21:54:05 -070098 }
99
Alex Crichton53548482018-08-11 21:54:05 -0700100 // Otherwise, only enable it if our feature is actually enabled.
Alex Crichtonce0904d2018-08-27 17:29:49 -0700101 cfg!(feature = "proc-macro")
102}
103
David Tolnay17eb0702019-01-05 12:23:17 -0800104struct RustcVersion {
105 minor: u32,
106 nightly: bool,
107}
108
109fn rustc_version() -> Option<RustcVersion> {
Alex Crichtonce0904d2018-08-27 17:29:49 -0700110 macro_rules! otry {
David Tolnay2ff99ce2018-09-01 09:40:51 -0700111 ($e:expr) => {
112 match $e {
113 Some(e) => e,
114 None => return None,
115 }
116 };
Alex Crichton53548482018-08-11 21:54:05 -0700117 }
David Tolnay17eb0702019-01-05 12:23:17 -0800118
Alex Crichtonce0904d2018-08-27 17:29:49 -0700119 let rustc = otry!(env::var_os("RUSTC"));
120 let output = otry!(Command::new(rustc).arg("--version").output().ok());
121 let version = otry!(str::from_utf8(&output.stdout).ok());
David Tolnay17eb0702019-01-05 12:23:17 -0800122 let nightly = version.contains("nightly");
Alex Crichtonce0904d2018-08-27 17:29:49 -0700123 let mut pieces = version.split('.');
124 if pieces.next() != Some("rustc 1") {
125 return None;
126 }
David Tolnay17eb0702019-01-05 12:23:17 -0800127 let minor = otry!(pieces.next());
128 let minor = otry!(minor.parse().ok());
129
130 Some(RustcVersion {
131 minor: minor,
132 nightly: nightly,
133 })
Alex Crichton53548482018-08-11 21:54:05 -0700134}
Wim Looman099db2a2019-04-28 11:55:09 +0200135
David Tolnayce12a482019-04-28 13:56:13 -0700136fn feature_allowed(feature: &str) -> bool {
137 // Recognized formats:
138 //
139 // -Z allow-features=feature1,feature2
140 //
141 // -Zallow-features=feature1,feature2
142
Wim Looman099db2a2019-04-28 11:55:09 +0200143 if let Some(rustflags) = env::var_os("RUSTFLAGS") {
David Tolnayce12a482019-04-28 13:56:13 -0700144 for mut flag in rustflags.to_string_lossy().split(' ') {
145 if flag.starts_with("-Z") {
146 flag = &flag["-Z".len()..];
147 }
148 if flag.starts_with("allow-features=") {
149 flag = &flag["allow-features=".len()..];
150 return flag.split(',').any(|allowed| allowed == feature);
Wim Looman099db2a2019-04-28 11:55:09 +0200151 }
152 }
153 }
David Tolnayce12a482019-04-28 13:56:13 -0700154
155 // No allow-features= flag, allowed by default.
156 true
Wim Looman099db2a2019-04-28 11:55:09 +0200157}