@@ -34,20 +34,60 @@ fn use_feature(feature: &str) {
34
34
35
35
/// Test whether the rustc at `var("RUSTC")` supports the given feature.
36
36
fn has_feature ( feature : & str ) -> bool {
37
+ can_compile ( format ! (
38
+ "#![allow(stable_features)]\n #![feature({})]" ,
39
+ feature
40
+ ) )
41
+ }
42
+
43
+ /// Test whether the rustc at `var("RUSTC")` can compile the given code.
44
+ fn can_compile < T : AsRef < str > > ( test : T ) -> bool {
45
+ use std:: process:: Stdio ;
46
+
37
47
let out_dir = var ( "OUT_DIR" ) . unwrap ( ) ;
38
48
let rustc = var ( "RUSTC" ) . unwrap ( ) ;
49
+ let target = var ( "TARGET" ) . unwrap ( ) ;
50
+
51
+ // Use `RUSTC_WRAPPER` if it's set, unless it's set to an empty string, as
52
+ // documented [here].
53
+ // [here]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-reads
54
+ let wrapper = var ( "RUSTC_WRAPPER" )
55
+ . ok ( )
56
+ . and_then ( |w| if w. is_empty ( ) { None } else { Some ( w) } ) ;
39
57
40
- let mut child = std:: process:: Command :: new ( rustc)
41
- . arg ( "--crate-type=rlib" ) // Don't require `main`.
58
+ let mut cmd = if let Some ( wrapper) = wrapper {
59
+ let mut cmd = std:: process:: Command :: new ( wrapper) ;
60
+ // The wrapper's first argument is supposed to be the path to rustc.
61
+ cmd. arg ( rustc) ;
62
+ cmd
63
+ } else {
64
+ std:: process:: Command :: new ( rustc)
65
+ } ;
66
+
67
+ cmd. arg ( "--crate-type=rlib" ) // Don't require `main`.
42
68
. arg ( "--emit=metadata" ) // Do as little as possible but still parse.
69
+ . arg ( "--target" )
70
+ . arg ( target)
43
71
. arg ( "--out-dir" )
44
- . arg ( out_dir) // Put the output somewhere inconsequential.
72
+ . arg ( out_dir) ; // Put the output somewhere inconsequential.
73
+
74
+ // If Cargo wants to set RUSTFLAGS, use that.
75
+ if let Ok ( rustflags) = var ( "CARGO_ENCODED_RUSTFLAGS" ) {
76
+ if !rustflags. is_empty ( ) {
77
+ for arg in rustflags. split ( '\x1f' ) {
78
+ cmd. arg ( arg) ;
79
+ }
80
+ }
81
+ }
82
+
83
+ let mut child = cmd
45
84
. arg ( "-" ) // Read from stdin.
46
- . stdin ( std:: process:: Stdio :: piped ( ) ) // Stdin is a pipe.
85
+ . stdin ( Stdio :: piped ( ) ) // Stdin is a pipe.
86
+ . stderr ( Stdio :: null ( ) ) // Errors from feature detection aren't interesting and can be confusing.
47
87
. spawn ( )
48
88
. unwrap ( ) ;
49
89
50
- writeln ! ( child. stdin. take( ) . unwrap( ) , "#![feature({})] " , feature ) . unwrap ( ) ;
90
+ writeln ! ( child. stdin. take( ) . unwrap( ) , "{} " , test . as_ref ( ) ) . unwrap ( ) ;
51
91
52
92
child. wait ( ) . unwrap ( ) . success ( )
53
93
}
0 commit comments