1
+ use std:: borrow:: Borrow ;
2
+ use std:: fmt:: Write ;
3
+ use std:: fs;
1
4
use std:: path:: { Path , PathBuf } ;
2
5
6
+ use ar_archive_writer:: { COFFShortExport , MachineTypes } ;
3
7
use rustc_codegen_ssa:: back:: archive:: {
4
8
ArArchiveBuilder , ArchiveBuilder , ArchiveBuilderBuilder , DEFAULT_OBJECT_READER ,
5
9
} ;
10
+ use rustc_session:: cstore:: { DllCallingConvention , DllImport , PeImportNameType } ;
6
11
use rustc_session:: Session ;
7
12
8
13
pub ( crate ) struct ArArchiveBuilderBuilder ;
@@ -15,11 +20,121 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
15
20
fn create_dll_import_lib (
16
21
& self ,
17
22
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 ,
22
27
) -> 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
24
91
}
25
92
}
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