]>
Commit | Line | Data |
---|---|---|
f2b60f7d FG |
1 | use rustc_data_structures::fx::FxHashSet; |
2 | use rustc_data_structures::memmap::Mmap; | |
c295e0f8 | 3 | use rustc_session::cstore::DllImport; |
ba9703b0 | 4 | use rustc_session::Session; |
f2b60f7d | 5 | use rustc_span::symbol::Symbol; |
a1dfa0c6 | 6 | |
f2b60f7d FG |
7 | use object::read::archive::ArchiveFile; |
8 | ||
9 | use std::fmt::Display; | |
10 | use std::fs::File; | |
48663c56 XL |
11 | use std::io; |
12 | use std::path::{Path, PathBuf}; | |
a1dfa0c6 | 13 | |
064997fb FG |
14 | pub trait ArchiveBuilderBuilder { |
15 | fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a>; | |
48663c56 | 16 | |
064997fb FG |
17 | /// Creates a DLL Import Library <https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-creation#creating-an-import-library>. |
18 | /// and returns the path on disk to that import library. | |
19 | /// This functions doesn't take `self` so that it can be called from | |
20 | /// `linker_with_args`, which is specialized on `ArchiveBuilder` but | |
21 | /// doesn't take or create an instance of that type. | |
22 | fn create_dll_import_lib( | |
23 | &self, | |
24 | sess: &Session, | |
25 | lib_name: &str, | |
26 | dll_imports: &[DllImport], | |
27 | tmpdir: &Path, | |
f2b60f7d | 28 | is_direct_dependency: bool, |
064997fb | 29 | ) -> PathBuf; |
f2b60f7d FG |
30 | |
31 | fn extract_bundled_libs( | |
32 | &self, | |
33 | rlib: &Path, | |
34 | outdir: &Path, | |
35 | bundled_lib_file_names: &FxHashSet<Symbol>, | |
36 | ) -> Result<(), String> { | |
37 | let message = |msg: &str, e: &dyn Display| format!("{} '{}': {}", msg, &rlib.display(), e); | |
38 | let archive_map = unsafe { | |
39 | Mmap::map(File::open(rlib).map_err(|e| message("failed to open file", &e))?) | |
40 | .map_err(|e| message("failed to mmap file", &e))? | |
41 | }; | |
42 | let archive = ArchiveFile::parse(&*archive_map) | |
43 | .map_err(|e| message("failed to parse archive", &e))?; | |
44 | ||
45 | for entry in archive.members() { | |
46 | let entry = entry.map_err(|e| message("failed to read entry", &e))?; | |
47 | let data = entry | |
48 | .data(&*archive_map) | |
49 | .map_err(|e| message("failed to get data from archive member", &e))?; | |
50 | let name = std::str::from_utf8(entry.name()) | |
51 | .map_err(|e| message("failed to convert name", &e))?; | |
52 | if !bundled_lib_file_names.contains(&Symbol::intern(name)) { | |
53 | continue; // We need to extract only native libraries. | |
54 | } | |
55 | std::fs::write(&outdir.join(&name), data) | |
56 | .map_err(|e| message("failed to write file", &e))?; | |
57 | } | |
58 | Ok(()) | |
59 | } | |
064997fb | 60 | } |
48663c56 | 61 | |
064997fb FG |
62 | pub trait ArchiveBuilder<'a> { |
63 | fn add_file(&mut self, path: &Path); | |
17df50a5 | 64 | |
064997fb | 65 | fn add_archive( |
17df50a5 | 66 | &mut self, |
064997fb FG |
67 | archive: &Path, |
68 | skip: Box<dyn FnMut(&str) -> bool + 'static>, | |
69 | ) -> io::Result<()>; | |
70 | ||
71 | fn build(self: Box<Self>, output: &Path) -> bool; | |
48663c56 | 72 | } |