1- use rustc_data_structures:: fx:: FxHashSet ;
1+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
22use rustc_data_structures:: temp_dir:: MaybeTempDir ;
33use rustc_errors:: Handler ;
44use rustc_fs_util:: fix_windows_verbatim_for_gcc;
55use rustc_hir:: def_id:: CrateNum ;
6- use rustc_middle:: middle:: cstore:: { EncodedMetadata , LibSource } ;
6+ use rustc_middle:: middle:: cstore:: { DllImport , EncodedMetadata , LibSource } ;
77use rustc_middle:: middle:: dependency_format:: Linkage ;
88use rustc_session:: config:: { self , CFGuard , CrateType , DebugInfo } ;
99use rustc_session:: config:: { OutputFilenames , OutputType , PrintRequest } ;
@@ -30,6 +30,7 @@ use crate::{
3030use cc:: windows_registry;
3131use tempfile:: Builder as TempFileBuilder ;
3232
33+ use std:: cmp:: Ordering ;
3334use std:: ffi:: OsString ;
3435use std:: path:: { Path , PathBuf } ;
3536use std:: process:: { ExitStatus , Output , Stdio } ;
@@ -339,6 +340,12 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
339340 }
340341 }
341342
343+ for ( raw_dylib_name, raw_dylib_imports) in
344+ collate_raw_dylibs ( & codegen_results. crate_info . used_libraries )
345+ {
346+ ab. inject_dll_import_lib ( & raw_dylib_name, & raw_dylib_imports, tmpdir) ;
347+ }
348+
342349 // After adding all files to the archive, we need to update the
343350 // symbol table of the archive.
344351 ab. update_symbols ( ) ;
@@ -389,6 +396,57 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
389396 ab
390397}
391398
399+ /// Extract all symbols defined in raw-dylib libraries, collated by library name.
400+ ///
401+ /// If we have multiple extern blocks that specify symbols defined in the same raw-dylib library,
402+ /// then the CodegenResults value contains one NativeLib instance for each block. However, the
403+ /// linker appears to expect only a single import library for each library used, so we need to
404+ /// collate the symbols together by library name before generating the import libraries.
405+ fn collate_raw_dylibs ( used_libraries : & [ NativeLib ] ) -> Vec < ( String , Vec < DllImport > ) > {
406+ let mut dylib_table: FxHashMap < String , FxHashSet < Symbol > > = FxHashMap :: default ( ) ;
407+
408+ for lib in used_libraries {
409+ if lib. kind == NativeLibKind :: RawDylib {
410+ let name = lib. name . unwrap_or_else ( ||
411+ bug ! ( "`link` attribute with kind = \" raw-dylib\" and no name should have caused error earlier" )
412+ ) ;
413+ let name = if matches ! ( lib. verbatim, Some ( true ) ) {
414+ name. to_string ( )
415+ } else {
416+ format ! ( "{}.dll" , name)
417+ } ;
418+ dylib_table
419+ . entry ( name)
420+ . or_default ( )
421+ . extend ( lib. dll_imports . iter ( ) . map ( |import| import. name ) ) ;
422+ }
423+ }
424+
425+ // FIXME: when we add support for ordinals, fix this to propagate ordinals. Also figure out
426+ // what we should do if we have two DllImport values with the same name but different
427+ // ordinals.
428+ let mut result = dylib_table
429+ . into_iter ( )
430+ . map ( |( lib_name, imported_names) | {
431+ let mut names = imported_names
432+ . iter ( )
433+ . map ( |name| DllImport { name : * name, ordinal : None } )
434+ . collect :: < Vec < _ > > ( ) ;
435+ names. sort_unstable_by ( |a : & DllImport , b : & DllImport | {
436+ match a. name . as_str ( ) . cmp ( & b. name . as_str ( ) ) {
437+ Ordering :: Equal => a. ordinal . cmp ( & b. ordinal ) ,
438+ x => x,
439+ }
440+ } ) ;
441+ ( lib_name, names)
442+ } )
443+ . collect :: < Vec < _ > > ( ) ;
444+ result. sort_unstable_by ( |a : & ( String , Vec < DllImport > ) , b : & ( String , Vec < DllImport > ) | {
445+ a. 0 . cmp ( & b. 0 )
446+ } ) ;
447+ result
448+ }
449+
392450/// Create a static archive.
393451///
394452/// This is essentially the same thing as an rlib, but it also involves adding all of the upstream
@@ -2176,10 +2234,7 @@ fn add_upstream_native_libraries(
21762234 // already included them when we included the rust library
21772235 // previously
21782236 NativeLibKind :: Static { bundle : None | Some ( true ) , .. } => { }
2179- NativeLibKind :: RawDylib => {
2180- // FIXME(#58713): Proper handling for raw dylibs.
2181- bug ! ( "raw_dylib feature not yet implemented" ) ;
2182- }
2237+ NativeLibKind :: RawDylib => { }
21832238 }
21842239 }
21852240 }
0 commit comments