|
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
|
@@ -2302,10 +2360,7 @@ fn add_upstream_native_libraries(
|
2302 | 2360 | // already included them when we included the rust library
|
2303 | 2361 | // previously
|
2304 | 2362 | NativeLibKind::Static { bundle: None | Some(true), .. } => {}
|
2305 |
| - NativeLibKind::RawDylib => { |
2306 |
| - // FIXME(#58713): Proper handling for raw dylibs. |
2307 |
| - bug!("raw_dylib feature not yet implemented"); |
2308 |
| - } |
| 2363 | + NativeLibKind::RawDylib => {} |
2309 | 2364 | }
|
2310 | 2365 | }
|
2311 | 2366 | }
|
|
0 commit comments