use std::c_str::{ToCStr, CString};
use std::char;
+use std::io::{fs, TempDir, Process};
+use std::io;
use std::os::consts::{macos, freebsd, linux, android, win32};
use std::ptr;
use std::str;
-use std::io;
-use std::io::{fs, TempDir, Process};
-use std::vec_ng::Vec;
+use std::strbuf::StrBuf;
use flate;
use serialize::hex::ToHex;
use syntax::abi;
OutputTypeExe,
}
-pub fn llvm_err(sess: Session, msg: ~str) -> ! {
+pub fn llvm_err(sess: &Session, msg: ~str) -> ! {
unsafe {
let cstr = llvm::LLVMRustGetLastError();
if cstr == ptr::null() {
}
pub fn WriteOutputFile(
- sess: Session,
+ sess: &Session,
target: lib::llvm::TargetMachineRef,
pm: lib::llvm::PassManagerRef,
m: ModuleRef,
let result = llvm::LLVMRustWriteOutputFile(
target, pm, m, output, file_type);
if !result {
- llvm_err(sess, ~"could not write output");
+ llvm_err(sess, "could not write output".to_owned());
}
})
}
use std::c_str::ToCStr;
use std::io::Process;
- use std::libc::{c_uint, c_int};
+ use libc::{c_uint, c_int};
use std::str;
- use std::vec_ng::Vec;
// On android, we by default compile for armv7 processors. This enables
// things like double word CAS instructions (rather than emulating them)
}
}
- pub fn run_passes(sess: Session,
+ pub fn run_passes(sess: &Session,
trans: &CrateTranslation,
output_types: &[OutputType],
output: &OutputFilenames) {
(sess.targ_cfg.os == abi::OsMacos &&
sess.targ_cfg.arch == abi::X86_64);
+ let reloc_model = match sess.opts.cg.relocation_model.as_slice() {
+ "pic" => lib::llvm::RelocPIC,
+ "static" => lib::llvm::RelocStatic,
+ "default" => lib::llvm::RelocDefault,
+ "dynamic-no-pic" => lib::llvm::RelocDynamicNoPic,
+ _ => {
+ sess.err(format!("{} is not a valid relocation mode",
+ sess.opts.cg.relocation_model));
+ sess.abort_if_errors();
+ return;
+ }
+ };
+
let tm = sess.targ_cfg.target_strs.target_triple.with_c_str(|t| {
sess.opts.cg.target_cpu.with_c_str(|cpu| {
- target_feature(&sess).with_c_str(|features| {
+ target_feature(sess).with_c_str(|features| {
llvm::LLVMRustCreateTargetMachine(
t, cpu, features,
lib::llvm::CodeModelDefault,
- lib::llvm::RelocPIC,
+ reloc_model,
opt_level,
true,
use_softfp,
// Emit the bytecode if we're either saving our temporaries or
// emitting an rlib. Whenever an rlib is created, the bytecode is
// inserted into the archive in order to allow LTO against it.
- let crate_types = sess.crate_types.borrow();
if sess.opts.cg.save_temps ||
- (crate_types.get().contains(&session::CrateTypeRlib) &&
+ (sess.crate_types.borrow().contains(&session::CrateTypeRlib) &&
sess.opts.output_types.contains(&OutputTypeExe)) {
output.temp_path(OutputTypeBitcode).with_c_str(|buf| {
llvm::LLVMWriteBitcodeToFile(llmod, buf);
}
}
- pub fn run_assembler(sess: Session, outputs: &OutputFilenames) {
+ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
let cc = super::get_cc_prog(sess);
let assembly = outputs.temp_path(OutputTypeAssembly);
let object = outputs.path(OutputTypeObject);
// FIXME (#9639): This needs to handle non-utf8 paths
let args = [
- ~"-c",
- ~"-o", object.as_str().unwrap().to_owned(),
+ "-c".to_owned(),
+ "-o".to_owned(), object.as_str().unwrap().to_owned(),
assembly.as_str().unwrap().to_owned()];
debug!("{} '{}'", cc, args.connect("' '"));
if !prog.status.success() {
sess.err(format!("linking with `{}` failed: {}", cc, prog.status));
sess.note(format!("{} arguments: '{}'", cc, args.connect("' '")));
- sess.note(str::from_utf8_owned(prog.error + prog.output).unwrap());
+ let mut note = prog.error.clone();
+ note.push_all(prog.output.as_slice());
+ sess.note(str::from_utf8(note.as_slice()).unwrap().to_owned());
sess.abort_if_errors();
}
},
}
}
- unsafe fn configure_llvm(sess: Session) {
+ unsafe fn configure_llvm(sess: &Session) {
use sync::one::{Once, ONCE_INIT};
static mut INIT: Once = ONCE_INIT;
// This calculates STH for a symbol, as defined above
-fn symbol_hash(tcx: ty::ctxt, symbol_hasher: &mut Sha256,
- t: ty::t, link_meta: &LinkMeta) -> ~str {
+fn symbol_hash(tcx: &ty::ctxt,
+ symbol_hasher: &mut Sha256,
+ t: ty::t,
+ link_meta: &LinkMeta)
+ -> ~str {
// NB: do *not* use abbrevs here as we want the symbol names
// to be independent of one another in the crate.
symbol_hasher.input_str(link_meta.crate_hash.as_str());
symbol_hasher.input_str("-");
symbol_hasher.input_str(encoder::encoded_ty(tcx, t));
- let mut hash = truncated_hash_result(symbol_hasher);
// Prefix with 'h' so that it never blends into adjacent digits
- hash.unshift_char('h');
- hash
+ let mut hash = StrBuf::from_str("h");
+ hash.push_str(truncated_hash_result(symbol_hasher));
+ hash.into_owned()
}
fn get_symbol_hash(ccx: &CrateContext, t: ty::t) -> ~str {
- match ccx.type_hashcodes.borrow().get().find(&t) {
+ match ccx.type_hashcodes.borrow().find(&t) {
Some(h) => return h.to_str(),
None => {}
}
- let mut type_hashcodes = ccx.type_hashcodes.borrow_mut();
let mut symbol_hasher = ccx.symbol_hasher.borrow_mut();
- let hash = symbol_hash(ccx.tcx, symbol_hasher.get(), t, &ccx.link_meta);
- type_hashcodes.get().insert(t, hash.clone());
+ let hash = symbol_hash(ccx.tcx(), &mut *symbol_hasher, t, &ccx.link_meta);
+ ccx.type_hashcodes.borrow_mut().insert(t, hash.clone());
hash
}
// gas doesn't!
// gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $
pub fn sanitize(s: &str) -> ~str {
- let mut result = ~"";
+ let mut result = StrBuf::new();
for c in s.chars() {
match c {
// Escape these with $ sequences
| '_' | '.' | '$' => result.push_char(c),
_ => {
- let mut tstr = ~"";
+ let mut tstr = StrBuf::new();
char::escape_unicode(c, |c| tstr.push_char(c));
result.push_char('$');
- result.push_str(tstr.slice_from(1));
+ result.push_str(tstr.as_slice().slice_from(1));
}
}
}
// Underscore-qualify anything that didn't start as an ident.
+ let result = result.into_owned();
if result.len() > 0u &&
result[0] != '_' as u8 &&
! char::is_XID_start(result[0] as char) {
- return ~"_" + result;
+ return "_".to_owned() + result;
}
return result;
// To be able to work on all platforms and get *some* reasonable output, we
// use C++ name-mangling.
- let mut n = ~"_ZN"; // _Z == Begin name-sequence, N == nested
+ let mut n = StrBuf::from_str("_ZN"); // _Z == Begin name-sequence, N == nested
- fn push(n: &mut ~str, s: &str) {
+ fn push(n: &mut StrBuf, s: &str) {
let sani = sanitize(s);
n.push_str(format!("{}{}", sani.len(), sani));
}
}
n.push_char('E'); // End name-sequence.
- n
+ n.into_owned()
}
pub fn exported_name(path: PathElems, hash: &str, vers: &str) -> ~str {
pub fn mangle_exported_name(ccx: &CrateContext, path: PathElems,
t: ty::t, id: ast::NodeId) -> ~str {
- let mut hash = get_symbol_hash(ccx, t);
+ let mut hash = StrBuf::from_owned_str(get_symbol_hash(ccx, t));
// Paths can be completely identical for different nodes,
// e.g. `fn foo() { { fn a() {} } { fn a() {} } }`, so we
hash.push_char(EXTRA_CHARS[extra2] as char);
hash.push_char(EXTRA_CHARS[extra3] as char);
- exported_name(path, hash, ccx.link_meta.crateid.version_or_default())
-}
-
-pub fn mangle_internal_name_by_type_only(ccx: &CrateContext,
- t: ty::t,
- name: &str) -> ~str {
- let s = ppaux::ty_to_short_str(ccx.tcx, t);
- let path = [PathName(token::intern(name)),
- PathName(token::intern(s))];
- let hash = get_symbol_hash(ccx, t);
- mangle(ast_map::Values(path.iter()), Some(hash.as_slice()), None)
+ exported_name(path,
+ hash.as_slice(),
+ ccx.link_meta.crateid.version_or_default())
}
pub fn mangle_internal_name_by_type_and_seq(ccx: &CrateContext,
t: ty::t,
name: &str) -> ~str {
- let s = ppaux::ty_to_str(ccx.tcx, t);
+ let s = ppaux::ty_to_str(ccx.tcx(), t);
let path = [PathName(token::intern(s)),
gensym_name(name)];
let hash = get_symbol_hash(ccx, t);
format!("{}-{}-{}", id.name, crate_id_hash(id), id.version_or_default())
}
-pub fn get_cc_prog(sess: Session) -> ~str {
+pub fn get_cc_prog(sess: &Session) -> ~str {
match sess.opts.cg.linker {
Some(ref linker) => return linker.to_owned(),
None => {}
// instead of hard-coded gcc.
// For win32, there is no cc command, so we add a condition to make it use gcc.
match sess.targ_cfg.os {
- abi::OsWin32 => return ~"gcc",
+ abi::OsWin32 => return "gcc".to_owned(),
_ => {},
}
get_system_tool(sess, "cc")
}
-pub fn get_ar_prog(sess: Session) -> ~str {
+pub fn get_ar_prog(sess: &Session) -> ~str {
match sess.opts.cg.ar {
Some(ref ar) => return ar.to_owned(),
None => {}
get_system_tool(sess, "ar")
}
-fn get_system_tool(sess: Session, tool: &str) -> ~str {
+fn get_system_tool(sess: &Session, tool: &str) -> ~str {
match sess.targ_cfg.os {
abi::OsAndroid => match sess.opts.cg.android_cross_path {
Some(ref path) => {
}
}
-fn remove(sess: Session, path: &Path) {
+fn remove(sess: &Session, path: &Path) {
match fs::unlink(path) {
Ok(..) => {}
Err(e) => {
/// Perform the linkage portion of the compilation phase. This will generate all
/// of the requested outputs for this compilation session.
-pub fn link_binary(sess: Session,
+pub fn link_binary(sess: &Session,
trans: &CrateTranslation,
outputs: &OutputFilenames,
id: &CrateId) -> Vec<Path> {
let mut out_filenames = Vec::new();
- let crate_types = sess.crate_types.borrow();
- for &crate_type in crate_types.get().iter() {
+ for &crate_type in sess.crate_types.borrow().iter() {
let out_file = link_binary_output(sess, trans, crate_type, outputs, id);
out_filenames.push(out_file);
}
}
}
-fn link_binary_output(sess: Session,
+fn link_binary_output(sess: &Session,
trans: &CrateTranslation,
crate_type: session::CrateType,
outputs: &OutputFilenames,
Some(ref file) => file.clone(),
None => {
let out_filename = outputs.path(OutputTypeExe);
- filename_for_input(&sess, crate_type, id, &out_filename)
+ filename_for_input(sess, crate_type, id, &out_filename)
}
};
// rlib primarily contains the object file of the crate, but it also contains
// all of the object files from native libraries. This is done by unzipping
// native libraries and inserting all of the contents into this archive.
-fn link_rlib(sess: Session,
- trans: Option<&CrateTranslation>, // None == no metadata/bytecode
- obj_filename: &Path,
- out_filename: &Path) -> Archive {
+fn link_rlib<'a>(sess: &'a Session,
+ trans: Option<&CrateTranslation>, // None == no metadata/bytecode
+ obj_filename: &Path,
+ out_filename: &Path) -> Archive<'a> {
let mut a = Archive::create(sess, out_filename, obj_filename);
- let used_libraries = sess.cstore.get_used_libraries();
- let used_libraries = used_libraries.borrow();
- for &(ref l, kind) in used_libraries.get().iter() {
+ for &(ref l, kind) in sess.cstore.get_used_libraries().borrow().iter() {
match kind {
cstore::NativeStatic => {
a.add_native_library(l.as_slice()).unwrap();
// For LTO purposes, the bytecode of this library is also inserted
// into the archive.
let bc = obj_filename.with_extension("bc");
+ let bc_deflated = obj_filename.with_extension("bc.deflate");
match fs::File::open(&bc).read_to_end().and_then(|data| {
- fs::File::create(&bc).write(flate::deflate_bytes(data).as_slice())
+ fs::File::create(&bc_deflated)
+ .write(match flate::deflate_bytes(data.as_slice()) {
+ Some(compressed) => compressed,
+ None => sess.fatal("failed to compress bytecode")
+ }.as_slice())
}) {
Ok(()) => {}
Err(e) => {
- sess.err(format!("failed to compress bytecode: {}", e));
+ sess.err(format!("failed to write compressed bytecode: {}", e));
sess.abort_if_errors()
}
}
- a.add_file(&bc, false);
+ a.add_file(&bc_deflated, false);
+ remove(sess, &bc_deflated);
if !sess.opts.cg.save_temps &&
!sess.opts.output_types.contains(&OutputTypeBitcode) {
remove(sess, &bc);
// There's no need to include metadata in a static archive, so ensure to not
// link in the metadata object file (and also don't prepare the archive with a
// metadata file).
-fn link_staticlib(sess: Session, obj_filename: &Path, out_filename: &Path) {
+fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) {
let mut a = link_rlib(sess, None, obj_filename, out_filename);
a.add_native_library("morestack").unwrap();
a.add_native_library("compiler-rt").unwrap();
}
};
a.add_rlib(&p, name, sess.lto()).unwrap();
- let native_libs = csearch::get_native_libraries(sess.cstore, cnum);
+ let native_libs = csearch::get_native_libraries(&sess.cstore, cnum);
for &(kind, ref lib) in native_libs.iter() {
let name = match kind {
cstore::NativeStatic => "static library",
//
// This will invoke the system linker/cc to create the resulting file. This
// links to all upstream files as well.
-fn link_natively(sess: Session, dylib: bool, obj_filename: &Path,
+fn link_natively(sess: &Session, dylib: bool, obj_filename: &Path,
out_filename: &Path) {
let tmpdir = TempDir::new("rustc").expect("needs a temp dir");
// The invocations of cc share some flags across platforms
if !prog.status.success() {
sess.err(format!("linking with `{}` failed: {}", cc_prog, prog.status));
sess.note(format!("{} arguments: '{}'", cc_prog, cc_args.connect("' '")));
- sess.note(str::from_utf8_owned(prog.error + prog.output).unwrap());
+ let mut output = prog.error.clone();
+ output.push_all(prog.output.as_slice());
+ sess.note(str::from_utf8(output.as_slice()).unwrap().to_owned());
sess.abort_if_errors();
}
},
}
}
-fn link_args(sess: Session,
+fn link_args(sess: &Session,
dylib: bool,
tmpdir: &Path,
obj_filename: &Path,
// The default library location, we need this to find the runtime.
// The location of crates will be determined as needed.
// FIXME (#9639): This needs to handle non-utf8 paths
- let lib_path = sess.filesearch.get_target_lib_path();
- let stage: ~str = ~"-L" + lib_path.as_str().unwrap();
+ let lib_path = sess.filesearch().get_target_lib_path();
+ let stage: ~str = "-L".to_owned() + lib_path.as_str().unwrap();
let mut args = vec!(stage);
// FIXME (#9639): This needs to handle non-utf8 paths
args.push_all([
- ~"-o", out_filename.as_str().unwrap().to_owned(),
+ "-o".to_owned(), out_filename.as_str().unwrap().to_owned(),
obj_filename.as_str().unwrap().to_owned()]);
// Stack growth requires statically linking a __morestack function. Note
// line, but inserting this farther to the left makes the
// "rust_stack_exhausted" symbol an outstanding undefined symbol, which
// flags libstd as a required library (or whatever provides the symbol).
- args.push(~"-lmorestack");
+ args.push("-lmorestack".to_owned());
// When linking a dynamic library, we put the metadata into a section of the
// executable. This metadata is in a separate object file from the main
//
// FIXME(#11937) we should invoke the system linker directly
if sess.targ_cfg.os != abi::OsWin32 {
- args.push(~"-nodefaultlibs");
+ args.push("-nodefaultlibs".to_owned());
}
if sess.targ_cfg.os == abi::OsLinux {
// GNU-style linkers will use this to omit linking to libraries which
// don't actually fulfill any relocations, but only for libraries which
// follow this flag. Thus, use it before specifying libraries to link to.
- args.push(~"-Wl,--as-needed");
+ args.push("-Wl,--as-needed".to_owned());
// GNU-style linkers support optimization with -O. --gc-sections
// removes metadata and potentially other useful things, so don't
// do.
if sess.opts.optimize == session::Default ||
sess.opts.optimize == session::Aggressive {
- args.push(~"-Wl,-O1");
+ args.push("-Wl,-O1".to_owned());
}
}
// Make sure that we link to the dynamic libgcc, otherwise cross-module
// DWARF stack unwinding will not work.
// This behavior may be overridden by --link-args "-static-libgcc"
- args.push(~"-shared-libgcc");
+ args.push("-shared-libgcc".to_owned());
+
+ // And here, we see obscure linker flags #45. On windows, it has been
+ // found to be necessary to have this flag to compile liblibc.
+ //
+ // First a bit of background. On Windows, the file format is not ELF,
+ // but COFF (at least according to LLVM). COFF doesn't officially allow
+ // for section names over 8 characters, apparently. Our metadata
+ // section, ".note.rustc", you'll note is over 8 characters.
+ //
+ // On more recent versions of gcc on mingw, apparently the section name
+ // is *not* truncated, but rather stored elsewhere in a separate lookup
+ // table. On older versions of gcc, they apparently always truncated the
+ // section names (at least in some cases). Truncating the section name
+ // actually creates "invalid" objects [1] [2], but only for some
+ // introspection tools, not in terms of whether it can be loaded.
+ //
+ // Long story shory, passing this flag forces the linker to *not*
+ // truncate section names (so we can find the metadata section after
+ // it's compiled). The real kicker is that rust compiled just fine on
+ // windows for quite a long time *without* this flag, so I have no idea
+ // why it suddenly started failing for liblibc. Regardless, we
+ // definitely don't want section name truncation, so we're keeping this
+ // flag for windows.
+ //
+ // [1] - https://sourceware.org/bugzilla/show_bug.cgi?id=13130
+ // [2] - https://code.google.com/p/go/issues/detail?id=2139
+ args.push("-Wl,--enable-long-section-names".to_owned());
}
if sess.targ_cfg.os == abi::OsAndroid {
// Many of the symbols defined in compiler-rt are also defined in libgcc.
// Android linker doesn't like that by default.
- args.push(~"-Wl,--allow-multiple-definition");
+ args.push("-Wl,--allow-multiple-definition".to_owned());
}
// Take careful note of the ordering of the arguments we pass to the linker
if dylib {
// On mac we need to tell the linker to let this library be rpathed
if sess.targ_cfg.os == abi::OsMacos {
- args.push(~"-dynamiclib");
- args.push(~"-Wl,-dylib");
+ args.push("-dynamiclib".to_owned());
+ args.push("-Wl,-dylib".to_owned());
// FIXME (#9639): This needs to handle non-utf8 paths
if !sess.opts.cg.no_rpath {
- args.push(~"-Wl,-install_name,@rpath/" +
+ args.push("-Wl,-install_name,@rpath/".to_owned() +
out_filename.filename_str().unwrap());
}
} else {
- args.push(~"-shared")
+ args.push("-shared".to_owned())
}
}
if sess.targ_cfg.os == abi::OsFreebsd {
- args.push_all([~"-L/usr/local/lib",
- ~"-L/usr/local/lib/gcc46",
- ~"-L/usr/local/lib/gcc44"]);
+ args.push_all(["-L/usr/local/lib".to_owned(),
+ "-L/usr/local/lib/gcc46".to_owned(),
+ "-L/usr/local/lib/gcc44".to_owned()]);
}
// FIXME (#2397): At some point we want to rpath our guesses as to
//
// This is the end of the command line, so this library is used to resolve
// *all* undefined symbols in all other libraries, and this is intentional.
- args.push(~"-lcompiler-rt");
+ args.push("-lcompiler-rt".to_owned());
// Finally add all the linker arguments provided on the command line along
// with any #[link_args] attributes found inside the crate
args.push_all(sess.opts.cg.link_args.as_slice());
- let used_link_args = sess.cstore.get_used_link_args();
- let used_link_args = used_link_args.borrow();
- for arg in used_link_args.get().iter() {
+ for arg in sess.cstore.get_used_link_args().borrow().iter() {
args.push(arg.clone());
}
return args;
// Also note that the native libraries linked here are only the ones located
// in the current crate. Upstream crates with native library dependencies
// may have their native library pulled in above.
-fn add_local_native_libraries(args: &mut Vec<~str> , sess: Session) {
- let addl_lib_search_paths = sess.opts.addl_lib_search_paths.borrow();
- for path in addl_lib_search_paths.get().iter() {
+fn add_local_native_libraries(args: &mut Vec<~str>, sess: &Session) {
+ for path in sess.opts.addl_lib_search_paths.borrow().iter() {
// FIXME (#9639): This needs to handle non-utf8 paths
args.push("-L" + path.as_str().unwrap().to_owned());
}
args.push("-L" + path.as_str().unwrap().to_owned());
}
- let used_libraries = sess.cstore.get_used_libraries();
- let used_libraries = used_libraries.borrow();
- for &(ref l, kind) in used_libraries.get().iter() {
+ for &(ref l, kind) in sess.cstore.get_used_libraries().borrow().iter() {
match kind {
cstore::NativeUnknown | cstore::NativeStatic => {
args.push("-l" + *l);
}
cstore::NativeFramework => {
- args.push(~"-framework");
+ args.push("-framework".to_owned());
args.push(l.to_owned());
}
}
// Rust crates are not considered at all when creating an rlib output. All
// dependencies will be linked when producing the final output (instead of
// the intermediate rlib version)
-fn add_upstream_rust_crates(args: &mut Vec<~str> , sess: Session,
+fn add_upstream_rust_crates(args: &mut Vec<~str>, sess: &Session,
dylib: bool, tmpdir: &Path) {
// As a limitation of the current implementation, we require that everything
// * If one form of linking fails, the second is also attempted
// * If both forms fail, then we emit an error message
- let dynamic = get_deps(sess.cstore, cstore::RequireDynamic);
- let statik = get_deps(sess.cstore, cstore::RequireStatic);
+ let dynamic = get_deps(&sess.cstore, cstore::RequireDynamic);
+ let statik = get_deps(&sess.cstore, cstore::RequireStatic);
match (dynamic, statik, sess.opts.cg.prefer_dynamic, dylib) {
(_, Some(deps), false, false) => {
add_static_crates(args, sess, tmpdir, deps)
}
// Converts a library file-stem into a cc -l argument
- fn unlib(config: @session::Config, stem: &str) -> ~str {
- if stem.starts_with("lib") &&
- config.os != abi::OsWin32 {
+ fn unlib(config: &session::Config, stem: &str) -> ~str {
+ if stem.starts_with("lib") && config.os != abi::OsWin32 {
stem.slice(3, stem.len()).to_owned()
} else {
stem.to_owned()
}
// Adds the static "rlib" versions of all crates to the command line.
- fn add_static_crates(args: &mut Vec<~str> , sess: Session, tmpdir: &Path,
- crates: Vec<(ast::CrateNum, Path)> ) {
+ fn add_static_crates(args: &mut Vec<~str>, sess: &Session, tmpdir: &Path,
+ crates: Vec<(ast::CrateNum, Path)>) {
for (cnum, cratepath) in crates.move_iter() {
// When performing LTO on an executable output, all of the
// bytecode from the upstream libraries has already been
}
// Same thing as above, but for dynamic crates instead of static crates.
- fn add_dynamic_crates(args: &mut Vec<~str> , sess: Session,
+ fn add_dynamic_crates(args: &mut Vec<~str>, sess: &Session,
crates: Vec<(ast::CrateNum, Path)> ) {
// If we're performing LTO, then it should have been previously required
// that all upstream rust dependencies were available in an rlib format.
// what its name is
let dir = cratepath.dirname_str().unwrap();
if !dir.is_empty() { args.push("-L" + dir); }
- let libarg = unlib(sess.targ_cfg, cratepath.filestem_str().unwrap());
+ let libarg = unlib(&sess.targ_cfg, cratepath.filestem_str().unwrap());
args.push("-l" + libarg);
}
}
// crate as well.
//
// The use case for this is a little subtle. In theory the native
-// dependencies of a crate a purely an implementation detail of the crate
+// dependencies of a crate are purely an implementation detail of the crate
// itself, but the problem arises with generic and inlined functions. If a
// generic function calls a native function, then the generic function must
// be instantiated in the target crate, meaning that the native symbol must
// also be resolved in the target crate.
-fn add_upstream_native_libraries(args: &mut Vec<~str> , sess: Session) {
- let cstore = sess.cstore;
- cstore.iter_crate_data(|cnum, _| {
- let libs = csearch::get_native_libraries(cstore, cnum);
+fn add_upstream_native_libraries(args: &mut Vec<~str>, sess: &Session) {
+ // Be sure to use a topological sorting of crates becuase there may be
+ // interdependencies between native libraries. When passing -nodefaultlibs,
+ // for example, almost all native libraries depend on libc, so we have to
+ // make sure that's all the way at the right (liblibc is near the base of
+ // the dependency chain).
+ //
+ // This passes RequireStatic, but the actual requirement doesn't matter,
+ // we're just getting an ordering of crate numbers, we're not worried about
+ // the paths.
+ let crates = sess.cstore.get_used_crates(cstore::RequireStatic);
+ for (cnum, _) in crates.move_iter() {
+ let libs = csearch::get_native_libraries(&sess.cstore, cnum);
for &(kind, ref lib) in libs.iter() {
match kind {
cstore::NativeUnknown => args.push("-l" + *lib),
cstore::NativeFramework => {
- args.push(~"-framework");
+ args.push("-framework".to_owned());
args.push(lib.to_owned());
}
cstore::NativeStatic => {
}
}
}
- });
+ }
}