trans: Add kind to writeArchive

Updates our LLVM bindings to be able to write out multiple kinds of archives.
This commit also enables using LLVM instead of the system ar on all current
targets.
This commit is contained in:
Alex Crichton 2015-07-16 00:11:09 -07:00
parent 7f0e733f1d
commit 74e198126b
10 changed files with 52 additions and 15 deletions

View file

@ -23,6 +23,7 @@ pub fn opts() -> TargetOptions {
has_rpath: true,
dll_prefix: "lib".to_string(),
dll_suffix: ".dylib".to_string(),
archive_format: "bsd".to_string(),
pre_link_args: Vec::new(),
.. Default::default()
}

View file

@ -22,6 +22,7 @@ pub fn opts() -> TargetOptions {
position_independent_executables: true,
pre_link_args: vec!(
),
archive_format: "bsd".to_string(),
.. Default::default()
}

View file

@ -29,6 +29,7 @@ pub fn opts() -> TargetOptions {
"-Wl,--as-needed".to_string(),
),
position_independent_executables: true,
archive_format: "bsd".to_string(),
.. Default::default()
}
}

View file

@ -18,6 +18,7 @@ pub fn opts() -> TargetOptions {
executables: true,
morestack: true,
has_rpath: true,
archive_format: "bsd".to_string(),
.. Default::default()
}

View file

@ -27,6 +27,7 @@ pub fn opts() -> TargetOptions {
"-Wl,--as-needed".to_string(),
),
position_independent_executables: true,
archive_format: "bsd".to_string(),
.. Default::default()
}
}

View file

@ -27,6 +27,7 @@ pub fn opts() -> TargetOptions {
"-Wl,--as-needed".to_string(),
),
position_independent_executables: true,
archive_format: "bsd".to_string(),
.. Default::default()
}
}

View file

@ -118,6 +118,9 @@ impl<'a> Child<'a> {
unsafe {
let mut data_len = 0;
let data_ptr = ::LLVMRustArchiveChildData(self.ptr, &mut data_len);
if data_ptr.is_null() {
panic!("failed to read data from archive child");
}
slice::from_raw_parts(data_ptr as *const u8, data_len as usize)
}
}

View file

@ -452,6 +452,15 @@ pub enum DiagnosticKind {
DK_OptimizationFailure,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub enum ArchiveKind {
K_GNU,
K_MIPS64,
K_BSD,
K_COFF,
}
// Opaque pointer types
#[allow(missing_copy_implementations)]
pub enum Module_opaque {}
@ -2119,7 +2128,8 @@ extern {
pub fn LLVMRustWriteArchive(Dst: *const c_char,
NumMembers: size_t,
Members: *const RustArchiveMemberRef,
WriteSymbtab: bool) -> c_int;
WriteSymbtab: bool,
Kind: ArchiveKind) -> c_int;
pub fn LLVMRustArchiveMemberNew(Filename: *const c_char,
Name: *const c_char,
Child: ArchiveChildRef) -> RustArchiveMemberRef;

View file

@ -22,7 +22,7 @@ use std::str;
use libc;
use llvm::archive_ro::{ArchiveRO, Child};
use llvm;
use llvm::{self, ArchiveKind};
use rustc::metadata::loader::METADATA_FILENAME;
use rustc::session::Session;
use rustc_back::tempdir::TempDir;
@ -208,28 +208,34 @@ impl<'a> ArchiveBuilder<'a> {
/// Combine the provided files, rlibs, and native libraries into a single
/// `Archive`.
pub fn build(&mut self) {
let res = if self.using_llvm() {
self.build_with_llvm()
} else {
self.build_with_ar_cmd()
let res = match self.llvm_archive_kind() {
Some(kind) => self.build_with_llvm(kind),
None => self.build_with_ar_cmd(),
};
if let Err(e) = res {
self.config.sess.fatal(&format!("failed to build archive: {}", e));
}
}
pub fn using_llvm(&self) -> bool {
pub fn llvm_archive_kind(&self) -> Option<ArchiveKind> {
if unsafe { llvm::LLVMVersionMinor() < 7 } {
return false
return None
}
// Currently LLVM only supports writing archives in the 'gnu' format.
match &self.config.sess.target.target.options.archive_format[..] {
"gnu" => true,
_ => false,
"gnu" => Some(ArchiveKind::K_GNU),
"mips64" => Some(ArchiveKind::K_MIPS64),
"bsd" => Some(ArchiveKind::K_BSD),
"coff" => Some(ArchiveKind::K_COFF),
_ => None,
}
}
pub fn using_llvm(&self) -> bool {
self.llvm_archive_kind().is_some()
}
fn build_with_ar_cmd(&mut self) -> io::Result<()> {
let removals = mem::replace(&mut self.removals, Vec::new());
let additions = mem::replace(&mut self.additions, Vec::new());
@ -425,7 +431,7 @@ impl<'a> ArchiveBuilder<'a> {
}
}
fn build_with_llvm(&mut self) -> io::Result<()> {
fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> {
let mut archives = Vec::new();
let mut strings = Vec::new();
let mut members = Vec::new();
@ -482,7 +488,8 @@ impl<'a> ArchiveBuilder<'a> {
let r = llvm::LLVMRustWriteArchive(dst.as_ptr(),
members.len() as libc::size_t,
members.as_ptr(),
self.should_update_symbols);
self.should_update_symbols,
kind);
let ret = if r != 0 {
let err = llvm::LLVMRustGetLastError();
let msg = if err.is_null() {

View file

@ -120,7 +120,17 @@ LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) {
extern "C" const char*
LLVMRustArchiveChildData(Archive::Child *child, size_t *size) {
StringRef buf = child->getBuffer();
StringRef buf;
#if LLVM_VERSION_MINOR >= 7
ErrorOr<StringRef> buf_or_err = child->getBuffer();
if (buf_or_err.getError()) {
LLVMRustSetLastError(buf_or_err.getError().message().c_str());
return NULL;
}
buf = buf_or_err.get();
#else
buf = child->getBuffer();
#endif
*size = buf.size();
return buf.data();
}
@ -144,7 +154,8 @@ extern "C" int
LLVMRustWriteArchive(char *Dst,
size_t NumMembers,
const LLVMRustArchiveMember **NewMembers,
bool WriteSymbtab) {
bool WriteSymbtab,
Archive::Kind Kind) {
#if LLVM_VERSION_MINOR >= 7
std::vector<NewArchiveIterator> Members;
@ -157,7 +168,7 @@ LLVMRustWriteArchive(char *Dst,
Members.push_back(NewArchiveIterator(Member->child, Member->name));
}
}
auto pair = writeArchive(Dst, Members, WriteSymbtab);
auto pair = writeArchive(Dst, Members, WriteSymbtab, Kind, false);
if (!pair.second)
return 0;
LLVMRustSetLastError(pair.second.message().c_str());