1
Fork 0

Always use ar_archive_writer for import libs

This commit is contained in:
Chris Denton 2024-08-16 19:32:22 +00:00
parent 27b93da8de
commit 0156eb57a1
No known key found for this signature in database
GPG key ID: 713472F2F45627DE
10 changed files with 100 additions and 190 deletions

View file

@ -5,7 +5,7 @@ edition = "2021"
[dependencies]
# tidy-alphabetical-start
ar_archive_writer = "0.3.3"
ar_archive_writer = "0.4.0"
arrayvec = { version = "0.7", default-features = false }
bitflags = "2.4.1"
cc = "1.0.90"

View file

@ -32,6 +32,9 @@ codegen_ssa_dlltool_fail_import_library =
codegen_ssa_error_calling_dlltool =
Error calling dlltool '{$dlltool_path}': {$error}
codegen_ssa_error_creating_import_library =
Error creating import library for {$lib_name}: {$error}
codegen_ssa_error_creating_remark_dir = failed to create remark directory: {$error}
codegen_ssa_error_writing_def_file =

View file

@ -5,7 +5,9 @@ use std::fs::{self, File};
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use ar_archive_writer::{write_archive_to_stream, ArchiveKind, NewArchiveMember};
use ar_archive_writer::{
write_archive_to_stream, ArchiveKind, COFFShortExport, MachineTypes, NewArchiveMember,
};
pub use ar_archive_writer::{ObjectReader, DEFAULT_OBJECT_READER};
use object::read::archive::ArchiveFile;
use object::read::macho::FatArch;
@ -14,11 +16,15 @@ use rustc_data_structures::memmap::Mmap;
use rustc_session::Session;
use rustc_span::symbol::Symbol;
use tempfile::Builder as TempFileBuilder;
use tracing::trace;
use super::metadata::search_for_section;
use crate::common;
// Re-exporting for rustc_codegen_llvm::back::archive
pub use crate::errors::{ArchiveBuildFailure, ExtractBundledLibsError, UnknownArchiveKind};
use crate::errors::{DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorWritingDEFFile};
use crate::errors::{
DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile,
};
pub trait ArchiveBuilderBuilder {
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>;
@ -34,7 +40,81 @@ pub trait ArchiveBuilderBuilder {
lib_name: &str,
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.
create_mingw_dll_import_lib(
sess,
lib_name,
import_name_and_ordinal_vector,
output_path,
);
} else {
trace!("creating import library");
trace!(" dll_name {:#?}", lib_name);
trace!(" output_path {}", output_path.display());
trace!(
" import names: {}",
import_name_and_ordinal_vector
.iter()
.map(|(name, _ordinal)| name.clone())
.collect::<Vec<_>>()
.join(", "),
);
// All import names are Rust identifiers and therefore cannot contain \0 characters.
// FIXME: when support for #[link_name] is implemented, ensure that the import names
// still don't contain any \0 characters. Also need to check that the names don't
// contain substrings like " @" or "NONAME" that are keywords or otherwise reserved
// in definition files.
let mut file = match fs::File::create_new(&output_path) {
Ok(file) => file,
Err(error) => sess
.dcx()
.emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }),
};
let exports = import_name_and_ordinal_vector
.iter()
.map(|(name, ordinal)| COFFShortExport {
name: name.to_string(),
ext_name: None,
symbol_name: None,
alias_target: None,
ordinal: ordinal.unwrap_or(0),
noname: ordinal.is_some(),
data: false,
private: false,
constant: false,
})
.collect::<Vec<_>>();
let machine = match &*sess.target.arch {
"x86_64" => MachineTypes::AMD64,
"x86" => MachineTypes::I386,
"aarch64" => MachineTypes::ARM64,
"arm64ec" => MachineTypes::ARM64EC,
"arm" => MachineTypes::ARMNT,
cpu => panic!("unsupported cpu type {cpu}"),
};
if let Err(error) = ar_archive_writer::write_import_library(
&mut file,
lib_name,
&exports,
machine,
!sess.target.is_like_msvc,
/*comdat=*/ false,
) {
sess.dcx()
.emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() });
}
}
}
fn extract_bundled_libs<'a>(
&'a self,

View file

@ -1060,3 +1060,10 @@ pub struct CompilerBuiltinsCannotCall {
pub caller: String,
pub callee: String,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_error_creating_import_library)]
pub(crate) struct ErrorCreatingImportLibrary<'a> {
pub lib_name: &'a str,
pub error: String,
}