1
1
use std:: env;
2
+ use std:: ffi:: { OsStr , OsString } ;
3
+ use std:: fmt:: Display ;
2
4
use std:: path:: { Path , PathBuf } ;
3
- use std:: process:: Command ;
4
-
5
- use build_helper:: { output, tracked_env_var_os} ;
5
+ use std:: process:: { Command , Stdio } ;
6
6
7
7
fn detect_llvm_link ( ) -> ( & ' static str , & ' static str ) {
8
8
// Force the link mode we want, preferring static by default, but
@@ -14,13 +14,74 @@ fn detect_llvm_link() -> (&'static str, &'static str) {
14
14
}
15
15
}
16
16
17
+ // Because Cargo adds the compiler's dylib path to our library search path, llvm-config may
18
+ // break: the dylib path for the compiler, as of this writing, contains a copy of the LLVM
19
+ // shared library, which means that when our freshly built llvm-config goes to load it's
20
+ // associated LLVM, it actually loads the compiler's LLVM. In particular when building the first
21
+ // compiler (i.e., in stage 0) that's a problem, as the compiler's LLVM is likely different from
22
+ // the one we want to use. As such, we restore the environment to what bootstrap saw. This isn't
23
+ // perfect -- we might actually want to see something from Cargo's added library paths -- but
24
+ // for now it works.
25
+ fn restore_library_path ( ) {
26
+ let key = tracked_env_var_os ( "REAL_LIBRARY_PATH_VAR" ) . expect ( "REAL_LIBRARY_PATH_VAR" ) ;
27
+ if let Some ( env) = tracked_env_var_os ( "REAL_LIBRARY_PATH" ) {
28
+ env:: set_var ( & key, & env) ;
29
+ } else {
30
+ env:: remove_var ( & key) ;
31
+ }
32
+ }
33
+
34
+ /// Reads an environment variable and adds it to dependencies.
35
+ /// Supposed to be used for all variables except those set for build scripts by cargo
36
+ /// <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts>
37
+ fn tracked_env_var_os < K : AsRef < OsStr > + Display > ( key : K ) -> Option < OsString > {
38
+ println ! ( "cargo:rerun-if-env-changed={}" , key) ;
39
+ env:: var_os ( key)
40
+ }
41
+
42
+ fn rerun_if_changed_anything_in_dir ( dir : & Path ) {
43
+ let mut stack = dir
44
+ . read_dir ( )
45
+ . unwrap ( )
46
+ . map ( |e| e. unwrap ( ) )
47
+ . filter ( |e| & * e. file_name ( ) != ".git" )
48
+ . collect :: < Vec < _ > > ( ) ;
49
+ while let Some ( entry) = stack. pop ( ) {
50
+ let path = entry. path ( ) ;
51
+ if entry. file_type ( ) . unwrap ( ) . is_dir ( ) {
52
+ stack. extend ( path. read_dir ( ) . unwrap ( ) . map ( |e| e. unwrap ( ) ) ) ;
53
+ } else {
54
+ println ! ( "cargo:rerun-if-changed={}" , path. display( ) ) ;
55
+ }
56
+ }
57
+ }
58
+
59
+ #[ track_caller]
60
+ fn output ( cmd : & mut Command ) -> String {
61
+ let output = match cmd. stderr ( Stdio :: inherit ( ) ) . output ( ) {
62
+ Ok ( status) => status,
63
+ Err ( e) => {
64
+ println ! ( "\n \n failed to execute command: {:?}\n error: {}\n \n " , cmd, e) ;
65
+ std:: process:: exit ( 1 ) ;
66
+ }
67
+ } ;
68
+ if !output. status . success ( ) {
69
+ panic ! (
70
+ "command did not execute successfully: {:?}\n \
71
+ expected success, got: {}",
72
+ cmd, output. status
73
+ ) ;
74
+ }
75
+ String :: from_utf8 ( output. stdout ) . unwrap ( )
76
+ }
77
+
17
78
fn main ( ) {
18
79
if tracked_env_var_os ( "RUST_CHECK" ) . is_some ( ) {
19
80
// If we're just running `check`, there's no need for LLVM to be built.
20
81
return ;
21
82
}
22
83
23
- build_helper :: restore_library_path ( ) ;
84
+ restore_library_path ( ) ;
24
85
25
86
let target = env:: var ( "TARGET" ) . expect ( "TARGET was not set" ) ;
26
87
let llvm_config =
@@ -160,7 +221,7 @@ fn main() {
160
221
cfg. debug ( false ) ;
161
222
}
162
223
163
- build_helper :: rerun_if_changed_anything_in_dir ( Path :: new ( "llvm-wrapper" ) ) ;
224
+ rerun_if_changed_anything_in_dir ( Path :: new ( "llvm-wrapper" ) ) ;
164
225
cfg. file ( "llvm-wrapper/PassWrapper.cpp" )
165
226
. file ( "llvm-wrapper/RustWrapper.cpp" )
166
227
. file ( "llvm-wrapper/ArchiveWrapper.cpp" )
0 commit comments