|
2 | 2 |
|
3 | 3 | use std::env;
|
4 | 4 | use std::ffi::{CStr, CString, OsString};
|
5 |
| -use std::io; |
| 5 | +use std::fs; |
| 6 | +use std::io::{self, Write}; |
6 | 7 | use std::mem;
|
7 | 8 | use std::path::{Path, PathBuf};
|
8 | 9 | use std::ptr;
|
9 | 10 | use std::str;
|
10 | 11 |
|
| 12 | +use object::read::macho::FatArch; |
| 13 | + |
11 | 14 | use crate::common;
|
12 | 15 | use crate::llvm::archive_ro::{ArchiveRO, Child};
|
13 | 16 | use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
|
14 | 17 | use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
|
| 18 | +use rustc_data_structures::memmap::Mmap; |
15 | 19 | use rustc_session::cstore::DllImport;
|
16 | 20 | use rustc_session::Session;
|
17 | 21 |
|
@@ -53,21 +57,78 @@ fn llvm_machine_type(cpu: &str) -> LLVMMachineType {
|
53 | 57 | }
|
54 | 58 | }
|
55 | 59 |
|
| 60 | +fn try_filter_fat_archs( |
| 61 | + archs: object::read::Result<&[impl FatArch]>, |
| 62 | + target_arch: object::Architecture, |
| 63 | + archive_path: &Path, |
| 64 | + archive_map_data: &[u8], |
| 65 | +) -> io::Result<Option<PathBuf>> { |
| 66 | + let archs = archs.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; |
| 67 | + |
| 68 | + let desired = match archs.iter().filter(|a| a.architecture() == target_arch).next() { |
| 69 | + Some(a) => a, |
| 70 | + None => return Ok(None), |
| 71 | + }; |
| 72 | + |
| 73 | + let (mut new_f, extracted_path) = tempfile::Builder::new() |
| 74 | + .suffix(archive_path.file_name().unwrap()) |
| 75 | + .tempfile()? |
| 76 | + .keep() |
| 77 | + .unwrap(); |
| 78 | + |
| 79 | + new_f.write_all( |
| 80 | + desired.data(archive_map_data).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?, |
| 81 | + )?; |
| 82 | + |
| 83 | + Ok(Some(extracted_path)) |
| 84 | +} |
| 85 | + |
| 86 | +fn try_extract_macho_fat_archive( |
| 87 | + sess: &Session, |
| 88 | + archive_path: &Path, |
| 89 | +) -> io::Result<Option<PathBuf>> { |
| 90 | + let archive_map = unsafe { Mmap::map(fs::File::open(&archive_path)?)? }; |
| 91 | + let target_arch = match sess.target.arch.as_ref() { |
| 92 | + "aarch64" => object::Architecture::Aarch64, |
| 93 | + "x86_64" => object::Architecture::X86_64, |
| 94 | + _ => return Ok(None), |
| 95 | + }; |
| 96 | + |
| 97 | + match object::macho::FatHeader::parse(&*archive_map) { |
| 98 | + Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC => { |
| 99 | + let archs = object::macho::FatHeader::parse_arch32(&*archive_map); |
| 100 | + try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map) |
| 101 | + } |
| 102 | + Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => { |
| 103 | + let archs = object::macho::FatHeader::parse_arch64(&*archive_map); |
| 104 | + try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map) |
| 105 | + } |
| 106 | + // Not a FatHeader at all, just return None. |
| 107 | + _ => Ok(None), |
| 108 | + } |
| 109 | +} |
| 110 | + |
56 | 111 | impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
|
57 | 112 | fn add_archive(
|
58 | 113 | &mut self,
|
59 | 114 | archive: &Path,
|
60 | 115 | skip: Box<dyn FnMut(&str) -> bool + 'static>,
|
61 | 116 | ) -> io::Result<()> {
|
62 |
| - let archive_ro = match ArchiveRO::open(archive) { |
| 117 | + let mut archive = archive.to_path_buf(); |
| 118 | + if self.sess.target.llvm_target.contains("-apple-macosx") { |
| 119 | + if let Some(new_archive) = try_extract_macho_fat_archive(&self.sess, &archive)? { |
| 120 | + archive = new_archive |
| 121 | + } |
| 122 | + } |
| 123 | + let archive_ro = match ArchiveRO::open(&archive) { |
63 | 124 | Ok(ar) => ar,
|
64 | 125 | Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
|
65 | 126 | };
|
66 | 127 | if self.additions.iter().any(|ar| ar.path() == archive) {
|
67 | 128 | return Ok(());
|
68 | 129 | }
|
69 | 130 | self.additions.push(Addition::Archive {
|
70 |
| - path: archive.to_path_buf(), |
| 131 | + path: archive, |
71 | 132 | archive: archive_ro,
|
72 | 133 | skip: Box::new(skip),
|
73 | 134 | });
|
|
0 commit comments