]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_codegen_ssa/src/back/archive.rs
Remove `LitKind::synthesize_token_lit`.
[rust.git] / compiler / rustc_codegen_ssa / src / back / archive.rs
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;
6
7 use super::metadata::search_for_section;
8
9 use object::read::archive::ArchiveFile;
10
11 use std::error::Error;
12 use std::fs::File;
13 use std::io;
14 use std::path::{Path, PathBuf};
15
16 use crate::errors::ExtractBundledLibsError;
17
18 pub trait ArchiveBuilderBuilder {
19     fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a>;
20
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(
27         &self,
28         sess: &Session,
29         lib_name: &str,
30         dll_imports: &[DllImport],
31         tmpdir: &Path,
32         is_direct_dependency: bool,
33     ) -> PathBuf;
34
35     fn extract_bundled_libs<'a>(
36         &'a self,
37         rlib: &'a Path,
38         outdir: &Path,
39         bundled_lib_file_names: &FxHashSet<Symbol>,
40     ) -> Result<(), ExtractBundledLibsError<'_>> {
41         let archive_map = unsafe {
42             Mmap::map(
43                 File::open(rlib)
44                     .map_err(|e| ExtractBundledLibsError::OpenFile { rlib, error: Box::new(e) })?,
45             )
46             .map_err(|e| ExtractBundledLibsError::MmapFile { rlib, error: Box::new(e) })?
47         };
48         let archive = ArchiveFile::parse(&*archive_map)
49             .map_err(|e| ExtractBundledLibsError::ParseArchive { rlib, error: Box::new(e) })?;
50
51         for entry in archive.members() {
52             let entry = entry
53                 .map_err(|e| ExtractBundledLibsError::ReadEntry { rlib, error: Box::new(e) })?;
54             let data = entry
55                 .data(&*archive_map)
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.
61             }
62             let data = search_for_section(rlib, data, ".bundled_lib").map_err(|e| {
63                 ExtractBundledLibsError::ExtractSection { rlib, error: Box::<dyn Error>::from(e) }
64             })?;
65             std::fs::write(&outdir.join(&name), data)
66                 .map_err(|e| ExtractBundledLibsError::WriteFile { rlib, error: Box::new(e) })?;
67         }
68         Ok(())
69     }
70 }
71
72 pub trait ArchiveBuilder<'a> {
73     fn add_file(&mut self, path: &Path);
74
75     fn add_archive(
76         &mut self,
77         archive: &Path,
78         skip: Box<dyn FnMut(&str) -> bool + 'static>,
79     ) -> io::Result<()>;
80
81     fn build(self: Box<Self>, output: &Path) -> bool;
82 }