1 use rustc_data_structures::fx::FxHashSet;
2 use rustc_data_structures::memmap::Mmap;
3 use rustc_session::cstore::DllImport;
4 use rustc_session::Session;
5 use rustc_span::symbol::Symbol;
7 use super::metadata::search_for_section;
9 use object::read::archive::ArchiveFile;
11 use std::error::Error;
14 use std::path::{Path, PathBuf};
16 use crate::errors::ExtractBundledLibsError;
18 pub trait ArchiveBuilderBuilder {
19 fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a>;
21 /// Creates a DLL Import Library <https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-creation#creating-an-import-library>.
22 /// and returns the path on disk to that import library.
23 /// This functions doesn't take `self` so that it can be called from
24 /// `linker_with_args`, which is specialized on `ArchiveBuilder` but
25 /// doesn't take or create an instance of that type.
26 fn create_dll_import_lib(
30 dll_imports: &[DllImport],
32 is_direct_dependency: bool,
35 fn extract_bundled_libs<'a>(
39 bundled_lib_file_names: &FxHashSet<Symbol>,
40 ) -> Result<(), ExtractBundledLibsError<'_>> {
41 let archive_map = unsafe {
44 .map_err(|e| ExtractBundledLibsError::OpenFile { rlib, error: Box::new(e) })?,
46 .map_err(|e| ExtractBundledLibsError::MmapFile { rlib, error: Box::new(e) })?
48 let archive = ArchiveFile::parse(&*archive_map)
49 .map_err(|e| ExtractBundledLibsError::ParseArchive { rlib, error: Box::new(e) })?;
51 for entry in archive.members() {
53 .map_err(|e| ExtractBundledLibsError::ReadEntry { rlib, error: Box::new(e) })?;
56 .map_err(|e| ExtractBundledLibsError::ArchiveMember { rlib, error: Box::new(e) })?;
57 let name = std::str::from_utf8(entry.name())
58 .map_err(|e| ExtractBundledLibsError::ConvertName { rlib, error: Box::new(e) })?;
59 if !bundled_lib_file_names.contains(&Symbol::intern(name)) {
60 continue; // We need to extract only native libraries.
62 let data = search_for_section(rlib, data, ".bundled_lib").map_err(|e| {
63 ExtractBundledLibsError::ExtractSection { rlib, error: Box::<dyn Error>::from(e) }
65 std::fs::write(&outdir.join(&name), data)
66 .map_err(|e| ExtractBundledLibsError::WriteFile { rlib, error: Box::new(e) })?;
72 pub trait ArchiveBuilder<'a> {
73 fn add_file(&mut self, path: &Path);
78 skip: Box<dyn FnMut(&str) -> bool + 'static>,
81 fn build(self: Box<Self>, output: &Path) -> bool;