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