Skip to content

Commit

Permalink
rustc_trans: Add MSVC linker support
Browse files Browse the repository at this point in the history
This commit adds an implementation of the `Linker` trait which is used to drive
MSVC's `link.exe` support. Nothing too surprising here as it's mostly just
filling out the necessary tidbits here and there.
  • Loading branch information
alexcrichton committed May 19, 2015
1 parent eb50ffd commit 181dbd7
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 5 deletions.
13 changes: 8 additions & 5 deletions src/librustc_trans/back/link.rs
Expand Up @@ -9,7 +9,7 @@
// except according to those terms.

use super::archive::{Archive, ArchiveBuilder, ArchiveConfig, METADATA_FILENAME};
use super::linker::{Linker, GnuLinker};
use super::linker::{Linker, GnuLinker, MsvcLinker};
use super::rpath::RPathConfig;
use super::rpath;
use super::svh::Svh;
Expand Down Expand Up @@ -805,8 +805,12 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
}

{
let mut linker = GnuLinker { cmd: &mut cmd, sess: &sess };
link_args(&mut linker, sess, dylib, tmpdir.path(),
let mut linker = if sess.target.target.options.is_like_msvc {
Box::new(MsvcLinker { cmd: &mut cmd, sess: &sess }) as Box<Linker>
} else {
Box::new(GnuLinker { cmd: &mut cmd, sess: &sess }) as Box<Linker>
};
link_args(&mut *linker, sess, dylib, tmpdir.path(),
trans, obj_filename, out_filename);
if !sess.target.target.options.no_compiler_rt {
linker.link_staticlib("compiler-rt");
Expand Down Expand Up @@ -874,9 +878,8 @@ fn link_args(cmd: &mut Linker,
let t = &sess.target.target;

cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));

cmd.output_filename(out_filename);
cmd.add_object(obj_filename);
cmd.output_filename(out_filename);

// Stack growth requires statically linking a __morestack function. Note
// that this is listed *before* all other libraries. Due to the usage of the
Expand Down
78 changes: 78 additions & 0 deletions src/librustc_trans/back/linker.rs
Expand Up @@ -173,3 +173,81 @@ impl<'a> Linker for GnuLinker<'a> {
self.cmd.arg("-Wl,-Bdynamic");
}
}

pub struct MsvcLinker<'a> {
pub cmd: &'a mut Command,
pub sess: &'a Session,
}

impl<'a> Linker for MsvcLinker<'a> {
fn link_rlib(&mut self, lib: &Path) { self.cmd.arg(lib); }
fn add_object(&mut self, path: &Path) { self.cmd.arg(path); }
fn args(&mut self, args: &[String]) { self.cmd.args(args); }
fn build_dylib(&mut self, _out_filename: &Path) { self.cmd.arg("/DLL"); }
fn gc_sections(&mut self, _is_dylib: bool) { self.cmd.arg("/OPT:REF,ICF"); }

fn link_dylib(&mut self, lib: &str) {
self.cmd.arg(&format!("{}.lib", lib));
}
fn link_staticlib(&mut self, lib: &str) {
self.cmd.arg(&format!("{}.lib", lib));
}

fn position_independent_executable(&mut self) {
// noop
}

fn no_default_libraries(&mut self) {
// Currently we don't pass the /NODEFAULTLIB flag to the linker on MSVC
// as there's been trouble in the past of linking the C++ standard
// library required by LLVM. This likely needs to happen one day, but
// in general Windows is also a more controlled environment than
// Unix, so it's not necessarily as critical that this be implemented.
//
// Note that there are also some licensing worries about statically
// linking some libraries which require a specific agreement, so it may
// not ever be possible for us to pass this flag.
}

fn include_path(&mut self, path: &Path) {
let mut arg = OsString::from("/LIBPATH:");
arg.push(path);
self.cmd.arg(&arg);
}

fn output_filename(&mut self, path: &Path) {
let mut arg = OsString::from("/OUT:");
arg.push(path);
self.cmd.arg(&arg);
}

fn framework_path(&mut self, _path: &Path) {
panic!("frameworks are not supported on windows")
}
fn link_framework(&mut self, _framework: &str) {
panic!("frameworks are not supported on windows")
}

fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) {
// not supported?
self.link_staticlib(lib);
}
fn optimize(&mut self) {
// Needs more investigation of `/OPT` arguments
}
fn whole_archives(&mut self) {
// hints not supported?
}
fn no_whole_archives(&mut self) {
// hints not supported?
}

// On windows static libraries are of the form `foo.lib` and dynamic
// libraries are not linked against directly, but rather through their
// import libraries also called `foo.lib`. As a result there's no
// possibility for a native library to appear both dynamically and
// statically in the same folder so we don't have to worry about hints like
// we do on Unix platforms.
fn hint_static(&mut self) {}
fn hint_dynamic(&mut self) {}
}

0 comments on commit 181dbd7

Please sign in to comment.