link: switch from tar to ar for .rlibs.

This commit is contained in:
Eduard-Mihai Burtescu 2021-08-13 10:49:42 +03:00 committed by Eduard-Mihai Burtescu
parent 5a431e65a1
commit 731a5e86aa
4 changed files with 52 additions and 31 deletions

8
Cargo.lock generated
View File

@ -77,6 +77,12 @@ version = "1.0.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486"
[[package]]
name = "ar"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "450575f58f7bee32816abbff470cbc47797397c2a81e0eaced4b98436daf52e1"
[[package]]
name = "arrayvec"
version = "0.5.2"
@ -2234,6 +2240,7 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
name = "rustc_codegen_spirv"
version = "0.4.0-alpha.12"
dependencies = [
"ar",
"bimap",
"hashbrown 0.11.2",
"indexmap",
@ -2249,7 +2256,6 @@ dependencies = [
"smallvec",
"spirv-tools",
"syn",
"tar",
"tempfile",
"topological-sort",
]

View File

@ -35,6 +35,7 @@ num-traits = { version = "0.2", features = ["libm"] }
syn = { version = "1", features = ["visit", "visit-mut"] }
# Normal dependencies.
ar = "0.8.0"
bimap = "0.6"
indexmap = "1.6.0"
rspirv = { git = "https://github.com/gfx-rs/rspirv.git", rev = "c2a11ba7961fa7c675800f50c1903f0e96c633f8" }
@ -44,7 +45,6 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
smallvec = "1.6.1"
spirv-tools = { version = "0.6.1", default-features = false }
tar = "0.4.30"
topological-sort = "0.1"
[dev-dependencies]

View File

@ -2,6 +2,7 @@ use crate::codegen_cx::{CodegenArgs, ModuleOutputType};
use crate::{
linker, CompileResult, ModuleResult, SpirvCodegenBackend, SpirvModuleBuffer, SpirvThinBuffer,
};
use ar::{Archive, GnuBuilder, Header};
use rspirv::binary::Assemble;
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
use rustc_codegen_ssa::back::write::CodegenContext;
@ -19,12 +20,12 @@ use rustc_session::output::{check_file_is_writeable, invalid_output_for_target,
use rustc_session::utils::NativeLibKind;
use rustc_session::Session;
use std::env;
use std::ffi::{CString, OsStr};
use std::ffi::CString;
use std::fs::File;
use std::io::{BufWriter, Read};
use std::iter;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use tar::{Archive, Builder, Header};
pub fn link<'a>(
sess: &'a Session,
@ -439,25 +440,42 @@ fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
}
fn create_archive(files: &[&Path], metadata: &[u8], out_filename: &Path) {
let file = File::create(out_filename).unwrap();
let mut builder = Builder::new(file);
{
let mut header = Header::new_gnu();
header.set_path(METADATA_FILENAME).unwrap();
header.set_size(metadata.len() as u64);
header.set_cksum();
builder.append(&header, metadata).unwrap();
}
let files_with_names = files.iter().map(|file| {
(
file,
file.file_name()
.unwrap()
.to_str()
.expect("archive file names should be valid ASCII/UTF-8"),
)
});
let out_file = File::create(out_filename).unwrap();
let mut builder = GnuBuilder::new(
out_file,
iter::once(METADATA_FILENAME)
.chain(files_with_names.clone().map(|(_, name)| name))
.map(|name| name.as_bytes().to_vec())
.collect(),
);
builder
.append(
&Header::new(METADATA_FILENAME.as_bytes().to_vec(), metadata.len() as u64),
metadata,
)
.unwrap();
let mut filenames = FxHashSet::default();
filenames.insert(OsStr::new(METADATA_FILENAME));
for file in files {
filenames.insert(METADATA_FILENAME);
for (file, name) in files_with_names {
assert!(
filenames.insert(file.file_name().unwrap()),
filenames.insert(name),
"Duplicate filename in archive: {:?}",
file.file_name().unwrap()
);
// NOTE(eddyb) this could just be `builder.append_path(file)`, but we
// have to work around https://github.com/mdsteele/rust-ar/issues/19.
builder
.append_path_with_name(file, file.file_name().unwrap())
.append_file(name.as_bytes(), &mut File::open(file).unwrap())
.unwrap();
}
builder.into_inner().unwrap();
@ -465,9 +483,10 @@ fn create_archive(files: &[&Path], metadata: &[u8], out_filename: &Path) {
pub fn read_metadata(rlib: &Path) -> Result<MetadataRef, String> {
fn read_metadata_internal(rlib: &Path) -> Result<Option<MetadataRef>, std::io::Error> {
for entry in Archive::new(File::open(rlib)?).entries()? {
let mut archive = Archive::new(File::open(rlib).unwrap());
while let Some(entry) = archive.next_entry() {
let mut entry = entry?;
if entry.path()? == Path::new(METADATA_FILENAME) {
if entry.header().identifier() == METADATA_FILENAME.as_bytes() {
let mut bytes = Vec::new();
entry.read_to_end(&mut bytes)?;
let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(bytes);
@ -507,12 +526,13 @@ fn do_link(
// `rlibs` are archive files we've created in `create_archive`, usually produced by crates that are being
// referenced. We need to unpack them and add the modules inside.
for rlib in rlibs {
for entry in Archive::new(File::open(rlib).unwrap()).entries().unwrap() {
let mut archive = Archive::new(File::open(rlib).unwrap());
while let Some(entry) = archive.next_entry() {
let mut entry = entry.unwrap();
if entry.path().unwrap() != Path::new(METADATA_FILENAME) {
if entry.header().identifier() != METADATA_FILENAME.as_bytes() {
// std::fs::read adds 1 to the size, so do the same here - see comment:
// https://github.com/rust-lang/rust/blob/72868e017bdade60603a25889e253f556305f996/library/std/src/fs.rs#L200-L202
let mut bytes = Vec::with_capacity(entry.size() as usize + 1);
let mut bytes = Vec::with_capacity(entry.header().size() as usize + 1);
entry.read_to_end(&mut bytes).unwrap();
modules.push(load(&bytes));
}

View File

@ -6,12 +6,7 @@ vulnerability = "deny"
unmaintained = "warn"
yanked = "warn"
notice = "warn"
ignore = [
# The tar crate allows creating directories outside dst when unpacking.
# Safe to ignore: we both create/control all input tar files, and we do not unpack them.
# https://github.com/alexcrichton/tar-rs/issues/238
"RUSTSEC-2021-0080",
]
ignore = []
# This section is considered when running `cargo deny check bans`.
# More documentation about the 'bans' section can be found here:
@ -32,8 +27,8 @@ deny = [
skip = [
#{ name = "ansi_term", version = "=0.11.0" },
]
# Similarly to `skip` allows you to skip certain crates during duplicate
# detection. Unlike skip, it also includes the entire tree of transitive
# Similarly to `skip` allows you to skip certain crates during duplicate
# detection. Unlike skip, it also includes the entire tree of transitive
# dependencies starting at the specified crate, up to a certain depth, which is
# by default infinite
skip-tree = [
@ -60,7 +55,7 @@ allow = [
"BSD-2-Clause",
"BSD-3-Clause",
"ISC",
"Zlib",
]
# Allow 1 or more licenses on a per-crate basis, so that particular licenses