Skip to content

Support reading thin archives in ArArchiveBuilder #128936

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Aug 15, 2024
8 changes: 5 additions & 3 deletions compiler/rustc_codegen_llvm/src/back/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,11 @@ pub struct LlvmArchiveBuilderBuilder;

impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a> {
// FIXME use ArArchiveBuilder on most targets again once reading thin archives is
// implemented
if true {
// Keeping LlvmArchiveBuilder around in case of a regression caused by using
// ArArchiveBuilder.
// FIXME(#128955) remove a couple of months after #128936 gets merged in case
// no regression is found.
if false {
Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() })
} else {
Box::new(ArArchiveBuilder::new(sess, &LLVM_OBJECT_READER))
Expand Down
13 changes: 9 additions & 4 deletions compiler/rustc_codegen_ssa/src/back/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,10 +307,15 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> {
let file_name = String::from_utf8(entry.name().to_vec())
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
if !skip(&file_name) {
self.entries.push((
file_name.into_bytes(),
ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
));
if entry.is_thin() {
let member_path = archive_path.parent().unwrap().join(Path::new(&file_name));
self.entries.push((file_name.into_bytes(), ArchiveEntry::File(member_path)));
} else {
self.entries.push((
file_name.into_bytes(),
ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
));
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/tools/run-make-support/src/external_deps/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,12 @@ impl LlvmAr {
self
}

/// Like `obj_to_ar` except creating a thin archive.
pub fn obj_to_thin_ar(&mut self) -> &mut Self {
self.cmd.arg("rcus").arg("--thin");
self
}

/// Extract archive members back to files.
pub fn extract(&mut self) -> &mut Self {
self.cmd.arg("x");
Expand Down
5 changes: 5 additions & 0 deletions tests/run-make/staticlib-thin-archive/bin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn main() {
unsafe {
rust_lib::simple_fn();
}
}
28 changes: 28 additions & 0 deletions tests/run-make/staticlib-thin-archive/rmake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Regression test for https://github.com/rust-lang/rust/issues/107407 which
// checks that rustc can read thin archive. Before the object crate added thin
// archive support rustc would add emit object files to the staticlib and after
// the object crate added thin archive support it would previously crash the
// compiler due to a missing special case for thin archive members.
use std::path::Path;

use run_make_support::{llvm_ar, rust_lib_name, rustc, static_lib_name};

fn main() {
std::fs::create_dir("archive").unwrap();

// Build a thin archive
rustc().input("simple_obj.rs").emit("obj").output("archive/simple_obj.o").run();
llvm_ar()
.obj_to_thin_ar()
.output_input(
Path::new("archive").join(static_lib_name("thin_archive")),
"archive/simple_obj.o",
)
.run();

// Build an rlib which includes the members of this thin archive
rustc().input("rust_lib.rs").library_search_path("archive").run();

// Build a binary which requires a symbol from the thin archive
rustc().input("bin.rs").extern_("rust_lib", rust_lib_name("rust_lib")).run();
}
6 changes: 6 additions & 0 deletions tests/run-make/staticlib-thin-archive/rust_lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#![crate_type = "rlib"]

#[link(name = "thin_archive", kind = "static")]
extern "C" {
pub fn simple_fn();
}
4 changes: 4 additions & 0 deletions tests/run-make/staticlib-thin-archive/simple_obj.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#![crate_type = "staticlib"]

#[no_mangle]
extern "C" fn simple_fn() {}
Loading