@@ -95,6 +95,8 @@ mod c {
95
95
96
96
use std:: collections:: { BTreeMap , HashSet } ;
97
97
use std:: env;
98
+ use std:: fs:: File ;
99
+ use std:: io:: Write ;
98
100
use std:: path:: { Path , PathBuf } ;
99
101
100
102
struct Sources {
@@ -523,20 +525,13 @@ mod c {
523
525
cfg. compile ( "libcompiler-rt.a" ) ;
524
526
}
525
527
526
- fn build_aarch64_out_of_line_atomics_libraries ( builtins_dir : & Path , cfg : & cc:: Build ) {
527
- // NOTE: because we're recompiling the same source file in N different ways, building
528
- // serially is necessary. If we want to lift this restriction, we can either:
529
- // - create symlinks to lse.S and build those_(though we'd still need to pass special
530
- // #define-like flags to each of these), or
531
- // - synthesizing tiny .S files in out/ with the proper #defines, which ultimately #include
532
- // lse.S.
533
- // That said, it's unclear how useful this added complexity will be, so just do the simple
534
- // thing for now.
528
+ fn build_aarch64_out_of_line_atomics_libraries ( builtins_dir : & Path , cfg : & mut cc:: Build ) {
529
+ let out_dir = PathBuf :: from ( env:: var ( "OUT_DIR" ) . unwrap ( ) ) ;
535
530
let outlined_atomics_file = builtins_dir. join ( "aarch64/lse.S" ) ;
536
531
println ! ( "cargo:rerun-if-changed={}" , outlined_atomics_file. display( ) ) ;
537
532
538
- // Ideally, this would be a Vec of object files, but cc doesn't make it *entirely*
539
- // trivial to build an individual object.
533
+ cfg . include ( & builtins_dir ) ;
534
+
540
535
for instruction_type in & [ "cas" , "swp" , "ldadd" , "ldclr" , "ldeor" , "ldset" ] {
541
536
for size in & [ 1 , 2 , 4 , 8 , 16 ] {
542
537
if * size == 16 && * instruction_type != "cas" {
@@ -546,20 +541,30 @@ mod c {
546
541
for ( model_number, model_name) in
547
542
& [ ( 1 , "relax" ) , ( 2 , "acq" ) , ( 3 , "rel" ) , ( 4 , "acq_rel" ) ]
548
543
{
549
- let library_name = format ! (
550
- "liboutline_atomic_helper_{}{}_{}.a" ,
551
- instruction_type, size, model_name
544
+ // The original compiler-rt build system compiles the same
545
+ // source file multiple times with different compiler
546
+ // options. Here we do something slightly different: we
547
+ // create multiple .S files with the proper #defines and
548
+ // then include the original file.
549
+ //
550
+ // This is needed because the cc crate doesn't allow us to
551
+ // override the name of object files and libtool requires
552
+ // all objects in an archive to have unique names.
553
+ let path =
554
+ out_dir. join ( format ! ( "lse_{}{}_{}.S" , instruction_type, size, model_name) ) ;
555
+ let mut file = File :: create ( & path) . unwrap ( ) ;
556
+ writeln ! ( file, "#define L_{}" , instruction_type) . unwrap ( ) ;
557
+ writeln ! ( file, "#define SIZE {}" , size) . unwrap ( ) ;
558
+ writeln ! ( file, "#define MODEL {}" , model_number) . unwrap ( ) ;
559
+ writeln ! (
560
+ file,
561
+ "#include \" {}\" " ,
562
+ outlined_atomics_file. canonicalize( ) . unwrap( ) . display( )
552
563
) ;
553
- let sym = format ! ( "__aarch64_{}{}_{}" , instruction_type, size, model_name) ;
554
- let mut cfg = cfg. clone ( ) ;
555
-
556
- cfg. include ( & builtins_dir)
557
- . define ( & format ! ( "L_{}" , instruction_type) , None )
558
- . define ( "SIZE" , size. to_string ( ) . as_str ( ) )
559
- . define ( "MODEL" , model_number. to_string ( ) . as_str ( ) )
560
- . file ( & outlined_atomics_file) ;
561
- cfg. compile ( & library_name) ;
564
+ drop ( file) ;
565
+ cfg. file ( path) ;
562
566
567
+ let sym = format ! ( "__aarch64_{}{}_{}" , instruction_type, size, model_name) ;
563
568
println ! ( "cargo:rustc-cfg={}=\" optimized-c\" " , sym) ;
564
569
}
565
570
}
0 commit comments