Skip to content

Commit eaab9d2

Browse files
committed
Ensure AArch64 LSE object files have distinct names in an archive
This is needed by libtool which rejects archives that contain object files with the same name multiple times. Fixes #443
1 parent 95b5211 commit eaab9d2

File tree

1 file changed

+28
-23
lines changed

1 file changed

+28
-23
lines changed

build.rs

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ mod c {
9595

9696
use std::collections::{BTreeMap, HashSet};
9797
use std::env;
98+
use std::fs::File;
99+
use std::io::Write;
98100
use std::path::{Path, PathBuf};
99101

100102
struct Sources {
@@ -523,20 +525,13 @@ mod c {
523525
cfg.compile("libcompiler-rt.a");
524526
}
525527

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());
535530
let outlined_atomics_file = builtins_dir.join("aarch64/lse.S");
536531
println!("cargo:rerun-if-changed={}", outlined_atomics_file.display());
537532

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+
540535
for instruction_type in &["cas", "swp", "ldadd", "ldclr", "ldeor", "ldset"] {
541536
for size in &[1, 2, 4, 8, 16] {
542537
if *size == 16 && *instruction_type != "cas" {
@@ -546,20 +541,30 @@ mod c {
546541
for (model_number, model_name) in
547542
&[(1, "relax"), (2, "acq"), (3, "rel"), (4, "acq_rel")]
548543
{
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()
552563
);
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);
562566

567+
let sym = format!("__aarch64_{}{}_{}", instruction_type, size, model_name);
563568
println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
564569
}
565570
}

0 commit comments

Comments
 (0)