11//! A helper class for dealing with static archives
22
3- use std:: ffi:: { c_char, c_void, CStr , CString , OsString } ;
3+ use std:: ffi:: { c_char, c_void, CStr , CString } ;
44use std:: path:: { Path , PathBuf } ;
5- use std:: { env , io, mem, ptr, str} ;
5+ use std:: { io, mem, ptr, str} ;
66
77use 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 ,
1011} ;
11- use rustc_session :: cstore :: DllImport ;
12+ use rustc_codegen_ssa :: common ;
1213use rustc_session:: Session ;
1314use tracing:: trace;
1415
15- use crate :: common;
16- use crate :: errors:: {
17- DlltoolFailImportLibrary , ErrorCallingDllTool , ErrorCreatingImportLibrary , ErrorWritingDEFFile ,
18- } ;
16+ use crate :: errors:: ErrorCreatingImportLibrary ;
1917use crate :: llvm:: archive_ro:: { ArchiveRO , Child } ;
2018use crate :: llvm:: { self , ArchiveKind , LLVMMachineType , LLVMRustCOFFShortExport } ;
2119
@@ -121,116 +119,21 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
121119 & self ,
122120 sess : & Session ,
123121 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 ) {
149126 // The binutils linker used on -windows-gnu targets cannot read the import
150127 // libraries generated by LLVM: in our attempts, the linker produced an .EXE
151128 // that loaded but crashed with an AV upon calling one of the imported
152129 // functions. Therefore, use binutils to create the import library instead,
153130 // 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,
168136 ) ;
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- }
234137 } else {
235138 // we've checked for \0 characters in the library name already
236139 let dll_name_z = CString :: new ( lib_name) . unwrap ( ) ;
@@ -242,9 +145,9 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
242145 trace ! ( " output_path {}" , output_path. display( ) ) ;
243146 trace ! (
244147 " import names: {}" ,
245- dll_imports
148+ import_name_and_ordinal_vector
246149 . iter( )
247- . map( |import| import . name. to_string ( ) )
150+ . map( |( name , _ordinal ) | name. clone ( ) )
248151 . collect:: <Vec <_>>( )
249152 . join( ", " ) ,
250153 ) ;
@@ -281,9 +184,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
281184 error : llvm:: last_error ( ) . unwrap_or ( "unknown LLVM error" . to_string ( ) ) ,
282185 } ) ;
283186 }
284- } ;
285-
286- output_path
187+ }
287188 }
288189}
289190
@@ -457,39 +358,3 @@ impl<'a> LlvmArchiveBuilder<'a> {
457358fn string_to_io_error ( s : String ) -> io:: Error {
458359 io:: Error :: new ( io:: ErrorKind :: Other , format ! ( "bad archive: {s}" ) )
459360}
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