|
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 | 12 | use rustc_codegen_ssa::common; |
12 | 13 | use rustc_session::Session; |
13 | 14 | use tracing::trace; |
14 | 15 |
|
15 | | -use crate::errors::{ |
16 | | - DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile, |
17 | | -}; |
| 16 | +use crate::errors::ErrorCreatingImportLibrary; |
18 | 17 | use crate::llvm::archive_ro::{ArchiveRO, Child}; |
19 | 18 | use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport}; |
20 | 19 |
|
@@ -121,95 +120,18 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { |
121 | 120 | import_name_and_ordinal_vector: Vec<(String, Option<u16>)>, |
122 | 121 | output_path: &Path, |
123 | 122 | ) { |
124 | | - let target = &sess.target; |
125 | | - let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(target); |
126 | | - |
127 | | - if mingw_gnu_toolchain { |
| 123 | + if common::is_mingw_gnu_toolchain(&sess.target) { |
128 | 124 | // The binutils linker used on -windows-gnu targets cannot read the import |
129 | 125 | // libraries generated by LLVM: in our attempts, the linker produced an .EXE |
130 | 126 | // that loaded but crashed with an AV upon calling one of the imported |
131 | 127 | // functions. Therefore, use binutils to create the import library instead, |
132 | 128 | // by writing a .DEF file to the temp dir and calling binutils's dlltool. |
133 | | - let def_file_path = output_path.with_extension("def"); |
134 | | - |
135 | | - let def_file_content = format!( |
136 | | - "EXPORTS\n{}", |
137 | | - import_name_and_ordinal_vector |
138 | | - .into_iter() |
139 | | - .map(|(name, ordinal)| { |
140 | | - match ordinal { |
141 | | - Some(n) => format!("{name} @{n} NONAME"), |
142 | | - None => name, |
143 | | - } |
144 | | - }) |
145 | | - .collect::<Vec<String>>() |
146 | | - .join("\n") |
| 129 | + create_mingw_dll_import_lib( |
| 130 | + sess, |
| 131 | + lib_name, |
| 132 | + import_name_and_ordinal_vector, |
| 133 | + output_path, |
147 | 134 | ); |
148 | | - |
149 | | - match std::fs::write(&def_file_path, def_file_content) { |
150 | | - Ok(_) => {} |
151 | | - Err(e) => { |
152 | | - sess.dcx().emit_fatal(ErrorWritingDEFFile { error: e }); |
153 | | - } |
154 | | - }; |
155 | | - |
156 | | - // --no-leading-underscore: For the `import_name_type` feature to work, we need to be |
157 | | - // able to control the *exact* spelling of each of the symbols that are being imported: |
158 | | - // hence we don't want `dlltool` adding leading underscores automatically. |
159 | | - let dlltool = find_binutils_dlltool(sess); |
160 | | - let temp_prefix = { |
161 | | - let mut path = PathBuf::from(&output_path); |
162 | | - path.pop(); |
163 | | - path.push(lib_name); |
164 | | - path |
165 | | - }; |
166 | | - // dlltool target architecture args from: |
167 | | - // https://github.com/llvm/llvm-project-release-prs/blob/llvmorg-15.0.6/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp#L69 |
168 | | - let (dlltool_target_arch, dlltool_target_bitness) = match sess.target.arch.as_ref() { |
169 | | - "x86_64" => ("i386:x86-64", "--64"), |
170 | | - "x86" => ("i386", "--32"), |
171 | | - "aarch64" => ("arm64", "--64"), |
172 | | - "arm" => ("arm", "--32"), |
173 | | - _ => panic!("unsupported arch {}", sess.target.arch), |
174 | | - }; |
175 | | - let mut dlltool_cmd = std::process::Command::new(&dlltool); |
176 | | - dlltool_cmd |
177 | | - .arg("-d") |
178 | | - .arg(def_file_path) |
179 | | - .arg("-D") |
180 | | - .arg(lib_name) |
181 | | - .arg("-l") |
182 | | - .arg(&output_path) |
183 | | - .arg("-m") |
184 | | - .arg(dlltool_target_arch) |
185 | | - .arg("-f") |
186 | | - .arg(dlltool_target_bitness) |
187 | | - .arg("--no-leading-underscore") |
188 | | - .arg("--temp-prefix") |
189 | | - .arg(temp_prefix); |
190 | | - |
191 | | - match dlltool_cmd.output() { |
192 | | - Err(e) => { |
193 | | - sess.dcx().emit_fatal(ErrorCallingDllTool { |
194 | | - dlltool_path: dlltool.to_string_lossy(), |
195 | | - error: e, |
196 | | - }); |
197 | | - } |
198 | | - // dlltool returns '0' on failure, so check for error output instead. |
199 | | - Ok(output) if !output.stderr.is_empty() => { |
200 | | - sess.dcx().emit_fatal(DlltoolFailImportLibrary { |
201 | | - dlltool_path: dlltool.to_string_lossy(), |
202 | | - dlltool_args: dlltool_cmd |
203 | | - .get_args() |
204 | | - .map(|arg| arg.to_string_lossy()) |
205 | | - .collect::<Vec<_>>() |
206 | | - .join(" "), |
207 | | - stdout: String::from_utf8_lossy(&output.stdout), |
208 | | - stderr: String::from_utf8_lossy(&output.stderr), |
209 | | - }) |
210 | | - } |
211 | | - _ => {} |
212 | | - } |
213 | 135 | } else { |
214 | 136 | // we've checked for \0 characters in the library name already |
215 | 137 | let dll_name_z = CString::new(lib_name).unwrap(); |
@@ -434,39 +356,3 @@ impl<'a> LlvmArchiveBuilder<'a> { |
434 | 356 | fn string_to_io_error(s: String) -> io::Error { |
435 | 357 | io::Error::new(io::ErrorKind::Other, format!("bad archive: {s}")) |
436 | 358 | } |
437 | | - |
438 | | -fn find_binutils_dlltool(sess: &Session) -> OsString { |
439 | | - assert!(sess.target.options.is_like_windows && !sess.target.options.is_like_msvc); |
440 | | - if let Some(dlltool_path) = &sess.opts.cg.dlltool { |
441 | | - return dlltool_path.clone().into_os_string(); |
442 | | - } |
443 | | - |
444 | | - let tool_name: OsString = if sess.host.options.is_like_windows { |
445 | | - // If we're compiling on Windows, always use "dlltool.exe". |
446 | | - "dlltool.exe" |
447 | | - } else { |
448 | | - // On other platforms, use the architecture-specific name. |
449 | | - match sess.target.arch.as_ref() { |
450 | | - "x86_64" => "x86_64-w64-mingw32-dlltool", |
451 | | - "x86" => "i686-w64-mingw32-dlltool", |
452 | | - "aarch64" => "aarch64-w64-mingw32-dlltool", |
453 | | - |
454 | | - // For non-standard architectures (e.g., aarch32) fallback to "dlltool". |
455 | | - _ => "dlltool", |
456 | | - } |
457 | | - } |
458 | | - .into(); |
459 | | - |
460 | | - // NOTE: it's not clear how useful it is to explicitly search PATH. |
461 | | - for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) { |
462 | | - let full_path = dir.join(&tool_name); |
463 | | - if full_path.is_file() { |
464 | | - return full_path.into_os_string(); |
465 | | - } |
466 | | - } |
467 | | - |
468 | | - // The user didn't specify the location of the dlltool binary, and we weren't able |
469 | | - // to find the appropriate one on the PATH. Just return the name of the tool |
470 | | - // and let the invocation fail with a hopefully useful error message. |
471 | | - tool_name |
472 | | -} |
0 commit comments