diff options
Diffstat (limited to 'compiler/rustc_codegen_llvm/src/back/archive.rs')
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/back/archive.rs | 173 |
1 files changed, 19 insertions, 154 deletions
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index 2f5a864d70e..a2ab19ac800 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -1,21 +1,19 @@ //! A helper class for dealing with static archives -use std::ffi::{c_char, c_void, CStr, CString, OsString}; +use std::ffi::{c_char, c_void, CStr, CString}; use std::path::{Path, PathBuf}; -use std::{env, io, mem, ptr, str}; +use std::{io, mem, ptr, str}; use rustc_codegen_ssa::back::archive::{ - try_extract_macho_fat_archive, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder, - ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind, DEFAULT_OBJECT_READER, + create_mingw_dll_import_lib, try_extract_macho_fat_archive, ArArchiveBuilder, + ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind, + DEFAULT_OBJECT_READER, }; -use rustc_session::cstore::DllImport; +use rustc_codegen_ssa::common; use rustc_session::Session; use tracing::trace; -use crate::common; -use crate::errors::{ - DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile, -}; +use crate::errors::ErrorCreatingImportLibrary; use crate::llvm::archive_ro::{ArchiveRO, Child}; use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport}; @@ -121,116 +119,21 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { &self, sess: &Session, lib_name: &str, - dll_imports: &[DllImport], - tmpdir: &Path, - is_direct_dependency: bool, - ) -> PathBuf { - let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" }; - let output_path = tmpdir.join(format!("{lib_name}{name_suffix}.lib")); - - let target = &sess.target; - let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(target); - - let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = dll_imports - .iter() - .map(|import: &DllImport| { - if sess.target.arch == "x86" { - ( - common::i686_decorated_name(import, mingw_gnu_toolchain, false), - import.ordinal(), - ) - } else { - (import.name.to_string(), import.ordinal()) - } - }) - .collect(); - - if mingw_gnu_toolchain { + import_name_and_ordinal_vector: Vec<(String, Option<u16>)>, + output_path: &Path, + ) { + if common::is_mingw_gnu_toolchain(&sess.target) { // The binutils linker used on -windows-gnu targets cannot read the import // libraries generated by LLVM: in our attempts, the linker produced an .EXE // that loaded but crashed with an AV upon calling one of the imported // functions. Therefore, use binutils to create the import library instead, // by writing a .DEF file to the temp dir and calling binutils's dlltool. - let def_file_path = tmpdir.join(format!("{lib_name}{name_suffix}.def")); - - let def_file_content = format!( - "EXPORTS\n{}", - import_name_and_ordinal_vector - .into_iter() - .map(|(name, ordinal)| { - match ordinal { - Some(n) => format!("{name} @{n} NONAME"), - None => name, - } - }) - .collect::<Vec<String>>() - .join("\n") + create_mingw_dll_import_lib( + sess, + lib_name, + import_name_and_ordinal_vector, + output_path, ); - - match std::fs::write(&def_file_path, def_file_content) { - Ok(_) => {} - Err(e) => { - sess.dcx().emit_fatal(ErrorWritingDEFFile { error: e }); - } - }; - - // --no-leading-underscore: For the `import_name_type` feature to work, we need to be - // able to control the *exact* spelling of each of the symbols that are being imported: - // hence we don't want `dlltool` adding leading underscores automatically. - let dlltool = find_binutils_dlltool(sess); - let temp_prefix = { - let mut path = PathBuf::from(&output_path); - path.pop(); - path.push(lib_name); - path - }; - // dlltool target architecture args from: - // https://github.com/llvm/llvm-project-release-prs/blob/llvmorg-15.0.6/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp#L69 - let (dlltool_target_arch, dlltool_target_bitness) = match sess.target.arch.as_ref() { - "x86_64" => ("i386:x86-64", "--64"), - "x86" => ("i386", "--32"), - "aarch64" => ("arm64", "--64"), - "arm" => ("arm", "--32"), - _ => panic!("unsupported arch {}", sess.target.arch), - }; - let mut dlltool_cmd = std::process::Command::new(&dlltool); - dlltool_cmd - .arg("-d") - .arg(def_file_path) - .arg("-D") - .arg(lib_name) - .arg("-l") - .arg(&output_path) - .arg("-m") - .arg(dlltool_target_arch) - .arg("-f") - .arg(dlltool_target_bitness) - .arg("--no-leading-underscore") - .arg("--temp-prefix") - .arg(temp_prefix); - - match dlltool_cmd.output() { - Err(e) => { - sess.dcx().emit_fatal(ErrorCallingDllTool { - dlltool_path: dlltool.to_string_lossy(), - error: e, - }); - } - // dlltool returns '0' on failure, so check for error output instead. - Ok(output) if !output.stderr.is_empty() => { - sess.dcx().emit_fatal(DlltoolFailImportLibrary { - dlltool_path: dlltool.to_string_lossy(), - dlltool_args: dlltool_cmd - .get_args() - .map(|arg| arg.to_string_lossy()) - .collect::<Vec<_>>() - .join(" "), - stdout: String::from_utf8_lossy(&output.stdout), - stderr: String::from_utf8_lossy(&output.stderr), - }) - } - _ => {} - } } else { // we've checked for \0 characters in the library name already let dll_name_z = CString::new(lib_name).unwrap(); @@ -242,9 +145,9 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { trace!(" output_path {}", output_path.display()); trace!( " import names: {}", - dll_imports + import_name_and_ordinal_vector .iter() - .map(|import| import.name.to_string()) + .map(|(name, _ordinal)| name.clone()) .collect::<Vec<_>>() .join(", "), ); @@ -281,9 +184,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { error: llvm::last_error().unwrap_or("unknown LLVM error".to_string()), }); } - }; - - output_path + } } } @@ -457,39 +358,3 @@ impl<'a> LlvmArchiveBuilder<'a> { fn string_to_io_error(s: String) -> io::Error { io::Error::new(io::ErrorKind::Other, format!("bad archive: {s}")) } - -fn find_binutils_dlltool(sess: &Session) -> OsString { - assert!(sess.target.options.is_like_windows && !sess.target.options.is_like_msvc); - if let Some(dlltool_path) = &sess.opts.cg.dlltool { - return dlltool_path.clone().into_os_string(); - } - - let tool_name: OsString = if sess.host.options.is_like_windows { - // If we're compiling on Windows, always use "dlltool.exe". - "dlltool.exe" - } else { - // On other platforms, use the architecture-specific name. - match sess.target.arch.as_ref() { - "x86_64" => "x86_64-w64-mingw32-dlltool", - "x86" => "i686-w64-mingw32-dlltool", - "aarch64" => "aarch64-w64-mingw32-dlltool", - - // For non-standard architectures (e.g., aarch32) fallback to "dlltool". - _ => "dlltool", - } - } - .into(); - - // NOTE: it's not clear how useful it is to explicitly search PATH. - for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) { - let full_path = dir.join(&tool_name); - if full_path.is_file() { - return full_path.into_os_string(); - } - } - - // The user didn't specify the location of the dlltool binary, and we weren't able - // to find the appropriate one on the PATH. Just return the name of the tool - // and let the invocation fail with a hopefully useful error message. - tool_name -} |
