// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use back::archive::{Archive, METADATA_FILENAME};
-use back::rpath;
-use back::svh::Svh;
+use super::archive::{Archive, ArchiveBuilder, ArchiveConfig, METADATA_FILENAME};
+use super::rpath;
+use super::rpath::RPathConfig;
+use super::svh::Svh;
use driver::driver::{CrateTranslation, OutputFilenames, Input, FileInput};
use driver::config::NoDebugInfo;
use driver::session::Session;
use driver::config;
-use lib::llvm::llvm;
-use lib::llvm::ModuleRef;
-use lib;
+use llvm;
+use llvm::ModuleRef;
use metadata::common::LinkMeta;
use metadata::{encoder, cstore, filesearch, csearch, loader, creader};
use middle::trans::context::CrateContext;
use std::c_str::{ToCStr, CString};
use std::char;
+use std::collections::HashSet;
use std::io::{fs, TempDir, Command};
use std::io;
use std::ptr;
sess.fatal(msg.as_slice());
} else {
let err = CString::new(cstr, true);
- let err = str::from_utf8_lossy(err.as_bytes());
+ let err = String::from_utf8_lossy(err.as_bytes());
sess.fatal(format!("{}: {}",
msg.as_slice(),
err.as_slice()).as_slice());
pub fn write_output_file(
sess: &Session,
- target: lib::llvm::TargetMachineRef,
- pm: lib::llvm::PassManagerRef,
+ target: llvm::TargetMachineRef,
+ pm: llvm::PassManagerRef,
m: ModuleRef,
output: &Path,
- file_type: lib::llvm::FileType) {
+ file_type: llvm::FileType) {
unsafe {
output.with_c_str(|output| {
let result = llvm::LLVMRustWriteOutputFile(
pub mod write {
- use back::lto;
- use back::link::{write_output_file, OutputType};
- use back::link::{OutputTypeAssembly, OutputTypeBitcode};
- use back::link::{OutputTypeExe, OutputTypeLlvmAssembly};
- use back::link::{OutputTypeObject};
+ use super::super::lto;
+ use super::{write_output_file, OutputType};
+ use super::{OutputTypeAssembly, OutputTypeBitcode};
+ use super::{OutputTypeExe, OutputTypeLlvmAssembly};
+ use super::{OutputTypeObject};
use driver::driver::{CrateTranslation, OutputFilenames};
use driver::config::NoDebugInfo;
use driver::session::Session;
use driver::config;
- use lib::llvm::llvm;
- use lib::llvm::{ModuleRef, TargetMachineRef, PassManagerRef};
- use lib;
+ use llvm;
+ use llvm::{ModuleRef, TargetMachineRef, PassManagerRef};
use util::common::time;
use syntax::abi;
}
let opt_level = match sess.opts.optimize {
- config::No => lib::llvm::CodeGenLevelNone,
- config::Less => lib::llvm::CodeGenLevelLess,
- config::Default => lib::llvm::CodeGenLevelDefault,
- config::Aggressive => lib::llvm::CodeGenLevelAggressive,
+ config::No => llvm::CodeGenLevelNone,
+ config::Less => llvm::CodeGenLevelLess,
+ config::Default => llvm::CodeGenLevelDefault,
+ config::Aggressive => llvm::CodeGenLevelAggressive,
};
let use_softfp = sess.opts.cg.soft_float;
let fdata_sections = ffunction_sections;
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,
+ "pic" => llvm::RelocPIC,
+ "static" => llvm::RelocStatic,
+ "default" => llvm::RelocDefault,
+ "dynamic-no-pic" => llvm::RelocDynamicNoPic,
_ => {
sess.err(format!("{} is not a valid relocation mode",
sess.opts
}
};
+ let code_model = match sess.opts.cg.code_model.as_slice() {
+ "default" => llvm::CodeModelDefault,
+ "small" => llvm::CodeModelSmall,
+ "kernel" => llvm::CodeModelKernel,
+ "medium" => llvm::CodeModelMedium,
+ "large" => llvm::CodeModelLarge,
+ _ => {
+ sess.err(format!("{} is not a valid code model",
+ sess.opts
+ .cg
+ .code_model).as_slice());
+ sess.abort_if_errors();
+ return;
+ }
+ };
+
let tm = sess.targ_cfg
.target_strs
.target_triple
target_feature(sess).with_c_str(|features| {
llvm::LLVMRustCreateTargetMachine(
t, cpu, features,
- lib::llvm::CodeModelDefault,
+ code_model,
reloc_model,
opt_level,
true /* EnableSegstk */,
};
with_codegen(tm, llmod, trans.no_builtins, |cpm| {
write_output_file(sess, tm, cpm, llmod, &path,
- lib::llvm::AssemblyFile);
+ llvm::AssemblyFile);
});
}
OutputTypeObject => {
Some(ref path) => {
with_codegen(tm, llmod, trans.no_builtins, |cpm| {
write_output_file(sess, tm, cpm, llmod, path,
- lib::llvm::ObjectFile);
+ llvm::ObjectFile);
});
}
None => {}
.with_extension("metadata.o");
write_output_file(sess, tm, cpm,
trans.metadata_module, &out,
- lib::llvm::ObjectFile);
+ llvm::ObjectFile);
})
}
});
sess.note(format!("{}", &cmd).as_slice());
let mut note = prog.error.clone();
note.push_all(prog.output.as_slice());
- sess.note(str::from_utf8(note.as_slice()).unwrap()
- .as_slice());
+ sess.note(str::from_utf8(note.as_slice()).unwrap());
sess.abort_if_errors();
}
},
});
}
- unsafe fn populate_llvm_passes(fpm: lib::llvm::PassManagerRef,
- mpm: lib::llvm::PassManagerRef,
+ unsafe fn populate_llvm_passes(fpm: llvm::PassManagerRef,
+ mpm: llvm::PassManagerRef,
llmod: ModuleRef,
- opt: lib::llvm::CodeGenOptLevel,
+ opt: llvm::CodeGenOptLevel,
no_builtins: bool) {
// Create the PassManagerBuilder for LLVM. We configure it with
// reasonable defaults and prepare it to actually populate the pass
// manager.
let builder = llvm::LLVMPassManagerBuilderCreate();
match opt {
- lib::llvm::CodeGenLevelNone => {
+ llvm::CodeGenLevelNone => {
// Don't add lifetime intrinsics at O0
llvm::LLVMRustAddAlwaysInlinePass(builder, false);
}
- lib::llvm::CodeGenLevelLess => {
+ llvm::CodeGenLevelLess => {
llvm::LLVMRustAddAlwaysInlinePass(builder, true);
}
// numeric values copied from clang
- lib::llvm::CodeGenLevelDefault => {
+ llvm::CodeGenLevelDefault => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
225);
}
- lib::llvm::CodeGenLevelAggressive => {
+ llvm::CodeGenLevelAggressive => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
275);
}
s
};
+ // Look in attributes 100% of the time to make sure the attribute is marked
+ // as used. After doing this, however, we still prioritize a crate name from
+ // the command line over one found in the #[crate_name] attribute. If we
+ // find both we ensure that they're the same later on as well.
+ let attr_crate_name = attrs.iter().find(|at| at.check_name("crate_name"))
+ .and_then(|at| at.value_str().map(|s| (at, s)));
+
match sess {
Some(sess) => {
match sess.opts.crate_name {
- Some(ref s) => return validate(s.clone(), None),
+ Some(ref s) => {
+ match attr_crate_name {
+ Some((attr, ref name)) if s.as_slice() != name.get() => {
+ let msg = format!("--crate-name and #[crate_name] \
+ are required to match, but `{}` \
+ != `{}`", s, name);
+ sess.span_err(attr.span, msg.as_slice());
+ }
+ _ => {},
+ }
+ return validate(s.clone(), None);
+ }
None => {}
}
}
None => {}
}
- let crate_name = attrs.iter().find(|at| at.check_name("crate_name"))
- .and_then(|at| at.value_str().map(|s| (at, s)));
- match crate_name {
+ match attr_crate_name {
Some((attr, s)) => return validate(s.get().to_string(), Some(attr.span)),
None => {}
}
name: String) -> LinkMeta {
let r = LinkMeta {
crate_name: name,
- crate_hash: Svh::calculate(sess, krate),
+ crate_hash: Svh::calculate(&sess.opts.cg.metadata, krate),
};
info!("{}", r);
return r;
abi::OsLinux => (loader::LINUX_DLL_PREFIX, loader::LINUX_DLL_SUFFIX),
abi::OsAndroid => (loader::ANDROID_DLL_PREFIX, loader::ANDROID_DLL_SUFFIX),
abi::OsFreebsd => (loader::FREEBSD_DLL_PREFIX, loader::FREEBSD_DLL_SUFFIX),
+ abi::OsDragonfly => (loader::DRAGONFLY_DLL_PREFIX, loader::DRAGONFLY_DLL_SUFFIX),
abi::OsiOS => unreachable!(),
};
out_filename.with_filename(format!("{}{}{}",
config::CrateTypeStaticlib => {
out_filename.with_filename(format!("lib{}.a", libname))
}
- config::CrateTypeExecutable => out_filename.clone(),
+ config::CrateTypeExecutable => {
+ match sess.targ_cfg.os {
+ abi::OsWin32 => out_filename.with_extension("exe"),
+ abi::OsMacos |
+ abi::OsLinux |
+ abi::OsAndroid |
+ abi::OsFreebsd |
+ abi::OsDragonfly |
+ abi::OsiOS => out_filename.clone(),
+ }
+ }
}
}
match crate_type {
config::CrateTypeRlib => {
- link_rlib(sess, Some(trans), &obj_filename, &out_filename);
+ link_rlib(sess, Some(trans), &obj_filename, &out_filename).build();
}
config::CrateTypeStaticlib => {
link_staticlib(sess, &obj_filename, &out_filename);
out_filename
}
+fn archive_search_paths(sess: &Session) -> Vec<Path> {
+ let mut rustpath = filesearch::rust_path();
+ rustpath.push(sess.target_filesearch().get_lib_path());
+ // FIXME: Addl lib search paths are an unordered HashSet?
+ // Shouldn't this search be done in some order?
+ let addl_lib_paths: HashSet<Path> = sess.opts.addl_lib_search_paths.borrow().clone();
+ let mut search: Vec<Path> = addl_lib_paths.move_iter().collect();
+ search.push_all(rustpath.as_slice());
+ return search;
+}
+
// Create an 'rlib'
//
// An rlib in its current incarnation is essentially a renamed .a file. The
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);
+ out_filename: &Path) -> ArchiveBuilder<'a> {
+ let handler = &sess.diagnostic().handler;
+ let config = ArchiveConfig {
+ handler: handler,
+ dst: out_filename.clone(),
+ lib_search_paths: archive_search_paths(sess),
+ os: sess.targ_cfg.os,
+ maybe_ar_prog: sess.opts.cg.ar.clone()
+ };
+ let mut ab = ArchiveBuilder::create(config);
+ ab.add_file(obj_filename).unwrap();
for &(ref l, kind) in sess.cstore.get_used_libraries().borrow().iter() {
match kind {
cstore::NativeStatic => {
- a.add_native_library(l.as_slice()).unwrap();
+ ab.add_native_library(l.as_slice()).unwrap();
}
cstore::NativeFramework | cstore::NativeUnknown => {}
}
}
+ // After adding all files to the archive, we need to update the
+ // symbol table of the archive.
+ ab.update_symbols();
+
+ let mut ab = match sess.targ_cfg.os {
+ // For OSX/iOS, we must be careful to update symbols only when adding
+ // object files. We're about to start adding non-object files, so run
+ // `ar` now to process the object files.
+ abi::OsMacos | abi::OsiOS => ab.build().extend(),
+ _ => ab,
+ };
+
// Note that it is important that we add all of our non-object "magical
// files" *after* all of the object files in the archive. The reason for
// this is as follows:
sess.abort_if_errors();
}
}
- a.add_file(&metadata, false);
+ ab.add_file(&metadata).unwrap();
remove(sess, &metadata);
// For LTO purposes, the bytecode of this library is also inserted
sess.abort_if_errors()
}
}
- a.add_file(&bc_deflated, false);
+ ab.add_file(&bc_deflated).unwrap();
remove(sess, &bc_deflated);
if !sess.opts.cg.save_temps &&
!sess.opts.output_types.contains(&OutputTypeBitcode) {
remove(sess, &bc);
}
-
- // After adding all files to the archive, we need to update the
- // symbol table of the archive. This currently dies on OSX (see
- // #11162), and isn't necessary there anyway
- match sess.targ_cfg.os {
- abi::OsMacos | abi::OsiOS => {}
- _ => { a.update_symbols(); }
- }
}
None => {}
}
- return a;
+
+ ab
}
// Create a static archive
// 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) {
- let mut a = link_rlib(sess, None, obj_filename, out_filename);
- a.add_native_library("morestack").unwrap();
- a.add_native_library("compiler-rt").unwrap();
+ let ab = link_rlib(sess, None, obj_filename, out_filename);
+ let mut ab = match sess.targ_cfg.os {
+ abi::OsMacos | abi::OsiOS => ab.build().extend(),
+ _ => ab,
+ };
+ ab.add_native_library("morestack").unwrap();
+ ab.add_native_library("compiler-rt").unwrap();
let crates = sess.cstore.get_used_crates(cstore::RequireStatic);
let mut all_native_libs = vec![];
continue
}
};
- a.add_rlib(&p, name.as_slice(), sess.lto()).unwrap();
+ ab.add_rlib(&p, name.as_slice(), sess.lto()).unwrap();
let native_libs = csearch::get_native_libraries(&sess.cstore, cnum);
all_native_libs.extend(native_libs.move_iter());
}
+ ab.update_symbols();
+ let _ = ab.build();
+
if !all_native_libs.is_empty() {
sess.warn("link against the following native artifacts when linking against \
this static library");
sess.note(format!("{}", &cmd).as_slice());
let mut output = prog.error.clone();
output.push_all(prog.output.as_slice());
- sess.note(str::from_utf8(output.as_slice()).unwrap()
- .as_slice());
+ sess.note(str::from_utf8(output.as_slice()).unwrap());
sess.abort_if_errors();
}
},
// the symbols
if (sess.targ_cfg.os == abi::OsMacos || sess.targ_cfg.os == abi::OsiOS)
&& (sess.opts.debuginfo != NoDebugInfo) {
- match Command::new("dsymutil").arg(out_filename).status() {
+ match Command::new("dsymutil").arg(out_filename).output() {
Ok(..) => {}
Err(e) => {
sess.err(format!("failed to run dsymutil: {}", e).as_slice());
abi::OsMacos | abi::OsiOS => {
let morestack = lib_path.join("libmorestack.a");
- let mut v = "-Wl,-force_load,".as_bytes().to_owned();
+ let mut v = b"-Wl,-force_load,".to_vec();
v.push_all(morestack.as_vec());
cmd.arg(v.as_slice());
}
cmd.arg("-Wl,--gc-sections");
}
- if sess.targ_cfg.os == abi::OsLinux {
+ if sess.targ_cfg.os == abi::OsLinux || sess.targ_cfg.os == abi::OsDragonfly {
// 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.
if sess.targ_cfg.os == abi::OsMacos {
cmd.args(["-dynamiclib", "-Wl,-dylib"]);
- if !sess.opts.cg.no_rpath {
+ if sess.opts.cg.rpath {
let mut v = Vec::from_slice("-Wl,-install_name,@rpath/".as_bytes());
v.push_all(out_filename.filename().unwrap());
cmd.arg(v.as_slice());
"-L/usr/local/lib/gcc46",
"-L/usr/local/lib/gcc44"]);
}
+ else if sess.targ_cfg.os == abi::OsDragonfly {
+ cmd.args(["-L/usr/local/lib",
+ "-L/usr/lib/gcc47",
+ "-L/usr/lib/gcc44"]);
+ }
+
// FIXME (#2397): At some point we want to rpath our guesses as to
// where extern libraries might live, based on the
// addl_lib_search_paths
- if !sess.opts.cg.no_rpath {
- cmd.args(rpath::get_rpath_flags(sess, out_filename).as_slice());
+ if sess.opts.cg.rpath {
+ let sysroot = sess.sysroot();
+ let target_triple = sess.opts.target_triple.as_slice();
+ let get_install_prefix_lib_path = || {
+ let install_prefix = option_env!("CFG_PREFIX").expect("CFG_PREFIX");
+ let tlib = filesearch::relative_target_lib_path(sysroot, target_triple);
+ let mut path = Path::new(install_prefix);
+ path.push(&tlib);
+
+ path
+ };
+ let rpath_config = RPathConfig {
+ os: sess.targ_cfg.os,
+ used_crates: sess.cstore.get_used_crates(cstore::RequireDynamic),
+ out_filename: out_filename.clone(),
+ get_install_prefix_lib_path: get_install_prefix_lib_path,
+ realpath: ::util::fs::realpath
+ };
+ cmd.args(rpath::get_rpath_flags(rpath_config).as_slice());
}
// compiler-rt contains implementations of low-level LLVM helpers. This is
add_dynamic_crate(cmd, sess, src.dylib.unwrap())
}
cstore::RequireStatic => {
- add_static_crate(cmd, sess, tmpdir, cnum, src.rlib.unwrap())
+ add_static_crate(cmd, sess, tmpdir, src.rlib.unwrap())
}
}
// Adds the static "rlib" versions of all crates to the command line.
fn add_static_crate(cmd: &mut Command, sess: &Session, tmpdir: &Path,
- cnum: ast::CrateNum, cratepath: Path) {
+ cratepath: Path) {
// When performing LTO on an executable output, all of the
// bytecode from the upstream libraries has already been
// included in our object file output. We need to modify all of
// If we're not doing LTO, then our job is simply to just link
// against the archive.
if sess.lto() {
- let name = sess.cstore.get_crate_data(cnum).name.clone();
+ let name = cratepath.filename_str().unwrap();
+ let name = name.slice(3, name.len() - 5); // chop off lib/.rlib
time(sess.time_passes(),
format!("altering {}.rlib", name).as_slice(),
(), |()| {
sess.abort_if_errors();
}
}
- let mut archive = Archive::open(sess, dst.clone());
+ let handler = &sess.diagnostic().handler;
+ let config = ArchiveConfig {
+ handler: handler,
+ dst: dst.clone(),
+ lib_search_paths: archive_search_paths(sess),
+ os: sess.targ_cfg.os,
+ maybe_ar_prog: sess.opts.cg.ar.clone()
+ };
+ let mut archive = Archive::open(config);
archive.remove_file(format!("{}.o", name).as_slice());
let files = archive.files();
if files.iter().any(|s| s.as_slice().ends_with(".o")) {