Skip to content

Commit 9e3cb64

Browse files
committed
rustc_trans: Handle empty dlls on MSVC
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.
1 parent 91d799e commit 9e3cb64

File tree

2 files changed

+22
-2
lines changed

2 files changed

+22
-2
lines changed

src/librustc_trans/back/link.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1214,11 +1214,13 @@ fn add_upstream_rust_crates(cmd: &mut Linker, sess: &Session,
12141214

12151215
// Just need to tell the linker about where the library lives and
12161216
// what its name is
1217-
if let Some(dir) = cratepath.parent() {
1217+
let parent = cratepath.parent();
1218+
if let Some(dir) = parent {
12181219
cmd.include_path(&fix_windows_verbatim_for_gcc(dir));
12191220
}
12201221
let filestem = cratepath.file_stem().unwrap().to_str().unwrap();
1221-
cmd.link_dylib(&unlib(&sess.target, filestem));
1222+
cmd.link_rust_dylib(&unlib(&sess.target, filestem),
1223+
parent.unwrap_or(Path::new("")));
12221224
}
12231225
}
12241226

src/librustc_trans/back/linker.rs

+18
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use std::ffi::OsString;
1212
use std::path::{Path, PathBuf};
1313
use std::process::Command;
14+
use std::fs;
1415

1516
use rustc_back::archive;
1617
use session::Session;
@@ -25,6 +26,7 @@ use session::config;
2526
/// MSVC linker (e.g. `link.exe`) is being used.
2627
pub trait Linker {
2728
fn link_dylib(&mut self, lib: &str);
29+
fn link_rust_dylib(&mut self, lib: &str, path: &Path);
2830
fn link_framework(&mut self, framework: &str);
2931
fn link_staticlib(&mut self, lib: &str);
3032
fn link_rlib(&mut self, lib: &Path);
@@ -67,6 +69,10 @@ impl<'a> Linker for GnuLinker<'a> {
6769
fn position_independent_executable(&mut self) { self.cmd.arg("-pie"); }
6870
fn args(&mut self, args: &[String]) { self.cmd.args(args); }
6971

72+
fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
73+
self.cmd.arg("-l").arg(lib);
74+
}
75+
7076
fn link_framework(&mut self, framework: &str) {
7177
self.cmd.arg("-framework").arg(framework);
7278
}
@@ -189,6 +195,18 @@ impl<'a> Linker for MsvcLinker<'a> {
189195
fn link_dylib(&mut self, lib: &str) {
190196
self.cmd.arg(&format!("{}.lib", lib));
191197
}
198+
199+
fn link_rust_dylib(&mut self, lib: &str, path: &Path) {
200+
// When producing a dll, the MSVC linker may not actually emit a
201+
// `foo.lib` file if the dll doesn't actually export any symbols, so we
202+
// check to see if the file is there and just omit linking to it if it's
203+
// not present.
204+
let name = format!("{}.lib", lib);
205+
if fs::metadata(&path.join(&name)).is_ok() {
206+
self.cmd.arg(name);
207+
}
208+
}
209+
192210
fn link_staticlib(&mut self, lib: &str) {
193211
self.cmd.arg(&format!("{}.lib", lib));
194212
}

0 commit comments

Comments
 (0)