|
1 | | -use rustc_data_structures::fx::FxHashSet; |
| 1 | +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; |
2 | 2 | use rustc_data_structures::temp_dir::MaybeTempDir; |
3 | 3 | use rustc_errors::Handler; |
4 | 4 | use rustc_fs_util::fix_windows_verbatim_for_gcc; |
5 | 5 | use rustc_hir::def_id::CrateNum; |
6 | | -use rustc_middle::middle::cstore::LibSource; |
| 6 | +use rustc_middle::middle::cstore::{DllImport, LibSource}; |
7 | 7 | use rustc_middle::middle::dependency_format::Linkage; |
8 | 8 | use rustc_session::config::{self, CFGuard, CrateType, DebugInfo}; |
9 | 9 | use rustc_session::config::{OutputFilenames, OutputType, PrintRequest}; |
@@ -34,6 +34,7 @@ use object::write::Object; |
34 | 34 | use object::{Architecture, BinaryFormat, Endianness, FileFlags, SectionFlags, SectionKind}; |
35 | 35 | use tempfile::Builder as TempFileBuilder; |
36 | 36 |
|
| 37 | +use std::cmp::Ordering; |
37 | 38 | use std::ffi::OsString; |
38 | 39 | use std::path::{Path, PathBuf}; |
39 | 40 | use std::process::{ExitStatus, Output, Stdio}; |
@@ -343,6 +344,12 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( |
343 | 344 | } |
344 | 345 | } |
345 | 346 |
|
| 347 | + for (raw_dylib_name, raw_dylib_imports) in |
| 348 | + collate_raw_dylibs(&codegen_results.crate_info.used_libraries) |
| 349 | + { |
| 350 | + ab.inject_dll_import_lib(&raw_dylib_name, &raw_dylib_imports, tmpdir); |
| 351 | + } |
| 352 | + |
346 | 353 | // After adding all files to the archive, we need to update the |
347 | 354 | // symbol table of the archive. |
348 | 355 | ab.update_symbols(); |
@@ -524,6 +531,57 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( |
524 | 531 | } |
525 | 532 | } |
526 | 533 |
|
| 534 | +/// Extract all symbols defined in raw-dylib libraries, collated by library name. |
| 535 | +/// |
| 536 | +/// If we have multiple extern blocks that specify symbols defined in the same raw-dylib library, |
| 537 | +/// then the CodegenResults value contains one NativeLib instance for each block. However, the |
| 538 | +/// linker appears to expect only a single import library for each library used, so we need to |
| 539 | +/// collate the symbols together by library name before generating the import libraries. |
| 540 | +fn collate_raw_dylibs(used_libraries: &[NativeLib]) -> Vec<(String, Vec<DllImport>)> { |
| 541 | + let mut dylib_table: FxHashMap<String, FxHashSet<Symbol>> = FxHashMap::default(); |
| 542 | + |
| 543 | + for lib in used_libraries { |
| 544 | + if lib.kind == NativeLibKind::RawDylib { |
| 545 | + let name = lib.name.unwrap_or_else(|| |
| 546 | + bug!("`link` attribute with kind = \"raw-dylib\" and no name should have caused error earlier") |
| 547 | + ); |
| 548 | + let name = if matches!(lib.verbatim, Some(true)) { |
| 549 | + name.to_string() |
| 550 | + } else { |
| 551 | + format!("{}.dll", name) |
| 552 | + }; |
| 553 | + dylib_table |
| 554 | + .entry(name) |
| 555 | + .or_default() |
| 556 | + .extend(lib.dll_imports.iter().map(|import| import.name)); |
| 557 | + } |
| 558 | + } |
| 559 | + |
| 560 | + // FIXME: when we add support for ordinals, fix this to propagate ordinals. Also figure out |
| 561 | + // what we should do if we have two DllImport values with the same name but different |
| 562 | + // ordinals. |
| 563 | + let mut result = dylib_table |
| 564 | + .into_iter() |
| 565 | + .map(|(lib_name, imported_names)| { |
| 566 | + let mut names = imported_names |
| 567 | + .iter() |
| 568 | + .map(|name| DllImport { name: *name, ordinal: None }) |
| 569 | + .collect::<Vec<_>>(); |
| 570 | + names.sort_unstable_by(|a: &DllImport, b: &DllImport| { |
| 571 | + match a.name.as_str().cmp(&b.name.as_str()) { |
| 572 | + Ordering::Equal => a.ordinal.cmp(&b.ordinal), |
| 573 | + x => x, |
| 574 | + } |
| 575 | + }); |
| 576 | + (lib_name, names) |
| 577 | + }) |
| 578 | + .collect::<Vec<_>>(); |
| 579 | + result.sort_unstable_by(|a: &(String, Vec<DllImport>), b: &(String, Vec<DllImport>)| { |
| 580 | + a.0.cmp(&b.0) |
| 581 | + }); |
| 582 | + result |
| 583 | +} |
| 584 | + |
527 | 585 | /// Create a static archive. |
528 | 586 | /// |
529 | 587 | /// This is essentially the same thing as an rlib, but it also involves adding all of the upstream |
@@ -2303,10 +2361,7 @@ fn add_upstream_native_libraries( |
2303 | 2361 | // already included them when we included the rust library |
2304 | 2362 | // previously |
2305 | 2363 | NativeLibKind::Static { bundle: None | Some(true), .. } => {} |
2306 | | - NativeLibKind::RawDylib => { |
2307 | | - // FIXME(#58713): Proper handling for raw dylibs. |
2308 | | - bug!("raw_dylib feature not yet implemented"); |
2309 | | - } |
| 2364 | + NativeLibKind::RawDylib => {} |
2310 | 2365 | } |
2311 | 2366 | } |
2312 | 2367 | } |
|
0 commit comments