1
1
use std:: process:: Command ;
2
2
use std:: env;
3
- use std:: fs:: { self , File } ;
4
3
use std:: path:: Path ;
4
+ use llvm_tools:: { LlvmTools , exe} ;
5
5
6
6
fn main ( ) {
7
7
let out_dir = env:: var ( "OUT_DIR" ) . unwrap ( ) ;
8
+ let llvm_tools = LlvmTools :: new ( ) . expect ( "LLVM tools not found" ) ;
9
+ let objcopy = llvm_tools. tool ( & exe ( "llvm-objcopy" ) ) . expect ( "llvm-objcopy not found" ) ;
8
10
9
- // first stage
10
- let mut cmd = Command :: new ( "cargo" ) ;
11
- cmd. arg ( "xbuild" ) . arg ( "--release" ) ;
12
- cmd. arg ( "--manifest-path=first_stage/Cargo.toml" ) ;
13
- cmd. arg ( "-Z" ) . arg ( "unstable-options" ) ;
14
- cmd. arg ( "--out-dir" ) . arg ( & out_dir) ;
15
- let status = cmd. status ( ) . unwrap ( ) ;
16
- assert ! ( status. success( ) ) ;
17
-
18
- // second stage
11
+ build_subproject ( Path :: new ( "first_stage" ) , & [ "_start" , "print_char" ] , & out_dir, & objcopy) ;
12
+ build_subproject ( Path :: new ( "second_stage" ) , & [ "second_stage" ] , & out_dir, & objcopy) ;
13
+ }
14
+
15
+ fn build_subproject ( dir : & Path , global_symbols : & [ & str ] , out_dir : & str , objcopy : & Path ) {
16
+ let dir_name = dir. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
17
+ let manifest_path = dir. join ( "Cargo.toml" ) ;
18
+ let out_path = Path :: new ( & out_dir) ;
19
+ assert ! ( global_symbols. len( ) > 0 , "must have at least one global symbol" ) ;
20
+
21
+ // build
19
22
let mut cmd = Command :: new ( "cargo" ) ;
20
23
cmd. arg ( "xbuild" ) . arg ( "--release" ) ;
21
- cmd. arg ( "--manifest-path=second_stage/Cargo.toml" ) ;
24
+ cmd. arg ( format ! ( "--manifest-path={}" , manifest_path . display ( ) ) ) ;
22
25
cmd. arg ( "-Z" ) . arg ( "unstable-options" ) ;
23
26
cmd. arg ( "--out-dir" ) . arg ( & out_dir) ;
27
+ cmd. arg ( "--target-dir" ) . arg ( "target" ) ;
28
+ cmd. env ( "XBUILD_SYSROOT_PATH" , format ! ( "target/{}-sysroot" , dir_name) ) ;
24
29
let status = cmd. status ( ) . unwrap ( ) ;
25
30
assert ! ( status. success( ) ) ;
26
31
27
- let concat_script = Path :: new ( & out_dir) . join ( "concat.mri" ) ;
28
- fs:: write ( & concat_script, "
29
- create libreal_mode.a
30
- addlib libfirst_stage.a
31
- addlib libsecond_stage.a
32
- save
33
- end
34
- " ) . unwrap ( ) ;
35
-
36
- // concat archives
37
- let mut cmd = Command :: new ( "ar" ) ;
38
- cmd. arg ( "-M" ) . stdin ( File :: open ( concat_script) . unwrap ( ) ) ;
39
- cmd. current_dir ( & out_dir) ;
32
+ // localize symbols
33
+ let mut cmd = Command :: new ( objcopy) ;
34
+ for symbol in global_symbols {
35
+ cmd. arg ( "-G" ) . arg ( symbol) ;
36
+ }
37
+ cmd. arg ( out_path. join ( format ! ( "lib{}.a" , dir_name) ) ) ;
40
38
let status = cmd. status ( ) . unwrap ( ) ;
41
39
assert ! ( status. success( ) ) ;
42
-
40
+
41
+ // emit linker flags
43
42
println ! ( "cargo:rustc-link-search=native={}" , out_dir) ;
44
- println ! ( "cargo:rustc-link-lib=static=real_mode" ) ;
43
+ println ! ( "cargo:rustc-link-lib=static={}" , dir_name ) ;
45
44
}
0 commit comments