Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove the source archive functionality of ArchiveWriter #98098

Merged
merged 5 commits into from
Jun 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 8 additions & 35 deletions compiler/rustc_codegen_cranelift/src/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,50 +30,19 @@ pub(crate) struct ArArchiveBuilder<'a> {
}

impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> Self {
let (src_archives, entries) = if let Some(input) = input {
let read_cache = ReadCache::new(File::open(input).unwrap());
let archive = ArchiveFile::parse(&read_cache).unwrap();
let mut entries = Vec::new();

for entry in archive.members() {
let entry = entry.unwrap();
entries.push((
entry.name().to_vec(),
ArchiveEntry::FromArchive { archive_index: 0, file_range: entry.file_range() },
));
}

(vec![read_cache.into_inner()], entries)
} else {
(vec![], Vec::new())
};

fn new(sess: &'a Session, output: &Path) -> Self {
ArArchiveBuilder {
sess,
dst: output.to_path_buf(),
use_gnu_style_archive: sess.target.archive_format == "gnu",
// FIXME fix builtin ranlib on macOS
no_builtin_ranlib: sess.target.is_like_osx,

src_archives,
entries,
src_archives: vec![],
entries: vec![],
}
}

fn src_files(&mut self) -> Vec<String> {
self.entries.iter().map(|(name, _)| String::from_utf8(name.clone()).unwrap()).collect()
}

fn remove_file(&mut self, name: &str) {
let index = self
.entries
.iter()
.position(|(entry_name, _)| entry_name == name.as_bytes())
.expect("Tried to remove file not existing in src archive");
self.entries.remove(index);
}

fn add_file(&mut self, file: &Path) {
self.entries.push((
file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(),
Expand Down Expand Up @@ -105,7 +74,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
Ok(())
}

fn build(mut self) {
fn build(mut self) -> bool {
enum BuilderKind {
Bsd(ar::Builder<File>),
Gnu(ar::GnuBuilder<File>),
Expand Down Expand Up @@ -204,6 +173,8 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
)
};

let any_members = !entries.is_empty();

// Add all files
for (entry_name, data) in entries.into_iter() {
let header = ar::Header::new(entry_name, data.len() as u64);
Expand All @@ -229,6 +200,8 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
self.sess.fatal(&format!("Ranlib exited with code {:?}", status.code()));
}
}

any_members
}

fn inject_dll_import_lib(
Expand Down
47 changes: 8 additions & 39 deletions compiler/rustc_codegen_gcc/src/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub struct ArArchiveBuilder<'a> {
}

impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> Self {
fn new(sess: &'a Session, output: &Path) -> Self {
let config = ArchiveConfig {
sess,
dst: output.to_path_buf(),
Expand All @@ -41,48 +41,13 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
use_gnu_style_archive: sess.target.options.archive_format == "gnu",
};

let (src_archives, entries) = if let Some(input) = input {
let mut archive = ar::Archive::new(File::open(input).unwrap());
let mut entries = Vec::new();

let mut i = 0;
while let Some(entry) = archive.next_entry() {
let entry = entry.unwrap();
entries.push((
String::from_utf8(entry.header().identifier().to_vec()).unwrap(),
ArchiveEntry::FromArchive {
archive_index: 0,
entry_index: i,
},
));
i += 1;
}

(vec![(input.to_owned(), archive)], entries)
} else {
(vec![], Vec::new())
};

ArArchiveBuilder {
config,
src_archives,
entries,
src_archives: vec![],
entries: vec![],
}
}

fn src_files(&mut self) -> Vec<String> {
self.entries.iter().map(|(name, _)| name.clone()).collect()
}

fn remove_file(&mut self, name: &str) {
let index = self
.entries
.iter()
.position(|(entry_name, _)| entry_name == name)
.expect("Tried to remove file not existing in src archive");
self.entries.remove(index);
}

fn add_file(&mut self, file: &Path) {
self.entries.push((
file.file_name().unwrap().to_str().unwrap().to_string(),
Expand Down Expand Up @@ -113,7 +78,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
Ok(())
}

fn build(mut self) {
fn build(mut self) -> bool {
use std::process::Command;

fn add_file_using_ar(archive: &Path, file: &Path) {
Expand Down Expand Up @@ -146,6 +111,8 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
BuilderKind::Bsd(ar::Builder::new(File::create(&self.config.dst).unwrap()))
};

let any_members = !self.entries.is_empty();

// Add all files
for (entry_name, entry) in self.entries.into_iter() {
match entry {
Expand Down Expand Up @@ -206,6 +173,8 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
if !status.success() {
self.config.sess.fatal(&format!("Ranlib exited with code {:?}", status.code()));
}

any_members
}

fn inject_dll_import_lib(&mut self, _lib_name: &str, _dll_imports: &[DllImport], _tmpdir: &MaybeTempDir) {
Expand Down
120 changes: 25 additions & 95 deletions compiler/rustc_codegen_llvm/src/back/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,12 @@ use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_session::cstore::{DllCallingConvention, DllImport};
use rustc_session::Session;

struct ArchiveConfig<'a> {
pub sess: &'a Session,
pub dst: PathBuf,
pub src: Option<PathBuf>,
}

/// Helper for adding many files to an archive.
#[must_use = "must call build() to finish building the archive"]
pub struct LlvmArchiveBuilder<'a> {
config: ArchiveConfig<'a>,
removals: Vec<String>,
sess: &'a Session,
dst: PathBuf,
additions: Vec<Addition>,
src_archive: Option<Option<ArchiveRO>>,
}

enum Addition {
Expand All @@ -50,10 +43,6 @@ fn is_relevant_child(c: &Child<'_>) -> bool {
}
}

fn archive_config<'a>(sess: &'a Session, output: &Path, input: Option<&Path>) -> ArchiveConfig<'a> {
ArchiveConfig { sess, dst: output.to_path_buf(), src: input.map(|p| p.to_path_buf()) }
}

/// Map machine type strings to values of LLVM's MachineTypes enum.
fn llvm_machine_type(cpu: &str) -> LLVMMachineType {
match cpu {
Expand All @@ -68,37 +57,8 @@ fn llvm_machine_type(cpu: &str) -> LLVMMachineType {
impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
/// Creates a new static archive, ready for modifying the archive specified
/// by `config`.
fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> LlvmArchiveBuilder<'a> {
let config = archive_config(sess, output, input);
LlvmArchiveBuilder {
config,
removals: Vec::new(),
additions: Vec::new(),
src_archive: None,
}
}

/// Removes a file from this archive
fn remove_file(&mut self, file: &str) {
self.removals.push(file.to_string());
}

/// Lists all files in an archive
fn src_files(&mut self) -> Vec<String> {
if self.src_archive().is_none() {
return Vec::new();
}

let archive = self.src_archive.as_ref().unwrap().as_ref().unwrap();

archive
.iter()
.filter_map(|child| child.ok())
.filter(is_relevant_child)
.filter_map(|child| child.name())
.filter(|name| !self.removals.iter().any(|x| x == name))
.map(|name| name.to_owned())
.collect()
fn new(sess: &'a Session, output: &Path) -> LlvmArchiveBuilder<'a> {
LlvmArchiveBuilder { sess, dst: output.to_path_buf(), additions: Vec::new() }
}

fn add_archive<F>(&mut self, archive: &Path, skip: F) -> io::Result<()>
Expand Down Expand Up @@ -129,13 +89,10 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {

/// Combine the provided files, rlibs, and native libraries into a single
/// `Archive`.
fn build(mut self) {
let kind = self.llvm_archive_kind().unwrap_or_else(|kind| {
self.config.sess.fatal(&format!("Don't know how to build archive of type: {}", kind))
});

if let Err(e) = self.build_with_llvm(kind) {
self.config.sess.fatal(&format!("failed to build archive: {}", e));
fn build(mut self) -> bool {
match self.build_with_llvm() {
Ok(any_members) => any_members,
Err(e) => self.sess.fatal(&format!("failed to build archive: {}", e)),
}
}

Expand All @@ -151,7 +108,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
output_path.with_extension("lib")
};

let target = &self.config.sess.target;
let target = &self.sess.target;
let mingw_gnu_toolchain = target.vendor == "pc"
&& target.os == "windows"
&& target.env == "gnu"
Expand All @@ -160,7 +117,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = dll_imports
.iter()
.map(|import: &DllImport| {
if self.config.sess.target.arch == "x86" {
if self.sess.target.arch == "x86" {
(
LlvmArchiveBuilder::i686_decorated_name(import, mingw_gnu_toolchain),
import.ordinal,
Expand Down Expand Up @@ -197,11 +154,11 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
match std::fs::write(&def_file_path, def_file_content) {
Ok(_) => {}
Err(e) => {
self.config.sess.fatal(&format!("Error writing .DEF file: {}", e));
self.sess.fatal(&format!("Error writing .DEF file: {}", e));
}
};

let dlltool = find_binutils_dlltool(self.config.sess);
let dlltool = find_binutils_dlltool(self.sess);
let result = std::process::Command::new(dlltool)
.args([
"-d",
Expand All @@ -215,9 +172,9 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {

match result {
Err(e) => {
self.config.sess.fatal(&format!("Error calling dlltool: {}", e));
self.sess.fatal(&format!("Error calling dlltool: {}", e));
}
Ok(output) if !output.status.success() => self.config.sess.fatal(&format!(
Ok(output) if !output.status.success() => self.sess.fatal(&format!(
"Dlltool could not create import library: {}\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
Expand Down Expand Up @@ -263,13 +220,13 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
output_path_z.as_ptr(),
ffi_exports.as_ptr(),
ffi_exports.len(),
llvm_machine_type(&self.config.sess.target.arch) as u16,
!self.config.sess.target.is_like_msvc,
llvm_machine_type(&self.sess.target.arch) as u16,
!self.sess.target.is_like_msvc,
)
};

if result == crate::llvm::LLVMRustResult::Failure {
self.config.sess.fatal(&format!(
self.sess.fatal(&format!(
"Error creating import library for {}: {}",
lib_name,
llvm::last_error().unwrap_or("unknown LLVM error".to_string())
Expand All @@ -278,7 +235,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
};

self.add_archive(&output_path, |_| false).unwrap_or_else(|e| {
self.config.sess.fatal(&format!(
self.sess.fatal(&format!(
"failed to add native library {}: {}",
output_path.display(),
e
Expand All @@ -288,46 +245,19 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
}

impl<'a> LlvmArchiveBuilder<'a> {
fn src_archive(&mut self) -> Option<&ArchiveRO> {
if let Some(ref a) = self.src_archive {
return a.as_ref();
}
let src = self.config.src.as_ref()?;
self.src_archive = Some(ArchiveRO::open(src).ok());
self.src_archive.as_ref().unwrap().as_ref()
}

fn llvm_archive_kind(&self) -> Result<ArchiveKind, &str> {
let kind = &*self.config.sess.target.archive_format;
kind.parse().map_err(|_| kind)
}
fn build_with_llvm(&mut self) -> io::Result<bool> {
let kind = &*self.sess.target.archive_format;
let kind = kind.parse::<ArchiveKind>().map_err(|_| kind).unwrap_or_else(|kind| {
self.sess.fatal(&format!("Don't know how to build archive of type: {}", kind))
});

fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> {
let removals = mem::take(&mut self.removals);
let mut additions = mem::take(&mut self.additions);
let mut strings = Vec::new();
let mut members = Vec::new();

let dst = CString::new(self.config.dst.to_str().unwrap())?;
let dst = CString::new(self.dst.to_str().unwrap())?;

unsafe {
if let Some(archive) = self.src_archive() {
for child in archive.iter() {
let child = child.map_err(string_to_io_error)?;
let Some(child_name) = child.name() else { continue };
if removals.iter().any(|r| r == child_name) {
continue;
}

let name = CString::new(child_name)?;
members.push(llvm::LLVMRustArchiveMemberNew(
ptr::null(),
name.as_ptr(),
Some(child.raw),
));
strings.push(name);
}
}
for addition in &mut additions {
match addition {
Addition::File { path, name_in_archive } => {
Expand Down Expand Up @@ -389,7 +319,7 @@ impl<'a> LlvmArchiveBuilder<'a> {
};
Err(io::Error::new(io::ErrorKind::Other, msg))
} else {
Ok(())
Ok(!members.is_empty())
};
for member in members {
llvm::LLVMRustArchiveMemberFree(member);
Expand Down
Loading