use rustc::session::Session;
use rustc::session::config::{self, CrateType, OptLevel, DebugInfo,
LinkerPluginLto, Lto};
+use rustc::middle::exported_symbols::ExportedSymbol;
use rustc::ty::TyCtxt;
use rustc_target::spec::{LinkerFlavor, LldFlavor};
use rustc_serialize::{json, Encoder};
+use syntax::symbol::Symbol;
/// For all the linkers we support, and information they might
/// need out of the shared crate context before we get rid of it.
/// used to dispatch on whether a GNU-like linker (generally `ld.exe`) or an
/// 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_dylib(&mut self, lib: Symbol);
+ fn link_rust_dylib(&mut self, lib: Symbol, path: &Path);
+ fn link_framework(&mut self, framework: Symbol);
+ fn link_staticlib(&mut self, lib: Symbol);
fn link_rlib(&mut self, lib: &Path);
fn link_whole_rlib(&mut self, lib: &Path);
- fn link_whole_staticlib(&mut self, lib: &str, search_path: &[PathBuf]);
+ fn link_whole_staticlib(&mut self, lib: Symbol, search_path: &[PathBuf]);
fn include_path(&mut self, path: &Path);
fn framework_path(&mut self, path: &Path);
fn output_filename(&mut self, path: &Path);
}
impl<'a> Linker for GccLinker<'a> {
- fn link_dylib(&mut self, lib: &str) { self.hint_dynamic(); self.cmd.arg(format!("-l{}", lib)); }
- fn link_staticlib(&mut self, lib: &str) {
- self.hint_static(); self.cmd.arg(format!("-l{}", lib));
+ fn link_dylib(&mut self, lib: Symbol) {
+ self.hint_dynamic();
+ self.cmd.arg(format!("-l{}", lib));
+ }
+ fn link_staticlib(&mut self, lib: Symbol) {
+ self.hint_static();
+ self.cmd.arg(format!("-l{}", lib));
}
fn link_rlib(&mut self, lib: &Path) { self.hint_static(); self.cmd.arg(lib); }
fn include_path(&mut self, path: &Path) { self.cmd.arg("-L").arg(path); }
fn build_static_executable(&mut self) { self.cmd.arg("-static"); }
fn args(&mut self, args: &[String]) { self.cmd.args(args); }
- fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
+ fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
self.hint_dynamic();
self.cmd.arg(format!("-l{}", lib));
}
- fn link_framework(&mut self, framework: &str) {
+ fn link_framework(&mut self, framework: Symbol) {
self.hint_dynamic();
- self.cmd.arg("-framework").arg(framework);
+ self.cmd.arg("-framework").sym_arg(framework);
}
// Here we explicitly ask that the entire archive is included into the
// don't otherwise explicitly reference them. This can occur for
// libraries which are just providing bindings, libraries with generic
// functions, etc.
- fn link_whole_staticlib(&mut self, lib: &str, search_path: &[PathBuf]) {
+ fn link_whole_staticlib(&mut self, lib: Symbol, search_path: &[PathBuf]) {
self.hint_static();
let target = &self.sess.target.target;
if !target.options.is_like_osx {
}
}
- fn link_dylib(&mut self, lib: &str) {
+ fn link_dylib(&mut self, lib: Symbol) {
self.cmd.arg(&format!("{}.lib", lib));
}
- fn link_rust_dylib(&mut self, lib: &str, path: &Path) {
+ fn link_rust_dylib(&mut self, lib: Symbol, 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
}
}
- fn link_staticlib(&mut self, lib: &str) {
+ fn link_staticlib(&mut self, lib: Symbol) {
self.cmd.arg(&format!("{}.lib", lib));
}
fn framework_path(&mut self, _path: &Path) {
bug!("frameworks are not supported on windows")
}
- fn link_framework(&mut self, _framework: &str) {
+ fn link_framework(&mut self, _framework: Symbol) {
bug!("frameworks are not supported on windows")
}
- fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) {
+ fn link_whole_staticlib(&mut self, lib: Symbol, _search_path: &[PathBuf]) {
// not supported?
self.link_staticlib(lib);
}
self.cmd.arg("-L").arg(path);
}
- fn link_staticlib(&mut self, lib: &str) {
- self.cmd.arg("-l").arg(lib);
+ fn link_staticlib(&mut self, lib: Symbol) {
+ self.cmd.arg("-l").sym_arg(lib);
}
fn output_filename(&mut self, path: &Path) {
self.cmd.arg(path);
}
- fn link_dylib(&mut self, lib: &str) {
+ fn link_dylib(&mut self, lib: Symbol) {
// Emscripten always links statically
self.link_staticlib(lib);
}
- fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) {
+ fn link_whole_staticlib(&mut self, lib: Symbol, _search_path: &[PathBuf]) {
// not supported?
self.link_staticlib(lib);
}
self.link_rlib(lib);
}
- fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
+ fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
self.link_dylib(lib);
}
bug!("frameworks are not supported on Emscripten")
}
- fn link_framework(&mut self, _framework: &str) {
+ fn link_framework(&mut self, _framework: Symbol) {
bug!("frameworks are not supported on Emscripten")
}
}
impl<'a> Linker for WasmLd<'a> {
- fn link_dylib(&mut self, lib: &str) {
- self.cmd.arg("-l").arg(lib);
+ fn link_dylib(&mut self, lib: Symbol) {
+ self.cmd.arg("-l").sym_arg(lib);
}
- fn link_staticlib(&mut self, lib: &str) {
- self.cmd.arg("-l").arg(lib);
+ fn link_staticlib(&mut self, lib: Symbol) {
+ self.cmd.arg("-l").sym_arg(lib);
}
fn link_rlib(&mut self, lib: &Path) {
self.cmd.args(args);
}
- fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
- self.cmd.arg("-l").arg(lib);
+ fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
+ self.cmd.arg("-l").sym_arg(lib);
}
- fn link_framework(&mut self, _framework: &str) {
+ fn link_framework(&mut self, _framework: Symbol) {
panic!("frameworks not supported")
}
- fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) {
- self.cmd.arg("-l").arg(lib);
+ fn link_whole_staticlib(&mut self, lib: Symbol, _search_path: &[PathBuf]) {
+ self.cmd.arg("-l").sym_arg(lib);
}
fn link_whole_rlib(&mut self, lib: &Path) {
}
}
- let formats = tcx.sess.dependency_formats.borrow();
- let deps = formats[&crate_type].iter();
+ let formats = tcx.dependency_formats(LOCAL_CRATE);
+ let deps = formats.iter().filter_map(|(t, list)| {
+ if *t == crate_type {
+ Some(list)
+ } else {
+ None
+ }
+ }).next().unwrap();
- for (index, dep_format) in deps.enumerate() {
+ for (index, dep_format) in deps.iter().enumerate() {
let cnum = CrateNum::new(index + 1);
// For each dependency that we are linking to statically ...
if *dep_format == Linkage::Static {
// ... we add its symbol list to our export list.
for &(symbol, level) in tcx.exported_symbols(cnum).iter() {
- if level.is_below_threshold(export_threshold) {
- symbols.push(symbol.symbol_name(tcx).to_string());
+ if !level.is_below_threshold(export_threshold) {
+ continue;
}
+
+ // Do not export generic symbols from upstream crates in linked
+ // artifact (notably the `dylib` crate type). The main reason
+ // for this is that `symbol_name` is actually wrong for generic
+ // symbols because it guesses the name we'd give them locally
+ // rather than the name it has upstream (depending on
+ // `share_generics` settings and such).
+ //
+ // To fix that issue we just say that linked artifacts, aka
+ // `dylib`s, never export generic symbols and they aren't
+ // available to downstream crates. (the not available part is
+ // handled elsewhere).
+ if let ExportedSymbol::Generic(..) = symbol {
+ continue;
+ }
+
+ symbols.push(symbol.symbol_name(tcx).to_string());
}
}
}
::std::mem::replace(&mut self.cmd, Command::new(""))
}
- fn link_dylib(&mut self, _lib: &str) {
+ fn link_dylib(&mut self, _lib: Symbol) {
panic!("external dylibs not supported")
}
- fn link_rust_dylib(&mut self, _lib: &str, _path: &Path) {
+ fn link_rust_dylib(&mut self, _lib: Symbol, _path: &Path) {
panic!("external dylibs not supported")
}
- fn link_staticlib(&mut self, _lib: &str) {
+ fn link_staticlib(&mut self, _lib: Symbol) {
panic!("staticlibs not supported")
}
- fn link_whole_staticlib(&mut self, _lib: &str, _search_path: &[PathBuf]) {
+ fn link_whole_staticlib(&mut self, _lib: Symbol, _search_path: &[PathBuf]) {
panic!("staticlibs not supported")
}
panic!("frameworks not supported")
}
- fn link_framework(&mut self, _framework: &str) {
+ fn link_framework(&mut self, _framework: Symbol) {
panic!("frameworks not supported")
}