]> git.lizzy.rs Git - rust.git/commitdiff
rustc_trans: Handle empty dlls on MSVC
authorAlex Crichton <alex@alexcrichton.com>
Thu, 25 Jun 2015 07:33:52 +0000 (00:33 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Thu, 25 Jun 2015 16:33:15 +0000 (09:33 -0700)
If a dylib doesn't actually export any symbols then link.exe won't emit a
`foo.lib` file to link against (as one isn't necessary). Detect this case in the
backend by omitting the `foo.lib` argument to the linker if it doesn't actually
exist.

src/librustc_trans/back/link.rs
src/librustc_trans/back/linker.rs

index 6b8b59de3c253b9a1a2124a0711ba044b9b40ce7..cf5feabcc57e2df0fecf0b48e1f260489c0a5c03 100644 (file)
@@ -1214,11 +1214,13 @@ fn add_dynamic_crate(cmd: &mut Linker, sess: &Session, cratepath: &Path) {
 
         // Just need to tell the linker about where the library lives and
         // what its name is
-        if let Some(dir) = cratepath.parent() {
+        let parent = cratepath.parent();
+        if let Some(dir) = parent {
             cmd.include_path(&fix_windows_verbatim_for_gcc(dir));
         }
         let filestem = cratepath.file_stem().unwrap().to_str().unwrap();
-        cmd.link_dylib(&unlib(&sess.target, filestem));
+        cmd.link_rust_dylib(&unlib(&sess.target, filestem),
+                            parent.unwrap_or(Path::new("")));
     }
 }
 
index 1eacec46c87bbad7b130cccc8f4fb0ef34ffd0b2..7253334d6998989c95104d671e630869565a5cee 100644 (file)
@@ -11,6 +11,7 @@
 use std::ffi::OsString;
 use std::path::{Path, PathBuf};
 use std::process::Command;
+use std::fs;
 
 use rustc_back::archive;
 use session::Session;
@@ -25,6 +26,7 @@
 /// MSVC linker (e.g. `link.exe`) is being used.
 pub trait Linker {
     fn link_dylib(&mut self, lib: &str);
+    fn link_rust_dylib(&mut self, lib: &str, path: &Path);
     fn link_framework(&mut self, framework: &str);
     fn link_staticlib(&mut self, lib: &str);
     fn link_rlib(&mut self, lib: &Path);
@@ -67,6 +69,10 @@ impl<'a> Linker for GnuLinker<'a> {
     fn position_independent_executable(&mut self) { self.cmd.arg("-pie"); }
     fn args(&mut self, args: &[String]) { self.cmd.args(args); }
 
+    fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
+        self.cmd.arg("-l").arg(lib);
+    }
+
     fn link_framework(&mut self, framework: &str) {
         self.cmd.arg("-framework").arg(framework);
     }
@@ -189,6 +195,18 @@ impl<'a> Linker for MsvcLinker<'a> {
     fn link_dylib(&mut self, lib: &str) {
         self.cmd.arg(&format!("{}.lib", lib));
     }
+
+    fn link_rust_dylib(&mut self, lib: &str, path: &Path) {
+        // When producing a dll, the MSVC linker may not actually emit a
+        // `foo.lib` file if the dll doesn't actually export any symbols, so we
+        // check to see if the file is there and just omit linking to it if it's
+        // not present.
+        let name = format!("{}.lib", lib);
+        if fs::metadata(&path.join(&name)).is_ok() {
+            self.cmd.arg(name);
+        }
+    }
+
     fn link_staticlib(&mut self, lib: &str) {
         self.cmd.arg(&format!("{}.lib", lib));
     }