Skip to content

Commit 7c6c7e8

Browse files
committed
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.
1 parent 90da3c6 commit 7c6c7e8

File tree

8 files changed

+210
-144
lines changed

8 files changed

+210
-144
lines changed

compiler/rustc_codegen_cranelift/src/archive.rs

+33-27
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,6 +17,32 @@ 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,
2248
use_gnu_style_archive: bool,
@@ -29,29 +55,18 @@ pub(crate) struct ArArchiveBuilder<'a> {
2955
}
3056

3157
impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
32-
fn new(sess: &'a Session) -> Self {
33-
ArArchiveBuilder {
34-
sess,
35-
use_gnu_style_archive: sess.target.archive_format == "gnu",
36-
// FIXME fix builtin ranlib on macOS
37-
no_builtin_ranlib: sess.target.is_like_osx,
38-
39-
src_archives: vec![],
40-
entries: vec![],
41-
}
42-
}
43-
4458
fn add_file(&mut self, file: &Path) {
4559
self.entries.push((
4660
file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(),
4761
ArchiveEntry::File(file.to_owned()),
4862
));
4963
}
5064

51-
fn add_archive<F>(&mut self, archive_path: &Path, mut skip: F) -> std::io::Result<()>
52-
where
53-
F: FnMut(&str) -> bool + 'static,
54-
{
65+
fn add_archive(
66+
&mut self,
67+
archive_path: &Path,
68+
mut skip: Box<dyn FnMut(&str) -> bool + 'static>,
69+
) -> std::io::Result<()> {
5570
let read_cache = ReadCache::new(std::fs::File::open(&archive_path)?);
5671
let archive = ArchiveFile::parse(&read_cache).unwrap();
5772
let archive_index = self.src_archives.len();
@@ -72,7 +87,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
7287
Ok(())
7388
}
7489

75-
fn build(mut self, output: &Path) -> bool {
90+
fn build(mut self: Box<Self>, output: &Path) -> bool {
7691
enum BuilderKind {
7792
Bsd(ar::Builder<File>),
7893
Gnu(ar::GnuBuilder<File>),
@@ -218,13 +233,4 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
218233

219234
any_members
220235
}
221-
222-
fn create_dll_import_lib(
223-
_sess: &Session,
224-
_lib_name: &str,
225-
_dll_imports: &[rustc_session::cstore::DllImport],
226-
_tmpdir: &Path,
227-
) -> PathBuf {
228-
bug!("creating dll imports is not supported");
229-
}
230236
}

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

compiler/rustc_codegen_gcc/src/archive.rs

+32-26
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
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;
@@ -21,41 +21,56 @@ enum ArchiveEntry {
2121
File(PathBuf),
2222
}
2323

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

32-
impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
33-
fn new(sess: &'a Session) -> Self {
26+
impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
27+
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> {
3428
let config = ArchiveConfig {
3529
sess,
3630
use_native_ar: false,
3731
// FIXME test for linux and System V derivatives instead
3832
use_gnu_style_archive: sess.target.options.archive_format == "gnu",
3933
};
4034

41-
ArArchiveBuilder {
35+
Box::new(ArArchiveBuilder {
4236
config,
4337
src_archives: vec![],
4438
entries: vec![],
45-
}
39+
})
4640
}
4741

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!();
50+
}
51+
}
52+
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> {
4862
fn add_file(&mut self, file: &Path) {
4963
self.entries.push((
5064
file.file_name().unwrap().to_str().unwrap().to_string(),
5165
ArchiveEntry::File(file.to_owned()),
5266
));
5367
}
5468

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

@@ -75,7 +90,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
7590
Ok(())
7691
}
7792

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

8196
fn add_file_using_ar(archive: &Path, file: &Path) {
@@ -171,13 +186,4 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
171186

172187
any_members
173188
}
174-
175-
fn create_dll_import_lib(
176-
_sess: &Session,
177-
_lib_name: &str,
178-
_dll_imports: &[DllImport],
179-
_tmpdir: &Path,
180-
) -> PathBuf {
181-
unimplemented!();
182-
}
183189
}

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
)

compiler/rustc_codegen_llvm/src/back/archive.rs

+16-12
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ 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

@@ -53,16 +53,11 @@ fn llvm_machine_type(cpu: &str) -> LLVMMachineType {
5353
}
5454

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

8883
/// Combine the provided files, rlibs, and native libraries into a single
8984
/// `Archive`.
90-
fn build(mut self, output: &Path) -> bool {
85+
fn build(mut self: Box<Self>, output: &Path) -> bool {
9186
match self.build_with_llvm(output) {
9287
Ok(any_members) => any_members,
9388
Err(e) => self.sess.fatal(&format!("failed to build archive: {}", e)),
9489
}
9590
}
91+
}
92+
93+
pub struct LlvmArchiveBuilderBuilder;
94+
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() })
98+
}
9699

97100
fn create_dll_import_lib(
101+
&self,
98102
sess: &Session,
99103
lib_name: &str,
100104
dll_imports: &[DllImport],

compiler/rustc_codegen_llvm/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -370,12 +370,12 @@ impl CodegenBackend for LlvmCodegenBackend {
370370
codegen_results: CodegenResults,
371371
outputs: &OutputFilenames,
372372
) -> Result<(), ErrorGuaranteed> {
373-
use crate::back::archive::LlvmArchiveBuilder;
373+
use crate::back::archive::LlvmArchiveBuilderBuilder;
374374
use rustc_codegen_ssa::back::link::link_binary;
375375

376376
// Run the linker on any artifacts that resulted from the LLVM run.
377377
// This should produce either a finished executable or library.
378-
link_binary::<LlvmArchiveBuilder<'_>>(sess, &codegen_results, outputs)
378+
link_binary(sess, &LlvmArchiveBuilderBuilder, &codegen_results, outputs)
379379
}
380380
}
381381

compiler/rustc_codegen_ssa/src/back/archive.rs

+15-10
Original file line numberDiff line numberDiff line change
@@ -39,26 +39,31 @@ pub(super) fn find_library(
3939
));
4040
}
4141

42-
pub trait ArchiveBuilder<'a> {
43-
fn new(sess: &'a Session) -> Self;
44-
45-
fn add_file(&mut self, path: &Path);
46-
47-
fn add_archive<F>(&mut self, archive: &Path, skip: F) -> io::Result<()>
48-
where
49-
F: FnMut(&str) -> bool + 'static;
50-
51-
fn build(self, output: &Path) -> bool;
42+
pub trait ArchiveBuilderBuilder {
43+
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a>;
5244

5345
/// Creates a DLL Import Library <https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-creation#creating-an-import-library>.
5446
/// and returns the path on disk to that import library.
5547
/// This functions doesn't take `self` so that it can be called from
5648
/// `linker_with_args`, which is specialized on `ArchiveBuilder` but
5749
/// doesn't take or create an instance of that type.
5850
fn create_dll_import_lib(
51+
&self,
5952
sess: &Session,
6053
lib_name: &str,
6154
dll_imports: &[DllImport],
6255
tmpdir: &Path,
6356
) -> PathBuf;
6457
}
58+
59+
pub trait ArchiveBuilder<'a> {
60+
fn add_file(&mut self, path: &Path);
61+
62+
fn add_archive(
63+
&mut self,
64+
archive: &Path,
65+
skip: Box<dyn FnMut(&str) -> bool + 'static>,
66+
) -> io::Result<()>;
67+
68+
fn build(self: Box<Self>, output: &Path) -> bool;
69+
}

0 commit comments

Comments
 (0)