diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 53cc0319829..0a7c3b6fc8f 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -9,7 +9,7 @@ // except according to those terms. use super::archive::{ArchiveBuilder, ArchiveConfig}; -use super::linker::{Linker, GnuLinker, MsvcLinker}; +use super::linker::Linker; use super::rpath::RPathConfig; use super::rpath; use super::msvc; @@ -637,13 +637,9 @@ fn link_natively(sess: &Session, } { - let mut linker = if sess.target.target.options.is_like_msvc { - Box::new(MsvcLinker { cmd: &mut cmd, sess: &sess }) as Box - } else { - Box::new(GnuLinker { cmd: &mut cmd, sess: &sess }) as Box - }; + let mut linker = trans.linker_info.to_linker(&mut cmd, &sess); link_args(&mut *linker, sess, crate_type, tmpdir, - objects, out_filename, trans, outputs); + objects, out_filename, outputs); if !sess.target.target.options.no_compiler_rt { linker.link_staticlib("compiler-rt"); } @@ -712,7 +708,6 @@ fn link_args(cmd: &mut Linker, tmpdir: &Path, objects: &[PathBuf], out_filename: &Path, - trans: &CrateTranslation, outputs: &OutputFilenames) { // The default library location, we need this to find the runtime. @@ -731,7 +726,7 @@ fn link_args(cmd: &mut Linker, // If we're building a dynamic library then some platforms need to make sure // that all symbols are exported correctly from the dynamic library. if crate_type != config::CrateTypeExecutable { - cmd.export_symbols(sess, trans, tmpdir, crate_type); + cmd.export_symbols(tmpdir, crate_type); } // When linking a dynamic library, we put the metadata into a section of the diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 50f6366e85c..cb990ead8e8 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -15,13 +15,50 @@ use std::io::prelude::*; use std::path::{Path, PathBuf}; use std::process::Command; +use context::SharedCrateContext; +use monomorphize::Instance; + use back::archive; use middle::dependency_format::Linkage; use session::Session; use session::config::CrateType; use session::config; use syntax::ast; -use CrateTranslation; + +/// For all the linkers we support, and information they might +/// need out of the shared crate context before we get rid of it. +pub struct LinkerInfo { + dylib_exports: Vec, + cdylib_exports: Vec +} + +impl<'a, 'tcx> LinkerInfo { + pub fn new(scx: &SharedCrateContext<'a, 'tcx>, + reachable: &[String]) -> LinkerInfo { + LinkerInfo { + dylib_exports: exported_symbols(scx, reachable, CrateType::CrateTypeDylib), + cdylib_exports: exported_symbols(scx, reachable, CrateType::CrateTypeCdylib) + } + } + + pub fn to_linker(&'a self, + cmd: &'a mut Command, + sess: &'a Session) -> Box { + if sess.target.target.options.is_like_msvc { + Box::new(MsvcLinker { + cmd: cmd, + sess: sess, + info: self + }) as Box + } else { + Box::new(GnuLinker { + cmd: cmd, + sess: sess, + info: self + }) as Box + } + } +} /// Linker abstraction used by back::link to build up the command to invoke a /// linker. @@ -53,16 +90,13 @@ pub trait Linker { fn hint_dynamic(&mut self); fn whole_archives(&mut self); fn no_whole_archives(&mut self); - fn export_symbols(&mut self, - sess: &Session, - trans: &CrateTranslation, - tmpdir: &Path, - crate_type: CrateType); + fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType); } pub struct GnuLinker<'a> { - pub cmd: &'a mut Command, - pub sess: &'a Session, + cmd: &'a mut Command, + sess: &'a Session, + info: &'a LinkerInfo } impl<'a> GnuLinker<'a> { @@ -201,11 +235,7 @@ impl<'a> Linker for GnuLinker<'a> { self.cmd.arg("-Wl,-Bdynamic"); } - fn export_symbols(&mut self, - sess: &Session, - trans: &CrateTranslation, - tmpdir: &Path, - crate_type: CrateType) { + fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) { // If we're compiling a dylib, then we let symbol visibility in object // files to take care of whether they're exported or not. // @@ -225,13 +255,13 @@ impl<'a> Linker for GnuLinker<'a> { }; let res = (|| -> io::Result<()> { let mut f = BufWriter::new(File::create(&path)?); - for sym in exported_symbols(sess, trans, crate_type) { + for sym in &self.info.cdylib_exports { writeln!(f, "{}{}", prefix, sym)?; } Ok(()) })(); if let Err(e) = res { - sess.fatal(&format!("failed to write lib.def file: {}", e)); + self.sess.fatal(&format!("failed to write lib.def file: {}", e)); } let mut arg = OsString::new(); if self.sess.target.target.options.is_like_osx { @@ -245,8 +275,9 @@ impl<'a> Linker for GnuLinker<'a> { } pub struct MsvcLinker<'a> { - pub cmd: &'a mut Command, - pub sess: &'a Session, + cmd: &'a mut Command, + sess: &'a Session, + info: &'a LinkerInfo } impl<'a> Linker for MsvcLinker<'a> { @@ -366,8 +397,6 @@ impl<'a> Linker for MsvcLinker<'a> { // in which case they may continue to transitively be used and hence need // their symbols exported. fn export_symbols(&mut self, - sess: &Session, - trans: &CrateTranslation, tmpdir: &Path, crate_type: CrateType) { let path = tmpdir.join("lib.def"); @@ -378,15 +407,18 @@ impl<'a> Linker for MsvcLinker<'a> { // straight to exports. writeln!(f, "LIBRARY")?; writeln!(f, "EXPORTS")?; - - for sym in exported_symbols(sess, trans, crate_type) { - writeln!(f, " {}", sym)?; + let symbols = if crate_type == CrateType::CrateTypeCdylib { + &self.info.cdylib_exports + } else { + &self.info.dylib_exports + }; + for symbol in symbols { + writeln!(f, " {}", symbol)?; } - Ok(()) })(); if let Err(e) = res { - sess.fatal(&format!("failed to write lib.def file: {}", e)); + self.sess.fatal(&format!("failed to write lib.def file: {}", e)); } let mut arg = OsString::from("/DEF:"); arg.push(path); @@ -394,10 +426,23 @@ impl<'a> Linker for MsvcLinker<'a> { } } -fn exported_symbols(sess: &Session, - trans: &CrateTranslation, - crate_type: CrateType) -> Vec { - let mut symbols = trans.reachable.iter().cloned().collect::>(); +fn exported_symbols(scx: &SharedCrateContext, + reachable: &[String], + crate_type: CrateType) + -> Vec { + if !scx.sess().crate_types.borrow().contains(&crate_type) { + return vec![]; + } + + // See explanation in GnuLinker::export_symbols, for + // why we don't ever need dylib symbols on non-MSVC. + if crate_type == CrateType::CrateTypeDylib { + if !scx.sess().target.target.options.is_like_msvc { + return vec![]; + } + } + + let mut symbols = reachable.to_vec(); // If we're producing anything other than a dylib then the `reachable` array // above is the exhaustive set of symbols we should be exporting. @@ -409,10 +454,10 @@ fn exported_symbols(sess: &Session, return symbols } - let cstore = &sess.cstore; - let formats = sess.dependency_formats.borrow(); - let upstream_symbols = formats[&crate_type].iter(); - symbols.extend(upstream_symbols.enumerate().filter_map(|(i, f)| { + let cstore = &scx.sess().cstore; + let formats = scx.sess().dependency_formats.borrow(); + let deps = formats[&crate_type].iter(); + symbols.extend(deps.enumerate().filter_map(|(i, f)| { if *f == Linkage::Static { Some((i + 1) as ast::CrateNum) } else { @@ -420,9 +465,8 @@ fn exported_symbols(sess: &Session, } }).flat_map(|cnum| { cstore.reachable_ids(cnum) - }).map(|did| { - cstore.item_symbol(did) + }).map(|did| -> String { + Instance::mono(scx, did).symbol_name(scx) })); - - return symbols + symbols } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 94ef80d3b85..84dd633a452 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -31,6 +31,7 @@ use super::CrateTranslation; use super::ModuleTranslation; use back::link; +use back::linker::LinkerInfo; use lint; use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param}; use llvm; @@ -2828,6 +2829,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; let no_builtins = attr::contains_name(&krate.attrs, "no_builtins"); + let linker_info = LinkerInfo::new(&shared_ccx, &reachable_symbols); CrateTranslation { modules: modules, metadata_module: metadata_module, @@ -2835,6 +2837,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, metadata: metadata, reachable: reachable_symbols, no_builtins: no_builtins, + linker_info: linker_info } } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index bccb5aa050b..0188a6d54de 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -145,6 +145,7 @@ pub struct CrateTranslation { pub metadata: Vec, pub reachable: Vec, pub no_builtins: bool, + pub linker_info: back::linker::LinkerInfo } __build_diagnostic_array! { librustc_trans, DIAGNOSTICS }