| 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<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(), |
| )); |
| } |
| } |
| } |
| } |