Skip to content

Commit 181dbd7

Browse files
committed
rustc_trans: Add MSVC linker support
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.
1 parent eb50ffd commit 181dbd7

File tree

2 files changed

+86
-5
lines changed

2 files changed

+86
-5
lines changed

src/librustc_trans/back/link.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

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

807807
{
808-
let mut linker = GnuLinker { cmd: &mut cmd, sess: &sess };
809-
link_args(&mut linker, sess, dylib, tmpdir.path(),
808+
let mut linker = if sess.target.target.options.is_like_msvc {
809+
Box::new(MsvcLinker { cmd: &mut cmd, sess: &sess }) as Box<Linker>
810+
} else {
811+
Box::new(GnuLinker { cmd: &mut cmd, sess: &sess }) as Box<Linker>
812+
};
813+
link_args(&mut *linker, sess, dylib, tmpdir.path(),
810814
trans, obj_filename, out_filename);
811815
if !sess.target.target.options.no_compiler_rt {
812816
linker.link_staticlib("compiler-rt");
@@ -874,9 +878,8 @@ fn link_args(cmd: &mut Linker,
874878
let t = &sess.target.target;
875879

876880
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
877-
878-
cmd.output_filename(out_filename);
879881
cmd.add_object(obj_filename);
882+
cmd.output_filename(out_filename);
880883

881884
// Stack growth requires statically linking a __morestack function. Note
882885
// that this is listed *before* all other libraries. Due to the usage of the

src/librustc_trans/back/linker.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,3 +173,81 @@ impl<'a> Linker for GnuLinker<'a> {
173173
self.cmd.arg("-Wl,-Bdynamic");
174174
}
175175
}
176+
177+
pub struct MsvcLinker<'a> {
178+
pub cmd: &'a mut Command,
179+
pub sess: &'a Session,
180+
}
181+
182+
impl<'a> Linker for MsvcLinker<'a> {
183+
fn link_rlib(&mut self, lib: &Path) { self.cmd.arg(lib); }
184+
fn add_object(&mut self, path: &Path) { self.cmd.arg(path); }
185+
fn args(&mut self, args: &[String]) { self.cmd.args(args); }
186+
fn build_dylib(&mut self, _out_filename: &Path) { self.cmd.arg("/DLL"); }
187+
fn gc_sections(&mut self, _is_dylib: bool) { self.cmd.arg("/OPT:REF,ICF"); }
188+
189+
fn link_dylib(&mut self, lib: &str) {
190+
self.cmd.arg(&format!("{}.lib", lib));
191+
}
192+
fn link_staticlib(&mut self, lib: &str) {
193+
self.cmd.arg(&format!("{}.lib", lib));
194+
}
195+
196+
fn position_independent_executable(&mut self) {
197+
// noop
198+
}
199+
200+
fn no_default_libraries(&mut self) {
201+
// Currently we don't pass the /NODEFAULTLIB flag to the linker on MSVC
202+
// as there's been trouble in the past of linking the C++ standard
203+
// library required by LLVM. This likely needs to happen one day, but
204+
// in general Windows is also a more controlled environment than
205+
// Unix, so it's not necessarily as critical that this be implemented.
206+
//
207+
// Note that there are also some licensing worries about statically
208+
// linking some libraries which require a specific agreement, so it may
209+
// not ever be possible for us to pass this flag.
210+
}
211+
212+
fn include_path(&mut self, path: &Path) {
213+
let mut arg = OsString::from("/LIBPATH:");
214+
arg.push(path);
215+
self.cmd.arg(&arg);
216+
}
217+
218+
fn output_filename(&mut self, path: &Path) {
219+
let mut arg = OsString::from("/OUT:");
220+
arg.push(path);
221+
self.cmd.arg(&arg);
222+
}
223+
224+
fn framework_path(&mut self, _path: &Path) {
225+
panic!("frameworks are not supported on windows")
226+
}
227+
fn link_framework(&mut self, _framework: &str) {
228+
panic!("frameworks are not supported on windows")
229+
}
230+
231+
fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) {
232+
// not supported?
233+
self.link_staticlib(lib);
234+
}
235+
fn optimize(&mut self) {
236+
// Needs more investigation of `/OPT` arguments
237+
}
238+
fn whole_archives(&mut self) {
239+
// hints not supported?
240+
}
241+
fn no_whole_archives(&mut self) {
242+
// hints not supported?
243+
}
244+
245+
// On windows static libraries are of the form `foo.lib` and dynamic
246+
// libraries are not linked against directly, but rather through their
247+
// import libraries also called `foo.lib`. As a result there's no
248+
// possibility for a native library to appear both dynamically and
249+
// statically in the same folder so we don't have to worry about hints like
250+
// we do on Unix platforms.
251+
fn hint_static(&mut self) {}
252+
fn hint_dynamic(&mut self) {}
253+
}

0 commit comments

Comments
 (0)