// 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;
}
{
- 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>
- };
+ 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");
}
tmpdir: &Path,
objects: &[PathBuf],
out_filename: &Path,
- trans: &CrateTranslation,
outputs: &OutputFilenames) {
// The default library location, we need this to find the runtime.
// 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
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<String>,
+ cdylib_exports: Vec<String>
+}
+
+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<Linker+'a> {
+ if sess.target.target.options.is_like_msvc {
+ Box::new(MsvcLinker {
+ cmd: cmd,
+ sess: sess,
+ info: self
+ }) as Box<Linker>
+ } else {
+ Box::new(GnuLinker {
+ cmd: cmd,
+ sess: sess,
+ info: self
+ }) as Box<Linker>
+ }
+ }
+}
/// Linker abstraction used by back::link to build up the command to invoke a
/// 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> {
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.
//
};
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 {
}
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> {
// 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");
// 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);
}
}
-fn exported_symbols(sess: &Session,
- trans: &CrateTranslation,
- crate_type: CrateType) -> Vec<String> {
- let mut symbols = trans.reachable.iter().cloned().collect::<Vec<_>>();
+fn exported_symbols(scx: &SharedCrateContext,
+ reachable: &[String],
+ crate_type: CrateType)
+ -> Vec<String> {
+ 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.
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 {
}
}).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
}