1+ use std:: borrow:: Borrow ;
2+ use std:: fmt:: Write ;
3+ use std:: fs;
14use std:: path:: { Path , PathBuf } ;
25
6+ use ar_archive_writer:: { COFFShortExport , MachineTypes } ;
37use rustc_codegen_ssa:: back:: archive:: {
48 ArArchiveBuilder , ArchiveBuilder , ArchiveBuilderBuilder , DEFAULT_OBJECT_READER ,
59} ;
10+ use rustc_session:: cstore:: { DllCallingConvention , DllImport , PeImportNameType } ;
611use rustc_session:: Session ;
712
813pub ( crate ) struct ArArchiveBuilderBuilder ;
@@ -15,11 +20,121 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
1520 fn create_dll_import_lib (
1621 & self ,
1722 sess : & Session ,
18- _lib_name : & str ,
19- _dll_imports : & [ rustc_session :: cstore :: DllImport ] ,
20- _tmpdir : & Path ,
21- _is_direct_dependency : bool ,
23+ lib_name : & str ,
24+ dll_imports : & [ DllImport ] ,
25+ tmpdir : & Path ,
26+ is_direct_dependency : bool ,
2227 ) -> PathBuf {
23- sess. dcx ( ) . fatal ( "raw-dylib is not yet supported by rustc_codegen_cranelift" ) ;
28+ let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" } ;
29+ let output_path = tmpdir. join ( format ! ( "{lib_name}{name_suffix}.lib" ) ) ;
30+
31+ let mut file = match fs:: OpenOptions :: new ( ) . write ( true ) . create_new ( true ) . open ( & output_path)
32+ {
33+ Ok ( file) => file,
34+ Err ( error) => {
35+ sess. dcx ( ) . fatal ( format ! (
36+ "failed to create import library file `{path}`: {error}" ,
37+ path = output_path. display( ) ,
38+ ) ) ;
39+ }
40+ } ;
41+
42+ let machine = match sess. target . arch . borrow ( ) {
43+ "x86" => MachineTypes :: I386 ,
44+ "x86_64" => MachineTypes :: AMD64 ,
45+ "arm" => MachineTypes :: ARMNT ,
46+ "aarch64" => MachineTypes :: ARM64 ,
47+ _ => {
48+ sess. dcx ( ) . fatal ( format ! (
49+ "unsupported target architecture `{arch}`" ,
50+ arch = sess. target. arch,
51+ ) ) ;
52+ }
53+ } ;
54+
55+ let exports = dll_imports
56+ . iter ( )
57+ . map ( |import| {
58+ let name = if machine == MachineTypes :: I386 {
59+ i686_decorated_name ( import, !sess. target . is_like_msvc )
60+ } else {
61+ import. name . to_string ( )
62+ } ;
63+ COFFShortExport {
64+ name,
65+ ext_name : None ,
66+ symbol_name : None ,
67+ alias_target : None ,
68+ ordinal : import. ordinal ( ) . unwrap_or ( 0 ) ,
69+ noname : import. ordinal ( ) . is_some ( ) ,
70+ data : false ,
71+ private : false ,
72+ constant : false ,
73+ }
74+ } )
75+ . collect :: < Vec < _ > > ( ) ;
76+
77+ if let Err ( error) = ar_archive_writer:: write_import_library (
78+ & mut file,
79+ lib_name,
80+ & exports,
81+ machine,
82+ !sess. target . is_like_msvc ,
83+ ) {
84+ sess. dcx ( ) . fatal ( format ! (
85+ "failed to create import library `{path}`: `{error}`" ,
86+ path = output_path. display( ) ,
87+ ) ) ;
88+ }
89+
90+ output_path
2491 }
2592}
93+
94+ fn i686_decorated_name ( dll_import : & DllImport , mingw : bool ) -> String {
95+ let name = dll_import. name . as_str ( ) ;
96+
97+ let ( add_prefix, add_suffix) = match dll_import. import_name_type {
98+ Some ( PeImportNameType :: NoPrefix ) => ( false , true ) ,
99+ Some ( PeImportNameType :: Undecorated ) => ( false , false ) ,
100+ _ => ( true , true ) ,
101+ } ;
102+
103+ // Worst case: +1 for prefix, +4 for suffix (@@__).
104+ let mut decorated_name = String :: with_capacity ( name. len ( ) + 5 ) ;
105+
106+ let prefix = if add_prefix && dll_import. is_fn {
107+ match dll_import. calling_convention {
108+ DllCallingConvention :: C | DllCallingConvention :: Vectorcall ( _) => None ,
109+ DllCallingConvention :: Stdcall ( _) => ( !mingw
110+ || dll_import. import_name_type == Some ( PeImportNameType :: Decorated ) )
111+ . then_some ( '_' ) ,
112+ DllCallingConvention :: Fastcall ( _) => Some ( '@' ) ,
113+ }
114+ } else if !dll_import. is_fn && !mingw {
115+ // For static variables, prefix with '_' on MSVC.
116+ Some ( '_' )
117+ } else {
118+ None
119+ } ;
120+ if let Some ( prefix) = prefix {
121+ decorated_name. push ( prefix) ;
122+ }
123+
124+ decorated_name. push_str ( name) ;
125+
126+ if add_suffix && dll_import. is_fn {
127+ match dll_import. calling_convention {
128+ DllCallingConvention :: C => { }
129+ DllCallingConvention :: Stdcall ( arg_list_size)
130+ | DllCallingConvention :: Fastcall ( arg_list_size) => {
131+ write ! ( & mut decorated_name, "@{arg_list_size}" ) . unwrap ( ) ;
132+ }
133+ DllCallingConvention :: Vectorcall ( arg_list_size) => {
134+ write ! ( & mut decorated_name, "@@{arg_list_size}" ) . unwrap ( ) ;
135+ }
136+ }
137+ }
138+
139+ decorated_name
140+ }
0 commit comments