about summary refs log tree commit diff
path: root/compiler/rustc_codegen_cranelift/src/archive.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_codegen_cranelift/src/archive.rs')
-rw-r--r--compiler/rustc_codegen_cranelift/src/archive.rs79
1 files changed, 74 insertions, 5 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs
index 084654af09d..5eedab4f2cb 100644
--- a/compiler/rustc_codegen_cranelift/src/archive.rs
+++ b/compiler/rustc_codegen_cranelift/src/archive.rs
@@ -1,8 +1,13 @@
+use std::borrow::Borrow;
+use std::fs;
 use std::path::Path;
 
+use ar_archive_writer::{COFFShortExport, MachineTypes};
 use rustc_codegen_ssa::back::archive::{
-    ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
+    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;
@@ -15,10 +20,74 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
     fn create_dll_import_lib(
         &self,
         sess: &Session,
-        _lib_name: &str,
-        _import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
-        _output_path: &Path,
+        lib_name: &str,
+        import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
+        output_path: &Path,
     ) {
-        sess.dcx().fatal("raw-dylib is not yet supported by rustc_codegen_cranelift");
+        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(),
+                ));
+            }
+        }
     }
 }