mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Rollup merge of #129164 - ChrisDenton:comdat, r=jieyouxu
Use `ar_archive_writer` for writing COFF import libs on all backends This is mostly the same as the llvm backend but with the cranelift version copy/pasted in place of the LLVM library. try-job: x86_64-msvc try-job: i686-msvc try-job: i686-mingw try-job: aarch64-gnu try-job: aarch64-apple try-job: test-various try-job: armhf-gnu
This commit is contained in:
commit
c4cf437fa1
@ -205,9 +205,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ar_archive_writer"
|
||||
version = "0.3.3"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f2bcb7cf51decfbbfc7ef476e28b0775b13e5eb1190f8b7df145cd53d4f4374"
|
||||
checksum = "de11a9d32db3327f981143bdf699ade4d637c6887b13b97e6e91a9154666963c"
|
||||
dependencies = [
|
||||
"object 0.36.2",
|
||||
]
|
||||
|
@ -1,13 +1,6 @@
|
||||
use std::borrow::Borrow;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use ar_archive_writer::{COFFShortExport, MachineTypes};
|
||||
use rustc_codegen_ssa::back::archive::{
|
||||
create_mingw_dll_import_lib, ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder,
|
||||
DEFAULT_OBJECT_READER,
|
||||
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
|
||||
};
|
||||
use rustc_codegen_ssa::common::is_mingw_gnu_toolchain;
|
||||
use rustc_session::Session;
|
||||
|
||||
pub(crate) struct ArArchiveBuilderBuilder;
|
||||
@ -16,78 +9,4 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
|
||||
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a> {
|
||||
Box::new(ArArchiveBuilder::new(sess, &DEFAULT_OBJECT_READER))
|
||||
}
|
||||
|
||||
fn create_dll_import_lib(
|
||||
&self,
|
||||
sess: &Session,
|
||||
lib_name: &str,
|
||||
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
||||
output_path: &Path,
|
||||
) {
|
||||
if 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 {
|
||||
let mut file =
|
||||
match fs::OpenOptions::new().write(true).create_new(true).open(&output_path) {
|
||||
Ok(file) => file,
|
||||
Err(error) => {
|
||||
sess.dcx().fatal(format!(
|
||||
"failed to create import library file `{path}`: {error}",
|
||||
path = output_path.display(),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let machine = match sess.target.arch.borrow() {
|
||||
"x86" => MachineTypes::I386,
|
||||
"x86_64" => MachineTypes::AMD64,
|
||||
"arm" => MachineTypes::ARMNT,
|
||||
"aarch64" => MachineTypes::ARM64,
|
||||
_ => {
|
||||
sess.dcx().fatal(format!(
|
||||
"unsupported target architecture `{arch}`",
|
||||
arch = sess.target.arch,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
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<_>>();
|
||||
|
||||
if let Err(error) = ar_archive_writer::write_import_library(
|
||||
&mut file,
|
||||
lib_name,
|
||||
&exports,
|
||||
machine,
|
||||
!sess.target.is_like_msvc,
|
||||
) {
|
||||
sess.dcx().fatal(format!(
|
||||
"failed to create import library `{path}`: `{error}`",
|
||||
path = output_path.display(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,6 @@
|
||||
#![warn(unused_lifetimes)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
extern crate ar_archive_writer;
|
||||
extern crate jobserver;
|
||||
#[macro_use]
|
||||
extern crate rustc_middle;
|
||||
|
@ -5,9 +5,6 @@ codegen_llvm_dynamic_linking_with_lto =
|
||||
.note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
|
||||
|
||||
|
||||
codegen_llvm_error_creating_import_library =
|
||||
Error creating import library for {$lib_name}: {$error}
|
||||
|
||||
codegen_llvm_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture
|
||||
|
||||
codegen_llvm_from_llvm_diag = {$message}
|
||||
|
@ -5,17 +5,13 @@ use std::path::{Path, PathBuf};
|
||||
use std::{io, mem, ptr, str};
|
||||
|
||||
use rustc_codegen_ssa::back::archive::{
|
||||
create_mingw_dll_import_lib, try_extract_macho_fat_archive, ArArchiveBuilder,
|
||||
ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind,
|
||||
DEFAULT_OBJECT_READER,
|
||||
try_extract_macho_fat_archive, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder,
|
||||
ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind, DEFAULT_OBJECT_READER,
|
||||
};
|
||||
use rustc_codegen_ssa::common;
|
||||
use rustc_session::Session;
|
||||
use tracing::trace;
|
||||
|
||||
use crate::errors::ErrorCreatingImportLibrary;
|
||||
use crate::llvm::archive_ro::{ArchiveRO, Child};
|
||||
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
|
||||
use crate::llvm::{self, ArchiveKind};
|
||||
|
||||
/// Helper for adding many files to an archive.
|
||||
#[must_use = "must call build() to finish building the archive"]
|
||||
@ -44,18 +40,6 @@ fn is_relevant_child(c: &Child<'_>) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Map machine type strings to values of LLVM's MachineTypes enum.
|
||||
fn llvm_machine_type(cpu: &str) -> LLVMMachineType {
|
||||
match cpu {
|
||||
"x86_64" => LLVMMachineType::AMD64,
|
||||
"x86" => LLVMMachineType::I386,
|
||||
"aarch64" => LLVMMachineType::ARM64,
|
||||
"arm64ec" => LLVMMachineType::ARM64EC,
|
||||
"arm" => LLVMMachineType::ARM,
|
||||
_ => panic!("unsupported cpu type {cpu}"),
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ArchiveBuilder for LlvmArchiveBuilder<'a> {
|
||||
fn add_archive(
|
||||
&mut self,
|
||||
@ -116,78 +100,6 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
||||
Box::new(ArArchiveBuilder::new(sess, &LLVM_OBJECT_READER))
|
||||
}
|
||||
}
|
||||
|
||||
fn create_dll_import_lib(
|
||||
&self,
|
||||
sess: &Session,
|
||||
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 {
|
||||
// we've checked for \0 characters in the library name already
|
||||
let dll_name_z = CString::new(lib_name).unwrap();
|
||||
|
||||
let output_path_z = rustc_fs_util::path_to_c_string(&output_path);
|
||||
|
||||
trace!("invoking LLVMRustWriteImportLibrary");
|
||||
trace!(" dll_name {:#?}", dll_name_z);
|
||||
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 cstring_import_name_and_ordinal_vector: Vec<(CString, Option<u16>)> =
|
||||
import_name_and_ordinal_vector
|
||||
.into_iter()
|
||||
.map(|(name, ordinal)| (CString::new(name).unwrap(), ordinal))
|
||||
.collect();
|
||||
|
||||
let ffi_exports: Vec<LLVMRustCOFFShortExport> = cstring_import_name_and_ordinal_vector
|
||||
.iter()
|
||||
.map(|(name_z, ordinal)| LLVMRustCOFFShortExport::new(name_z.as_ptr(), *ordinal))
|
||||
.collect();
|
||||
let result = unsafe {
|
||||
crate::llvm::LLVMRustWriteImportLibrary(
|
||||
dll_name_z.as_ptr(),
|
||||
output_path_z.as_ptr(),
|
||||
ffi_exports.as_ptr(),
|
||||
ffi_exports.len(),
|
||||
llvm_machine_type(&sess.target.arch) as u16,
|
||||
!sess.target.is_like_msvc,
|
||||
)
|
||||
};
|
||||
|
||||
if result == crate::llvm::LLVMRustResult::Failure {
|
||||
sess.dcx().emit_fatal(ErrorCreatingImportLibrary {
|
||||
lib_name,
|
||||
error: llvm::last_error().unwrap_or("unknown LLVM error".to_string()),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The object crate doesn't know how to get symbols for LLVM bitcode and COFF bigobj files.
|
||||
|
@ -39,13 +39,6 @@ pub(crate) enum PossibleFeature<'a> {
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_error_creating_import_library)]
|
||||
pub(crate) struct ErrorCreatingImportLibrary<'a> {
|
||||
pub lib_name: &'a str,
|
||||
pub error: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_symbol_already_defined)]
|
||||
pub(crate) struct SymbolAlreadyDefined<'a> {
|
||||
|
@ -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"
|
||||
|
@ -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 =
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user