Skip to content

Commit 1d010d4

Browse files
authored
Rollup merge of #99844 - bjorn3:archive_builder_interface_refactor, r=nagisa
Introduce an ArchiveBuilderBuilder This avoids monomorphizing all linker code for each codegen backend and will allow passing in extra information to the archive builder from the codegen backend. I'm going to use this in #97485 to allow passing in the right function to extract symbols from object files to a generic archive builder to be used by cg_llvm, cg_clif and cg_gcc.
2 parents 2c14bc3 + 7c6c7e8 commit 1d010d4

File tree

8 files changed

+218
-197
lines changed

8 files changed

+218
-197
lines changed

Diff for: compiler/rustc_codegen_cranelift/src/archive.rs

+36-36
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::fs::File;
55
use std::io::{self, Read, Seek};
66
use std::path::{Path, PathBuf};
77

8-
use rustc_codegen_ssa::back::archive::ArchiveBuilder;
8+
use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
99
use rustc_session::Session;
1010

1111
use object::read::archive::ArchiveFile;
@@ -17,9 +17,34 @@ enum ArchiveEntry {
1717
File(PathBuf),
1818
}
1919

20+
pub(crate) struct ArArchiveBuilderBuilder;
21+
22+
impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
23+
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> {
24+
Box::new(ArArchiveBuilder {
25+
sess,
26+
use_gnu_style_archive: sess.target.archive_format == "gnu",
27+
// FIXME fix builtin ranlib on macOS
28+
no_builtin_ranlib: sess.target.is_like_osx,
29+
30+
src_archives: vec![],
31+
entries: vec![],
32+
})
33+
}
34+
35+
fn create_dll_import_lib(
36+
&self,
37+
_sess: &Session,
38+
_lib_name: &str,
39+
_dll_imports: &[rustc_session::cstore::DllImport],
40+
_tmpdir: &Path,
41+
) -> PathBuf {
42+
bug!("creating dll imports is not supported");
43+
}
44+
}
45+
2046
pub(crate) struct ArArchiveBuilder<'a> {
2147
sess: &'a Session,
22-
dst: PathBuf,
2348
use_gnu_style_archive: bool,
2449
no_builtin_ranlib: bool,
2550

@@ -30,30 +55,18 @@ pub(crate) struct ArArchiveBuilder<'a> {
3055
}
3156

3257
impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
33-
fn new(sess: &'a Session, output: &Path) -> Self {
34-
ArArchiveBuilder {
35-
sess,
36-
dst: output.to_path_buf(),
37-
use_gnu_style_archive: sess.target.archive_format == "gnu",
38-
// FIXME fix builtin ranlib on macOS
39-
no_builtin_ranlib: sess.target.is_like_osx,
40-
41-
src_archives: vec![],
42-
entries: vec![],
43-
}
44-
}
45-
4658
fn add_file(&mut self, file: &Path) {
4759
self.entries.push((
4860
file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(),
4961
ArchiveEntry::File(file.to_owned()),
5062
));
5163
}
5264

53-
fn add_archive<F>(&mut self, archive_path: &Path, mut skip: F) -> std::io::Result<()>
54-
where
55-
F: FnMut(&str) -> bool + 'static,
56-
{
65+
fn add_archive(
66+
&mut self,
67+
archive_path: &Path,
68+
mut skip: Box<dyn FnMut(&str) -> bool + 'static>,
69+
) -> std::io::Result<()> {
5770
let read_cache = ReadCache::new(std::fs::File::open(&archive_path)?);
5871
let archive = ArchiveFile::parse(&read_cache).unwrap();
5972
let archive_index = self.src_archives.len();
@@ -74,7 +87,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
7487
Ok(())
7588
}
7689

77-
fn build(mut self) -> bool {
90+
fn build(mut self: Box<Self>, output: &Path) -> bool {
7891
enum BuilderKind {
7992
Bsd(ar::Builder<File>),
8093
Gnu(ar::GnuBuilder<File>),
@@ -163,7 +176,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
163176
let mut builder = if self.use_gnu_style_archive {
164177
BuilderKind::Gnu(
165178
ar::GnuBuilder::new(
166-
File::create(&self.dst).unwrap_or_else(|err| {
179+
File::create(output).unwrap_or_else(|err| {
167180
sess.fatal(&format!(
168181
"error opening destination during archive building: {}",
169182
err
@@ -178,7 +191,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
178191
} else {
179192
BuilderKind::Bsd(
180193
ar::Builder::new(
181-
File::create(&self.dst).unwrap_or_else(|err| {
194+
File::create(output).unwrap_or_else(|err| {
182195
sess.fatal(&format!(
183196
"error opening destination during archive building: {}",
184197
err
@@ -209,7 +222,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
209222

210223
// Run ranlib to be able to link the archive
211224
let status = std::process::Command::new(ranlib)
212-
.arg(self.dst)
225+
.arg(output)
213226
.status()
214227
.expect("Couldn't run ranlib");
215228

@@ -220,17 +233,4 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
220233

221234
any_members
222235
}
223-
224-
fn sess(&self) -> &Session {
225-
self.sess
226-
}
227-
228-
fn create_dll_import_lib(
229-
_sess: &Session,
230-
_lib_name: &str,
231-
_dll_imports: &[rustc_session::cstore::DllImport],
232-
_tmpdir: &Path,
233-
) -> PathBuf {
234-
bug!("creating dll imports is not supported");
235-
}
236236
}

Diff for: compiler/rustc_codegen_cranelift/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
226226
) -> Result<(), ErrorGuaranteed> {
227227
use rustc_codegen_ssa::back::link::link_binary;
228228

229-
link_binary::<crate::archive::ArArchiveBuilder<'_>>(sess, &codegen_results, outputs)
229+
link_binary(sess, &crate::archive::ArArchiveBuilderBuilder, &codegen_results, outputs)
230230
}
231231
}
232232

Diff for: compiler/rustc_codegen_gcc/src/archive.rs

+37-39
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
use std::fs::File;
22
use std::path::{Path, PathBuf};
33

4-
use rustc_codegen_ssa::back::archive::ArchiveBuilder;
4+
use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
55
use rustc_session::Session;
66

77
use rustc_session::cstore::DllImport;
88

99
struct ArchiveConfig<'a> {
1010
sess: &'a Session,
11-
dst: PathBuf,
1211
use_native_ar: bool,
1312
use_gnu_style_archive: bool,
1413
}
@@ -22,42 +21,56 @@ enum ArchiveEntry {
2221
File(PathBuf),
2322
}
2423

25-
pub struct ArArchiveBuilder<'a> {
26-
config: ArchiveConfig<'a>,
27-
src_archives: Vec<(PathBuf, ar::Archive<File>)>,
28-
// Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at
29-
// the end of an archive for linkers to not get confused.
30-
entries: Vec<(String, ArchiveEntry)>,
31-
}
24+
pub struct ArArchiveBuilderBuilder;
3225

33-
impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
34-
fn new(sess: &'a Session, output: &Path) -> Self {
26+
impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
27+
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> {
3528
let config = ArchiveConfig {
3629
sess,
37-
dst: output.to_path_buf(),
3830
use_native_ar: false,
3931
// FIXME test for linux and System V derivatives instead
4032
use_gnu_style_archive: sess.target.options.archive_format == "gnu",
4133
};
4234

43-
ArArchiveBuilder {
35+
Box::new(ArArchiveBuilder {
4436
config,
4537
src_archives: vec![],
4638
entries: vec![],
47-
}
39+
})
40+
}
41+
42+
fn create_dll_import_lib(
43+
&self,
44+
_sess: &Session,
45+
_lib_name: &str,
46+
_dll_imports: &[DllImport],
47+
_tmpdir: &Path,
48+
) -> PathBuf {
49+
unimplemented!();
4850
}
51+
}
4952

53+
pub struct ArArchiveBuilder<'a> {
54+
config: ArchiveConfig<'a>,
55+
src_archives: Vec<(PathBuf, ar::Archive<File>)>,
56+
// Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at
57+
// the end of an archive for linkers to not get confused.
58+
entries: Vec<(String, ArchiveEntry)>,
59+
}
60+
61+
impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
5062
fn add_file(&mut self, file: &Path) {
5163
self.entries.push((
5264
file.file_name().unwrap().to_str().unwrap().to_string(),
5365
ArchiveEntry::File(file.to_owned()),
5466
));
5567
}
5668

57-
fn add_archive<F>(&mut self, archive_path: &Path, mut skip: F) -> std::io::Result<()>
58-
where
59-
F: FnMut(&str) -> bool + 'static,
60-
{
69+
fn add_archive(
70+
&mut self,
71+
archive_path: &Path,
72+
mut skip: Box<dyn FnMut(&str) -> bool + 'static>,
73+
) -> std::io::Result<()> {
6174
let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?);
6275
let archive_index = self.src_archives.len();
6376

@@ -77,7 +90,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
7790
Ok(())
7891
}
7992

80-
fn build(mut self) -> bool {
93+
fn build(mut self: Box<Self>, output: &Path) -> bool {
8194
use std::process::Command;
8295

8396
fn add_file_using_ar(archive: &Path, file: &Path) {
@@ -97,17 +110,17 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
97110
}
98111

99112
let mut builder = if self.config.use_native_ar {
100-
BuilderKind::NativeAr(&self.config.dst)
113+
BuilderKind::NativeAr(output)
101114
} else if self.config.use_gnu_style_archive {
102115
BuilderKind::Gnu(ar::GnuBuilder::new(
103-
File::create(&self.config.dst).unwrap(),
116+
File::create(output).unwrap(),
104117
self.entries
105118
.iter()
106119
.map(|(name, _)| name.as_bytes().to_vec())
107120
.collect(),
108121
))
109122
} else {
110-
BuilderKind::Bsd(ar::Builder::new(File::create(&self.config.dst).unwrap()))
123+
BuilderKind::Bsd(ar::Builder::new(File::create(output).unwrap()))
111124
};
112125

113126
let any_members = !self.entries.is_empty();
@@ -164,28 +177,13 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
164177
std::mem::drop(builder);
165178

166179
// Run ranlib to be able to link the archive
167-
let status = std::process::Command::new("ranlib")
168-
.arg(self.config.dst)
169-
.status()
170-
.expect("Couldn't run ranlib");
180+
let status =
181+
std::process::Command::new("ranlib").arg(output).status().expect("Couldn't run ranlib");
171182

172183
if !status.success() {
173184
self.config.sess.fatal(&format!("Ranlib exited with code {:?}", status.code()));
174185
}
175186

176187
any_members
177188
}
178-
179-
fn sess(&self) -> &Session {
180-
self.config.sess
181-
}
182-
183-
fn create_dll_import_lib(
184-
_sess: &Session,
185-
_lib_name: &str,
186-
_dll_imports: &[DllImport],
187-
_tmpdir: &Path,
188-
) -> PathBuf {
189-
unimplemented!();
190-
}
191189
}

Diff for: compiler/rustc_codegen_gcc/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,9 @@ impl CodegenBackend for GccCodegenBackend {
133133
fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorGuaranteed> {
134134
use rustc_codegen_ssa::back::link::link_binary;
135135

136-
link_binary::<crate::archive::ArArchiveBuilder<'_>>(
136+
link_binary(
137137
sess,
138+
&crate::archive::ArArchiveBuilderBuilder,
138139
&codegen_results,
139140
outputs,
140141
)

Diff for: compiler/rustc_codegen_llvm/src/back/archive.rs

+17-18
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,14 @@ use std::str;
1010

1111
use crate::llvm::archive_ro::{ArchiveRO, Child};
1212
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
13-
use rustc_codegen_ssa::back::archive::ArchiveBuilder;
13+
use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
1414
use rustc_session::cstore::{DllCallingConvention, DllImport};
1515
use rustc_session::Session;
1616

1717
/// Helper for adding many files to an archive.
1818
#[must_use = "must call build() to finish building the archive"]
1919
pub struct LlvmArchiveBuilder<'a> {
2020
sess: &'a Session,
21-
dst: PathBuf,
2221
additions: Vec<Addition>,
2322
}
2423

@@ -54,16 +53,11 @@ fn llvm_machine_type(cpu: &str) -> LLVMMachineType {
5453
}
5554

5655
impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
57-
/// Creates a new static archive, ready for modifying the archive specified
58-
/// by `config`.
59-
fn new(sess: &'a Session, output: &Path) -> LlvmArchiveBuilder<'a> {
60-
LlvmArchiveBuilder { sess, dst: output.to_path_buf(), additions: Vec::new() }
61-
}
62-
63-
fn add_archive<F>(&mut self, archive: &Path, skip: F) -> io::Result<()>
64-
where
65-
F: FnMut(&str) -> bool + 'static,
66-
{
56+
fn add_archive(
57+
&mut self,
58+
archive: &Path,
59+
skip: Box<dyn FnMut(&str) -> bool + 'static>,
60+
) -> io::Result<()> {
6761
let archive_ro = match ArchiveRO::open(archive) {
6862
Ok(ar) => ar,
6963
Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
@@ -88,18 +82,23 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
8882

8983
/// Combine the provided files, rlibs, and native libraries into a single
9084
/// `Archive`.
91-
fn build(mut self) -> bool {
92-
match self.build_with_llvm() {
85+
fn build(mut self: Box<Self>, output: &Path) -> bool {
86+
match self.build_with_llvm(output) {
9387
Ok(any_members) => any_members,
9488
Err(e) => self.sess.fatal(&format!("failed to build archive: {}", e)),
9589
}
9690
}
91+
}
92+
93+
pub struct LlvmArchiveBuilderBuilder;
9794

98-
fn sess(&self) -> &Session {
99-
self.sess
95+
impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
96+
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> {
97+
Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() })
10098
}
10199

102100
fn create_dll_import_lib(
101+
&self,
103102
sess: &Session,
104103
lib_name: &str,
105104
dll_imports: &[DllImport],
@@ -241,7 +240,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
241240
}
242241

243242
impl<'a> LlvmArchiveBuilder<'a> {
244-
fn build_with_llvm(&mut self) -> io::Result<bool> {
243+
fn build_with_llvm(&mut self, output: &Path) -> io::Result<bool> {
245244
let kind = &*self.sess.target.archive_format;
246245
let kind = kind.parse::<ArchiveKind>().map_err(|_| kind).unwrap_or_else(|kind| {
247246
self.sess.fatal(&format!("Don't know how to build archive of type: {}", kind))
@@ -251,7 +250,7 @@ impl<'a> LlvmArchiveBuilder<'a> {
251250
let mut strings = Vec::new();
252251
let mut members = Vec::new();
253252

254-
let dst = CString::new(self.dst.to_str().unwrap())?;
253+
let dst = CString::new(output.to_str().unwrap())?;
255254

256255
unsafe {
257256
for addition in &mut additions {

0 commit comments

Comments
 (0)