|
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