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, }; use rustc_codegen_ssa::common::is_mingw_gnu_toolchain; use rustc_session::Session; pub(crate) struct ArArchiveBuilderBuilder; impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box { 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)>, 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::>(); 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(), )); } } } }