about summary refs log tree commit diff
path: root/src/librustc_codegen_ssa/back
diff options
context:
space:
mode:
authorMateusz Mikuła <mati865@gmail.com>2020-05-07 11:52:21 +0200
committerMateusz Mikuła <mati865@gmail.com>2020-07-29 14:19:57 +0200
commitdb9a84a1af8bd5cea3738833c0e8cd4e1bee3f7d (patch)
tree0ecc3a3b448b12cbc53297825fc8c7295671b337 /src/librustc_codegen_ssa/back
parent6ee1b62c811a6eb68d6db6dfb91f66a49956749b (diff)
downloadrust-db9a84a1af8bd5cea3738833c0e8cd4e1bee3f7d.tar.gz
rust-db9a84a1af8bd5cea3738833c0e8cd4e1bee3f7d.zip
MinGW: emit dllexport/dllimport by rustc
This fixes various cases where LD could not guess dllexport correctly and greatly improves compatibility with LLD which is not going to support linker scripts anytime soon
Diffstat (limited to 'src/librustc_codegen_ssa/back')
-rw-r--r--src/librustc_codegen_ssa/back/linker.rs23
-rw-r--r--src/librustc_codegen_ssa/back/write.rs4
2 files changed, 23 insertions, 4 deletions
diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs
index e64aafa599f..aba4991c295 100644
--- a/src/librustc_codegen_ssa/back/linker.rs
+++ b/src/librustc_codegen_ssa/back/linker.rs
@@ -523,8 +523,9 @@ impl<'a> Linker for GccLinker<'a> {
             return;
         }
 
+        let is_windows = self.sess.target.target.options.is_like_windows;
         let mut arg = OsString::new();
-        let path = tmpdir.join("list");
+        let path = tmpdir.join(if is_windows { "list.def" } else { "list" });
 
         debug!("EXPORTED SYMBOLS:");
 
@@ -540,6 +541,21 @@ impl<'a> Linker for GccLinker<'a> {
             if let Err(e) = res {
                 self.sess.fatal(&format!("failed to write lib.def file: {}", e));
             }
+        } else if is_windows {
+            let res: io::Result<()> = try {
+                let mut f = BufWriter::new(File::create(&path)?);
+
+                // .def file similar to MSVC one but without LIBRARY section
+                // because LD doesn't like when it's empty
+                writeln!(f, "EXPORTS")?;
+                for symbol in self.info.exports[&crate_type].iter() {
+                    debug!("  _{}", symbol);
+                    writeln!(f, "  {}", symbol)?;
+                }
+            };
+            if let Err(e) = res {
+                self.sess.fatal(&format!("failed to write list.def file: {}", e));
+            }
         } else {
             // Write an LD version script
             let res: io::Result<()> = try {
@@ -573,7 +589,10 @@ impl<'a> Linker for GccLinker<'a> {
             if !self.is_ld {
                 arg.push("-Wl,")
             }
-            arg.push("--version-script=");
+            // Both LD and LLD accept export list in *.def file form, there are no flags required
+            if !is_windows {
+                arg.push("--version-script=")
+            }
         }
 
         arg.push(&path);
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 23e0b9344ec..b0fae566a5a 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -1846,11 +1846,11 @@ fn msvc_imps_needed(tcx: TyCtxt<'_>) -> bool {
     // something is wrong with commandline arg validation.
     assert!(
         !(tcx.sess.opts.cg.linker_plugin_lto.enabled()
-            && tcx.sess.target.target.options.is_like_msvc
+            && tcx.sess.target.target.options.is_like_windows
             && tcx.sess.opts.cg.prefer_dynamic)
     );
 
-    tcx.sess.target.target.options.is_like_msvc &&
+    tcx.sess.target.target.options.is_like_windows &&
         tcx.sess.crate_types().iter().any(|ct| *ct == CrateType::Rlib) &&
     // ThinLTO can't handle this workaround in all cases, so we don't
     // emit the `__imp_` symbols. Instead we make them unnecessary by disallowing