|
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