1
1
//! A helper class for dealing with static archives
2
2
3
- use std:: ffi:: { c_char, c_void, CStr , CString , OsString } ;
3
+ use std:: ffi:: { c_char, c_void, CStr , CString } ;
4
4
use std:: path:: { Path , PathBuf } ;
5
- use std:: { env , io, mem, ptr, str} ;
5
+ use std:: { io, mem, ptr, str} ;
6
6
7
7
use rustc_codegen_ssa:: back:: archive:: {
8
- try_extract_macho_fat_archive, ArArchiveBuilder , ArchiveBuildFailure , ArchiveBuilder ,
9
- ArchiveBuilderBuilder , ObjectReader , UnknownArchiveKind , DEFAULT_OBJECT_READER ,
8
+ create_mingw_dll_import_lib, try_extract_macho_fat_archive, ArArchiveBuilder ,
9
+ ArchiveBuildFailure , ArchiveBuilder , ArchiveBuilderBuilder , ObjectReader , UnknownArchiveKind ,
10
+ DEFAULT_OBJECT_READER ,
10
11
} ;
11
- use rustc_session :: cstore :: DllImport ;
12
+ use rustc_codegen_ssa :: common ;
12
13
use rustc_session:: Session ;
13
14
use tracing:: trace;
14
15
15
- use crate :: common;
16
- use crate :: errors:: {
17
- DlltoolFailImportLibrary , ErrorCallingDllTool , ErrorCreatingImportLibrary , ErrorWritingDEFFile ,
18
- } ;
16
+ use crate :: errors:: ErrorCreatingImportLibrary ;
19
17
use crate :: llvm:: archive_ro:: { ArchiveRO , Child } ;
20
18
use crate :: llvm:: { self , ArchiveKind , LLVMMachineType , LLVMRustCOFFShortExport } ;
21
19
@@ -121,116 +119,21 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
121
119
& self ,
122
120
sess : & Session ,
123
121
lib_name : & str ,
124
- dll_imports : & [ DllImport ] ,
125
- tmpdir : & Path ,
126
- is_direct_dependency : bool ,
127
- ) -> PathBuf {
128
- let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" } ;
129
- let output_path = tmpdir. join ( format ! ( "{lib_name}{name_suffix}.lib" ) ) ;
130
-
131
- let target = & sess. target ;
132
- let mingw_gnu_toolchain = common:: is_mingw_gnu_toolchain ( target) ;
133
-
134
- let import_name_and_ordinal_vector: Vec < ( String , Option < u16 > ) > = dll_imports
135
- . iter ( )
136
- . map ( |import : & DllImport | {
137
- if sess. target . arch == "x86" {
138
- (
139
- common:: i686_decorated_name ( import, mingw_gnu_toolchain, false ) ,
140
- import. ordinal ( ) ,
141
- )
142
- } else {
143
- ( import. name . to_string ( ) , import. ordinal ( ) )
144
- }
145
- } )
146
- . collect ( ) ;
147
-
148
- if mingw_gnu_toolchain {
122
+ import_name_and_ordinal_vector : Vec < ( String , Option < u16 > ) > ,
123
+ output_path : & Path ,
124
+ ) {
125
+ if common:: is_mingw_gnu_toolchain ( & sess. target ) {
149
126
// The binutils linker used on -windows-gnu targets cannot read the import
150
127
// libraries generated by LLVM: in our attempts, the linker produced an .EXE
151
128
// that loaded but crashed with an AV upon calling one of the imported
152
129
// functions. Therefore, use binutils to create the import library instead,
153
130
// by writing a .DEF file to the temp dir and calling binutils's dlltool.
154
- let def_file_path = tmpdir. join ( format ! ( "{lib_name}{name_suffix}.def" ) ) ;
155
-
156
- let def_file_content = format ! (
157
- "EXPORTS\n {}" ,
158
- import_name_and_ordinal_vector
159
- . into_iter( )
160
- . map( |( name, ordinal) | {
161
- match ordinal {
162
- Some ( n) => format!( "{name} @{n} NONAME" ) ,
163
- None => name,
164
- }
165
- } )
166
- . collect:: <Vec <String >>( )
167
- . join( "\n " )
131
+ create_mingw_dll_import_lib (
132
+ sess,
133
+ lib_name,
134
+ import_name_and_ordinal_vector,
135
+ output_path,
168
136
) ;
169
-
170
- match std:: fs:: write ( & def_file_path, def_file_content) {
171
- Ok ( _) => { }
172
- Err ( e) => {
173
- sess. dcx ( ) . emit_fatal ( ErrorWritingDEFFile { error : e } ) ;
174
- }
175
- } ;
176
-
177
- // --no-leading-underscore: For the `import_name_type` feature to work, we need to be
178
- // able to control the *exact* spelling of each of the symbols that are being imported:
179
- // hence we don't want `dlltool` adding leading underscores automatically.
180
- let dlltool = find_binutils_dlltool ( sess) ;
181
- let temp_prefix = {
182
- let mut path = PathBuf :: from ( & output_path) ;
183
- path. pop ( ) ;
184
- path. push ( lib_name) ;
185
- path
186
- } ;
187
- // dlltool target architecture args from:
188
- // https://github.com/llvm/llvm-project-release-prs/blob/llvmorg-15.0.6/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp#L69
189
- let ( dlltool_target_arch, dlltool_target_bitness) = match sess. target . arch . as_ref ( ) {
190
- "x86_64" => ( "i386:x86-64" , "--64" ) ,
191
- "x86" => ( "i386" , "--32" ) ,
192
- "aarch64" => ( "arm64" , "--64" ) ,
193
- "arm" => ( "arm" , "--32" ) ,
194
- _ => panic ! ( "unsupported arch {}" , sess. target. arch) ,
195
- } ;
196
- let mut dlltool_cmd = std:: process:: Command :: new ( & dlltool) ;
197
- dlltool_cmd
198
- . arg ( "-d" )
199
- . arg ( def_file_path)
200
- . arg ( "-D" )
201
- . arg ( lib_name)
202
- . arg ( "-l" )
203
- . arg ( & output_path)
204
- . arg ( "-m" )
205
- . arg ( dlltool_target_arch)
206
- . arg ( "-f" )
207
- . arg ( dlltool_target_bitness)
208
- . arg ( "--no-leading-underscore" )
209
- . arg ( "--temp-prefix" )
210
- . arg ( temp_prefix) ;
211
-
212
- match dlltool_cmd. output ( ) {
213
- Err ( e) => {
214
- sess. dcx ( ) . emit_fatal ( ErrorCallingDllTool {
215
- dlltool_path : dlltool. to_string_lossy ( ) ,
216
- error : e,
217
- } ) ;
218
- }
219
- // dlltool returns '0' on failure, so check for error output instead.
220
- Ok ( output) if !output. stderr . is_empty ( ) => {
221
- sess. dcx ( ) . emit_fatal ( DlltoolFailImportLibrary {
222
- dlltool_path : dlltool. to_string_lossy ( ) ,
223
- dlltool_args : dlltool_cmd
224
- . get_args ( )
225
- . map ( |arg| arg. to_string_lossy ( ) )
226
- . collect :: < Vec < _ > > ( )
227
- . join ( " " ) ,
228
- stdout : String :: from_utf8_lossy ( & output. stdout ) ,
229
- stderr : String :: from_utf8_lossy ( & output. stderr ) ,
230
- } )
231
- }
232
- _ => { }
233
- }
234
137
} else {
235
138
// we've checked for \0 characters in the library name already
236
139
let dll_name_z = CString :: new ( lib_name) . unwrap ( ) ;
@@ -242,9 +145,9 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
242
145
trace ! ( " output_path {}" , output_path. display( ) ) ;
243
146
trace ! (
244
147
" import names: {}" ,
245
- dll_imports
148
+ import_name_and_ordinal_vector
246
149
. iter( )
247
- . map( |import| import . name. to_string ( ) )
150
+ . map( |( name , _ordinal ) | name. clone ( ) )
248
151
. collect:: <Vec <_>>( )
249
152
. join( ", " ) ,
250
153
) ;
@@ -281,9 +184,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
281
184
error : llvm:: last_error ( ) . unwrap_or ( "unknown LLVM error" . to_string ( ) ) ,
282
185
} ) ;
283
186
}
284
- } ;
285
-
286
- output_path
187
+ }
287
188
}
288
189
}
289
190
@@ -457,39 +358,3 @@ impl<'a> LlvmArchiveBuilder<'a> {
457
358
fn string_to_io_error ( s : String ) -> io:: Error {
458
359
io:: Error :: new ( io:: ErrorKind :: Other , format ! ( "bad archive: {s}" ) )
459
360
}
460
-
461
- fn find_binutils_dlltool ( sess : & Session ) -> OsString {
462
- assert ! ( sess. target. options. is_like_windows && !sess. target. options. is_like_msvc) ;
463
- if let Some ( dlltool_path) = & sess. opts . cg . dlltool {
464
- return dlltool_path. clone ( ) . into_os_string ( ) ;
465
- }
466
-
467
- let tool_name: OsString = if sess. host . options . is_like_windows {
468
- // If we're compiling on Windows, always use "dlltool.exe".
469
- "dlltool.exe"
470
- } else {
471
- // On other platforms, use the architecture-specific name.
472
- match sess. target . arch . as_ref ( ) {
473
- "x86_64" => "x86_64-w64-mingw32-dlltool" ,
474
- "x86" => "i686-w64-mingw32-dlltool" ,
475
- "aarch64" => "aarch64-w64-mingw32-dlltool" ,
476
-
477
- // For non-standard architectures (e.g., aarch32) fallback to "dlltool".
478
- _ => "dlltool" ,
479
- }
480
- }
481
- . into ( ) ;
482
-
483
- // NOTE: it's not clear how useful it is to explicitly search PATH.
484
- for dir in env:: split_paths ( & env:: var_os ( "PATH" ) . unwrap_or_default ( ) ) {
485
- let full_path = dir. join ( & tool_name) ;
486
- if full_path. is_file ( ) {
487
- return full_path. into_os_string ( ) ;
488
- }
489
- }
490
-
491
- // The user didn't specify the location of the dlltool binary, and we weren't able
492
- // to find the appropriate one on the PATH. Just return the name of the tool
493
- // and let the invocation fail with a hopefully useful error message.
494
- tool_name
495
- }
0 commit comments