Skip to content

Commit dc80ca7

Browse files
committed
Auto merge of #98098 - bjorn3:archive_refactor, r=michaelwoerister
Remove the source archive functionality of ArchiveWriter We now build archives through strictly additive means rather than taking an existing archive and potentially substracting parts. This is simpler and makes it easier to swap out the archive writer in #97485.
2 parents 72fd41a + 7643f82 commit dc80ca7

File tree

5 files changed

+62
-193
lines changed

5 files changed

+62
-193
lines changed

compiler/rustc_codegen_cranelift/src/archive.rs

+8-35
Original file line numberDiff line numberDiff line change
@@ -30,50 +30,19 @@ pub(crate) struct ArArchiveBuilder<'a> {
3030
}
3131

3232
impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
33-
fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> Self {
34-
let (src_archives, entries) = if let Some(input) = input {
35-
let read_cache = ReadCache::new(File::open(input).unwrap());
36-
let archive = ArchiveFile::parse(&read_cache).unwrap();
37-
let mut entries = Vec::new();
38-
39-
for entry in archive.members() {
40-
let entry = entry.unwrap();
41-
entries.push((
42-
entry.name().to_vec(),
43-
ArchiveEntry::FromArchive { archive_index: 0, file_range: entry.file_range() },
44-
));
45-
}
46-
47-
(vec![read_cache.into_inner()], entries)
48-
} else {
49-
(vec![], Vec::new())
50-
};
51-
33+
fn new(sess: &'a Session, output: &Path) -> Self {
5234
ArArchiveBuilder {
5335
sess,
5436
dst: output.to_path_buf(),
5537
use_gnu_style_archive: sess.target.archive_format == "gnu",
5638
// FIXME fix builtin ranlib on macOS
5739
no_builtin_ranlib: sess.target.is_like_osx,
5840

59-
src_archives,
60-
entries,
41+
src_archives: vec![],
42+
entries: vec![],
6143
}
6244
}
6345

64-
fn src_files(&mut self) -> Vec<String> {
65-
self.entries.iter().map(|(name, _)| String::from_utf8(name.clone()).unwrap()).collect()
66-
}
67-
68-
fn remove_file(&mut self, name: &str) {
69-
let index = self
70-
.entries
71-
.iter()
72-
.position(|(entry_name, _)| entry_name == name.as_bytes())
73-
.expect("Tried to remove file not existing in src archive");
74-
self.entries.remove(index);
75-
}
76-
7746
fn add_file(&mut self, file: &Path) {
7847
self.entries.push((
7948
file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(),
@@ -105,7 +74,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
10574
Ok(())
10675
}
10776

108-
fn build(mut self) {
77+
fn build(mut self) -> bool {
10978
enum BuilderKind {
11079
Bsd(ar::Builder<File>),
11180
Gnu(ar::GnuBuilder<File>),
@@ -204,6 +173,8 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
204173
)
205174
};
206175

176+
let any_members = !entries.is_empty();
177+
207178
// Add all files
208179
for (entry_name, data) in entries.into_iter() {
209180
let header = ar::Header::new(entry_name, data.len() as u64);
@@ -229,6 +200,8 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
229200
self.sess.fatal(&format!("Ranlib exited with code {:?}", status.code()));
230201
}
231202
}
203+
204+
any_members
232205
}
233206

234207
fn inject_dll_import_lib(

compiler/rustc_codegen_gcc/src/archive.rs

+8-39
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub struct ArArchiveBuilder<'a> {
3232
}
3333

3434
impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
35-
fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> Self {
35+
fn new(sess: &'a Session, output: &Path) -> Self {
3636
let config = ArchiveConfig {
3737
sess,
3838
dst: output.to_path_buf(),
@@ -41,48 +41,13 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
4141
use_gnu_style_archive: sess.target.options.archive_format == "gnu",
4242
};
4343

44-
let (src_archives, entries) = if let Some(input) = input {
45-
let mut archive = ar::Archive::new(File::open(input).unwrap());
46-
let mut entries = Vec::new();
47-
48-
let mut i = 0;
49-
while let Some(entry) = archive.next_entry() {
50-
let entry = entry.unwrap();
51-
entries.push((
52-
String::from_utf8(entry.header().identifier().to_vec()).unwrap(),
53-
ArchiveEntry::FromArchive {
54-
archive_index: 0,
55-
entry_index: i,
56-
},
57-
));
58-
i += 1;
59-
}
60-
61-
(vec![(input.to_owned(), archive)], entries)
62-
} else {
63-
(vec![], Vec::new())
64-
};
65-
6644
ArArchiveBuilder {
6745
config,
68-
src_archives,
69-
entries,
46+
src_archives: vec![],
47+
entries: vec![],
7048
}
7149
}
7250

73-
fn src_files(&mut self) -> Vec<String> {
74-
self.entries.iter().map(|(name, _)| name.clone()).collect()
75-
}
76-
77-
fn remove_file(&mut self, name: &str) {
78-
let index = self
79-
.entries
80-
.iter()
81-
.position(|(entry_name, _)| entry_name == name)
82-
.expect("Tried to remove file not existing in src archive");
83-
self.entries.remove(index);
84-
}
85-
8651
fn add_file(&mut self, file: &Path) {
8752
self.entries.push((
8853
file.file_name().unwrap().to_str().unwrap().to_string(),
@@ -113,7 +78,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
11378
Ok(())
11479
}
11580

116-
fn build(mut self) {
81+
fn build(mut self) -> bool {
11782
use std::process::Command;
11883

11984
fn add_file_using_ar(archive: &Path, file: &Path) {
@@ -146,6 +111,8 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
146111
BuilderKind::Bsd(ar::Builder::new(File::create(&self.config.dst).unwrap()))
147112
};
148113

114+
let any_members = !self.entries.is_empty();
115+
149116
// Add all files
150117
for (entry_name, entry) in self.entries.into_iter() {
151118
match entry {
@@ -206,6 +173,8 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
206173
if !status.success() {
207174
self.config.sess.fatal(&format!("Ranlib exited with code {:?}", status.code()));
208175
}
176+
177+
any_members
209178
}
210179

211180
fn inject_dll_import_lib(&mut self, _lib_name: &str, _dll_imports: &[DllImport], _tmpdir: &MaybeTempDir) {

compiler/rustc_codegen_llvm/src/back/archive.rs

+25-95
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,12 @@ use rustc_data_structures::temp_dir::MaybeTempDir;
1515
use rustc_session::cstore::{DllCallingConvention, DllImport};
1616
use rustc_session::Session;
1717

18-
struct ArchiveConfig<'a> {
19-
pub sess: &'a Session,
20-
pub dst: PathBuf,
21-
pub src: Option<PathBuf>,
22-
}
23-
2418
/// Helper for adding many files to an archive.
2519
#[must_use = "must call build() to finish building the archive"]
2620
pub struct LlvmArchiveBuilder<'a> {
27-
config: ArchiveConfig<'a>,
28-
removals: Vec<String>,
21+
sess: &'a Session,
22+
dst: PathBuf,
2923
additions: Vec<Addition>,
30-
src_archive: Option<Option<ArchiveRO>>,
3124
}
3225

3326
enum Addition {
@@ -50,10 +43,6 @@ fn is_relevant_child(c: &Child<'_>) -> bool {
5043
}
5144
}
5245

53-
fn archive_config<'a>(sess: &'a Session, output: &Path, input: Option<&Path>) -> ArchiveConfig<'a> {
54-
ArchiveConfig { sess, dst: output.to_path_buf(), src: input.map(|p| p.to_path_buf()) }
55-
}
56-
5746
/// Map machine type strings to values of LLVM's MachineTypes enum.
5847
fn llvm_machine_type(cpu: &str) -> LLVMMachineType {
5948
match cpu {
@@ -68,37 +57,8 @@ fn llvm_machine_type(cpu: &str) -> LLVMMachineType {
6857
impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
6958
/// Creates a new static archive, ready for modifying the archive specified
7059
/// by `config`.
71-
fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> LlvmArchiveBuilder<'a> {
72-
let config = archive_config(sess, output, input);
73-
LlvmArchiveBuilder {
74-
config,
75-
removals: Vec::new(),
76-
additions: Vec::new(),
77-
src_archive: None,
78-
}
79-
}
80-
81-
/// Removes a file from this archive
82-
fn remove_file(&mut self, file: &str) {
83-
self.removals.push(file.to_string());
84-
}
85-
86-
/// Lists all files in an archive
87-
fn src_files(&mut self) -> Vec<String> {
88-
if self.src_archive().is_none() {
89-
return Vec::new();
90-
}
91-
92-
let archive = self.src_archive.as_ref().unwrap().as_ref().unwrap();
93-
94-
archive
95-
.iter()
96-
.filter_map(|child| child.ok())
97-
.filter(is_relevant_child)
98-
.filter_map(|child| child.name())
99-
.filter(|name| !self.removals.iter().any(|x| x == name))
100-
.map(|name| name.to_owned())
101-
.collect()
60+
fn new(sess: &'a Session, output: &Path) -> LlvmArchiveBuilder<'a> {
61+
LlvmArchiveBuilder { sess, dst: output.to_path_buf(), additions: Vec::new() }
10262
}
10363

10464
fn add_archive<F>(&mut self, archive: &Path, skip: F) -> io::Result<()>
@@ -129,13 +89,10 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
12989

13090
/// Combine the provided files, rlibs, and native libraries into a single
13191
/// `Archive`.
132-
fn build(mut self) {
133-
let kind = self.llvm_archive_kind().unwrap_or_else(|kind| {
134-
self.config.sess.fatal(&format!("Don't know how to build archive of type: {}", kind))
135-
});
136-
137-
if let Err(e) = self.build_with_llvm(kind) {
138-
self.config.sess.fatal(&format!("failed to build archive: {}", e));
92+
fn build(mut self) -> bool {
93+
match self.build_with_llvm() {
94+
Ok(any_members) => any_members,
95+
Err(e) => self.sess.fatal(&format!("failed to build archive: {}", e)),
13996
}
14097
}
14198

@@ -151,7 +108,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
151108
output_path.with_extension("lib")
152109
};
153110

154-
let target = &self.config.sess.target;
111+
let target = &self.sess.target;
155112
let mingw_gnu_toolchain = target.vendor == "pc"
156113
&& target.os == "windows"
157114
&& target.env == "gnu"
@@ -160,7 +117,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
160117
let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = dll_imports
161118
.iter()
162119
.map(|import: &DllImport| {
163-
if self.config.sess.target.arch == "x86" {
120+
if self.sess.target.arch == "x86" {
164121
(
165122
LlvmArchiveBuilder::i686_decorated_name(import, mingw_gnu_toolchain),
166123
import.ordinal,
@@ -197,11 +154,11 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
197154
match std::fs::write(&def_file_path, def_file_content) {
198155
Ok(_) => {}
199156
Err(e) => {
200-
self.config.sess.fatal(&format!("Error writing .DEF file: {}", e));
157+
self.sess.fatal(&format!("Error writing .DEF file: {}", e));
201158
}
202159
};
203160

204-
let dlltool = find_binutils_dlltool(self.config.sess);
161+
let dlltool = find_binutils_dlltool(self.sess);
205162
let result = std::process::Command::new(dlltool)
206163
.args([
207164
"-d",
@@ -215,9 +172,9 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
215172

216173
match result {
217174
Err(e) => {
218-
self.config.sess.fatal(&format!("Error calling dlltool: {}", e));
175+
self.sess.fatal(&format!("Error calling dlltool: {}", e));
219176
}
220-
Ok(output) if !output.status.success() => self.config.sess.fatal(&format!(
177+
Ok(output) if !output.status.success() => self.sess.fatal(&format!(
221178
"Dlltool could not create import library: {}\n{}",
222179
String::from_utf8_lossy(&output.stdout),
223180
String::from_utf8_lossy(&output.stderr)
@@ -263,13 +220,13 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
263220
output_path_z.as_ptr(),
264221
ffi_exports.as_ptr(),
265222
ffi_exports.len(),
266-
llvm_machine_type(&self.config.sess.target.arch) as u16,
267-
!self.config.sess.target.is_like_msvc,
223+
llvm_machine_type(&self.sess.target.arch) as u16,
224+
!self.sess.target.is_like_msvc,
268225
)
269226
};
270227

271228
if result == crate::llvm::LLVMRustResult::Failure {
272-
self.config.sess.fatal(&format!(
229+
self.sess.fatal(&format!(
273230
"Error creating import library for {}: {}",
274231
lib_name,
275232
llvm::last_error().unwrap_or("unknown LLVM error".to_string())
@@ -278,7 +235,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
278235
};
279236

280237
self.add_archive(&output_path, |_| false).unwrap_or_else(|e| {
281-
self.config.sess.fatal(&format!(
238+
self.sess.fatal(&format!(
282239
"failed to add native library {}: {}",
283240
output_path.display(),
284241
e
@@ -288,46 +245,19 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
288245
}
289246

290247
impl<'a> LlvmArchiveBuilder<'a> {
291-
fn src_archive(&mut self) -> Option<&ArchiveRO> {
292-
if let Some(ref a) = self.src_archive {
293-
return a.as_ref();
294-
}
295-
let src = self.config.src.as_ref()?;
296-
self.src_archive = Some(ArchiveRO::open(src).ok());
297-
self.src_archive.as_ref().unwrap().as_ref()
298-
}
299-
300-
fn llvm_archive_kind(&self) -> Result<ArchiveKind, &str> {
301-
let kind = &*self.config.sess.target.archive_format;
302-
kind.parse().map_err(|_| kind)
303-
}
248+
fn build_with_llvm(&mut self) -> io::Result<bool> {
249+
let kind = &*self.sess.target.archive_format;
250+
let kind = kind.parse::<ArchiveKind>().map_err(|_| kind).unwrap_or_else(|kind| {
251+
self.sess.fatal(&format!("Don't know how to build archive of type: {}", kind))
252+
});
304253

305-
fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> {
306-
let removals = mem::take(&mut self.removals);
307254
let mut additions = mem::take(&mut self.additions);
308255
let mut strings = Vec::new();
309256
let mut members = Vec::new();
310257

311-
let dst = CString::new(self.config.dst.to_str().unwrap())?;
258+
let dst = CString::new(self.dst.to_str().unwrap())?;
312259

313260
unsafe {
314-
if let Some(archive) = self.src_archive() {
315-
for child in archive.iter() {
316-
let child = child.map_err(string_to_io_error)?;
317-
let Some(child_name) = child.name() else { continue };
318-
if removals.iter().any(|r| r == child_name) {
319-
continue;
320-
}
321-
322-
let name = CString::new(child_name)?;
323-
members.push(llvm::LLVMRustArchiveMemberNew(
324-
ptr::null(),
325-
name.as_ptr(),
326-
Some(child.raw),
327-
));
328-
strings.push(name);
329-
}
330-
}
331261
for addition in &mut additions {
332262
match addition {
333263
Addition::File { path, name_in_archive } => {
@@ -389,7 +319,7 @@ impl<'a> LlvmArchiveBuilder<'a> {
389319
};
390320
Err(io::Error::new(io::ErrorKind::Other, msg))
391321
} else {
392-
Ok(())
322+
Ok(!members.is_empty())
393323
};
394324
for member in members {
395325
llvm::LLVMRustArchiveMemberFree(member);

0 commit comments

Comments
 (0)