|
1 | 1 | //! A helper class for dealing with static archives |
2 | 2 |
|
3 | | -use std::ffi::{CStr, CString, c_char, c_void}; |
4 | | -use std::path::{Path, PathBuf}; |
5 | | -use std::{io, mem, ptr, str}; |
| 3 | +use std::ffi::{CStr, c_char, c_void}; |
| 4 | +use std::io; |
6 | 5 |
|
7 | 6 | use rustc_codegen_ssa::back::archive::{ |
8 | | - ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, |
9 | | - DEFAULT_OBJECT_READER, ObjectReader, UnknownArchiveKind, try_extract_macho_fat_archive, |
| 7 | + ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER, ObjectReader, |
10 | 8 | }; |
11 | 9 | use rustc_session::Session; |
12 | 10 |
|
13 | | -use crate::llvm::archive_ro::{ArchiveRO, Child}; |
14 | | -use crate::llvm::{self, ArchiveKind, last_error}; |
15 | | - |
16 | | -/// Helper for adding many files to an archive. |
17 | | -#[must_use = "must call build() to finish building the archive"] |
18 | | -pub(crate) struct LlvmArchiveBuilder<'a> { |
19 | | - sess: &'a Session, |
20 | | - additions: Vec<Addition>, |
21 | | -} |
22 | | - |
23 | | -enum Addition { |
24 | | - File { path: PathBuf, name_in_archive: String }, |
25 | | - Archive { path: PathBuf, archive: ArchiveRO, skip: Box<dyn FnMut(&str) -> bool> }, |
26 | | -} |
27 | | - |
28 | | -impl Addition { |
29 | | - fn path(&self) -> &Path { |
30 | | - match self { |
31 | | - Addition::File { path, .. } | Addition::Archive { path, .. } => path, |
32 | | - } |
33 | | - } |
34 | | -} |
35 | | - |
36 | | -fn is_relevant_child(c: &Child<'_>) -> bool { |
37 | | - match c.name() { |
38 | | - Some(name) => !name.contains("SYMDEF"), |
39 | | - None => false, |
40 | | - } |
41 | | -} |
42 | | - |
43 | | -impl<'a> ArchiveBuilder for LlvmArchiveBuilder<'a> { |
44 | | - fn add_archive( |
45 | | - &mut self, |
46 | | - archive: &Path, |
47 | | - skip: Box<dyn FnMut(&str) -> bool + 'static>, |
48 | | - ) -> io::Result<()> { |
49 | | - let mut archive = archive.to_path_buf(); |
50 | | - if self.sess.target.llvm_target.contains("-apple-macosx") { |
51 | | - if let Some(new_archive) = try_extract_macho_fat_archive(self.sess, &archive)? { |
52 | | - archive = new_archive |
53 | | - } |
54 | | - } |
55 | | - let archive_ro = match ArchiveRO::open(&archive) { |
56 | | - Ok(ar) => ar, |
57 | | - Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)), |
58 | | - }; |
59 | | - if self.additions.iter().any(|ar| ar.path() == archive) { |
60 | | - return Ok(()); |
61 | | - } |
62 | | - self.additions.push(Addition::Archive { |
63 | | - path: archive, |
64 | | - archive: archive_ro, |
65 | | - skip: Box::new(skip), |
66 | | - }); |
67 | | - Ok(()) |
68 | | - } |
69 | | - |
70 | | - /// Adds an arbitrary file to this archive |
71 | | - fn add_file(&mut self, file: &Path) { |
72 | | - let name = file.file_name().unwrap().to_str().unwrap(); |
73 | | - self.additions |
74 | | - .push(Addition::File { path: file.to_path_buf(), name_in_archive: name.to_owned() }); |
75 | | - } |
76 | | - |
77 | | - /// Combine the provided files, rlibs, and native libraries into a single |
78 | | - /// `Archive`. |
79 | | - fn build(mut self: Box<Self>, output: &Path) -> bool { |
80 | | - match self.build_with_llvm(output) { |
81 | | - Ok(any_members) => any_members, |
82 | | - Err(error) => { |
83 | | - self.sess.dcx().emit_fatal(ArchiveBuildFailure { path: output.to_owned(), error }) |
84 | | - } |
85 | | - } |
86 | | - } |
87 | | -} |
| 11 | +use crate::llvm; |
88 | 12 |
|
89 | 13 | pub(crate) struct LlvmArchiveBuilderBuilder; |
90 | 14 |
|
91 | 15 | impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { |
92 | 16 | fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a> { |
93 | | - // Keeping LlvmArchiveBuilder around in case of a regression caused by using |
94 | | - // ArArchiveBuilder. |
95 | | - // FIXME(#128955) remove a couple of months after #128936 gets merged in case |
96 | | - // no regression is found. |
97 | | - if false { |
98 | | - Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() }) |
99 | | - } else { |
100 | | - Box::new(ArArchiveBuilder::new(sess, &LLVM_OBJECT_READER)) |
101 | | - } |
| 17 | + // Use the `object` crate to build archives, with a little bit of help from LLVM. |
| 18 | + Box::new(ArArchiveBuilder::new(sess, &LLVM_OBJECT_READER)) |
102 | 19 | } |
103 | 20 | } |
104 | 21 |
|
@@ -178,91 +95,3 @@ fn llvm_is_64_bit_object_file(buf: &[u8]) -> bool { |
178 | 95 | fn llvm_is_ec_object_file(buf: &[u8]) -> bool { |
179 | 96 | unsafe { llvm::LLVMRustIsECObject(buf.as_ptr(), buf.len()) } |
180 | 97 | } |
181 | | - |
182 | | -impl<'a> LlvmArchiveBuilder<'a> { |
183 | | - fn build_with_llvm(&mut self, output: &Path) -> io::Result<bool> { |
184 | | - let kind = &*self.sess.target.archive_format; |
185 | | - let kind = kind |
186 | | - .parse::<ArchiveKind>() |
187 | | - .map_err(|_| kind) |
188 | | - .unwrap_or_else(|kind| self.sess.dcx().emit_fatal(UnknownArchiveKind { kind })); |
189 | | - |
190 | | - let mut additions = mem::take(&mut self.additions); |
191 | | - // Values in the `members` list below will contain pointers to the strings allocated here. |
192 | | - // So they need to get dropped after all elements of `members` get freed. |
193 | | - let mut strings = Vec::new(); |
194 | | - let mut members = Vec::new(); |
195 | | - |
196 | | - let dst = CString::new(output.to_str().unwrap())?; |
197 | | - |
198 | | - unsafe { |
199 | | - for addition in &mut additions { |
200 | | - match addition { |
201 | | - Addition::File { path, name_in_archive } => { |
202 | | - let path = CString::new(path.to_str().unwrap())?; |
203 | | - let name = CString::new(name_in_archive.as_bytes())?; |
204 | | - members.push(llvm::LLVMRustArchiveMemberNew( |
205 | | - path.as_ptr(), |
206 | | - name.as_ptr(), |
207 | | - None, |
208 | | - )); |
209 | | - strings.push(path); |
210 | | - strings.push(name); |
211 | | - } |
212 | | - Addition::Archive { archive, skip, .. } => { |
213 | | - for child in archive.iter() { |
214 | | - let child = child.map_err(string_to_io_error)?; |
215 | | - if !is_relevant_child(&child) { |
216 | | - continue; |
217 | | - } |
218 | | - let child_name = child.name().unwrap(); |
219 | | - if skip(child_name) { |
220 | | - continue; |
221 | | - } |
222 | | - |
223 | | - // It appears that LLVM's archive writer is a little |
224 | | - // buggy if the name we pass down isn't just the |
225 | | - // filename component, so chop that off here and |
226 | | - // pass it in. |
227 | | - // |
228 | | - // See LLVM bug 25877 for more info. |
229 | | - let child_name = |
230 | | - Path::new(child_name).file_name().unwrap().to_str().unwrap(); |
231 | | - let name = CString::new(child_name)?; |
232 | | - let m = llvm::LLVMRustArchiveMemberNew( |
233 | | - ptr::null(), |
234 | | - name.as_ptr(), |
235 | | - Some(child.raw), |
236 | | - ); |
237 | | - members.push(m); |
238 | | - strings.push(name); |
239 | | - } |
240 | | - } |
241 | | - } |
242 | | - } |
243 | | - |
244 | | - let r = llvm::LLVMRustWriteArchive( |
245 | | - dst.as_ptr(), |
246 | | - members.len() as libc::size_t, |
247 | | - members.as_ptr() as *const &_, |
248 | | - true, |
249 | | - kind, |
250 | | - self.sess.target.arch == "arm64ec", |
251 | | - ); |
252 | | - let ret = if r.into_result().is_err() { |
253 | | - let msg = last_error().unwrap_or_else(|| "failed to write archive".into()); |
254 | | - Err(io::Error::new(io::ErrorKind::Other, msg)) |
255 | | - } else { |
256 | | - Ok(!members.is_empty()) |
257 | | - }; |
258 | | - for member in members { |
259 | | - llvm::LLVMRustArchiveMemberFree(member); |
260 | | - } |
261 | | - ret |
262 | | - } |
263 | | - } |
264 | | -} |
265 | | - |
266 | | -fn string_to_io_error(s: String) -> io::Error { |
267 | | - io::Error::new(io::ErrorKind::Other, format!("bad archive: {s}")) |
268 | | -} |
0 commit comments