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

Wrap bundled static libraries into object files #104091

Merged
merged 1 commit into from
Nov 15, 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
6 changes: 6 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ use rustc_session::cstore::DllImport;
use rustc_session::Session;
use rustc_span::symbol::Symbol;

use super::metadata::search_for_section;

use object::read::archive::ArchiveFile;

use std::error::Error;
use std::fs::File;
use std::io;
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -56,6 +59,9 @@ pub trait ArchiveBuilderBuilder {
if !bundled_lib_file_names.contains(&Symbol::intern(name)) {
continue; // We need to extract only native libraries.
}
let data = search_for_section(rlib, data, ".bundled_lib").map_err(|e| {
ExtractBundledLibsError::ExtractSection { rlib, error: Box::<dyn Error>::from(e) }
petrochenkov marked this conversation as resolved.
Show resolved Hide resolved
})?;
std::fs::write(&outdir.join(&name), data)
.map_err(|e| ExtractBundledLibsError::WriteFile { rlib, error: Box::new(e) })?;
}
Expand Down
22 changes: 14 additions & 8 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc_errors::{ErrorGuaranteed, Handler};
use rustc_fs_util::fix_windows_verbatim_for_gcc;
use rustc_hir::def_id::CrateNum;
use rustc_metadata::find_native_static_library;
use rustc_metadata::fs::{emit_metadata, METADATA_FILENAME};
use rustc_metadata::fs::{emit_wrapper_file, METADATA_FILENAME};
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols::SymbolExportKind;
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Lto, Strip};
Expand All @@ -29,7 +29,7 @@ use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, T
use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
use super::command::Command;
use super::linker::{self, Linker};
use super::metadata::{create_rmeta_file, MetadataPosition};
use super::metadata::{create_wrapper_file, MetadataPosition};
use super::rpath::{self, RPathConfig};
use crate::{
errors, looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo, NativeLib,
Expand All @@ -44,7 +44,7 @@ use std::borrow::Borrow;
use std::cell::OnceCell;
use std::collections::BTreeSet;
use std::ffi::OsString;
use std::fs::{File, OpenOptions};
use std::fs::{read, File, OpenOptions};
use std::io::{BufWriter, Write};
petrochenkov marked this conversation as resolved.
Show resolved Hide resolved
use std::ops::Deref;
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -292,8 +292,8 @@ fn link_rlib<'a>(
let trailing_metadata = match flavor {
RlibFlavor::Normal => {
let (metadata, metadata_position) =
create_rmeta_file(sess, codegen_results.metadata.raw_data());
let metadata = emit_metadata(sess, &metadata, tmpdir);
create_wrapper_file(sess, b".rmeta".to_vec(), codegen_results.metadata.raw_data());
let metadata = emit_wrapper_file(sess, &metadata, tmpdir, METADATA_FILENAME);
match metadata_position {
MetadataPosition::First => {
// Most of the time metadata in rlib files is wrapped in a "dummy" object
Expand Down Expand Up @@ -376,12 +376,18 @@ fn link_rlib<'a>(
let location =
find_native_static_library(name.as_str(), lib.verbatim, &lib_search_paths, sess);
if sess.opts.unstable_opts.packed_bundled_libs && flavor == RlibFlavor::Normal {
packed_bundled_libs.push(find_native_static_library(
lib.filename.unwrap().as_str(),
let filename = lib.filename.unwrap();
let lib_path = find_native_static_library(
filename.as_str(),
Some(true),
&lib_search_paths,
sess,
));
);
let src = read(lib_path)
.map_err(|e| sess.emit_fatal(errors::ReadFileError { message: e }))?;
let (data, _) = create_wrapper_file(sess, b".bundled_lib".to_vec(), &src);
let wrapper_file = emit_wrapper_file(sess, &data, tmpdir, filename.as_str());
packed_bundled_libs.push(wrapper_file);
continue;
}
ab.add_archive(&location, Box::new(|_| false)).unwrap_or_else(|error| {
Expand Down
18 changes: 11 additions & 7 deletions compiler/rustc_codegen_ssa/src/back/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl MetadataLoader for DefaultMetadataLoader {
let data = entry
.data(data)
.map_err(|e| format!("failed to parse rlib '{}': {}", path.display(), e))?;
return search_for_metadata(path, data, ".rmeta");
return search_for_section(path, data, ".rmeta");
}
}

Expand All @@ -69,11 +69,11 @@ impl MetadataLoader for DefaultMetadataLoader {
}

fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> {
load_metadata_with(path, |data| search_for_metadata(path, data, ".rustc"))
load_metadata_with(path, |data| search_for_section(path, data, ".rustc"))
}
}

fn search_for_metadata<'a>(
pub(super) fn search_for_section<'a>(
path: &Path,
bytes: &'a [u8],
section: &str,
Expand Down Expand Up @@ -223,7 +223,11 @@ pub enum MetadataPosition {
// * ELF - All other targets are similar to Windows in that there's a
// `SHF_EXCLUDE` flag we can set on sections in an object file to get
// automatically removed from the final output.
pub fn create_rmeta_file(sess: &Session, metadata: &[u8]) -> (Vec<u8>, MetadataPosition) {
pub fn create_wrapper_file(
sess: &Session,
section_name: Vec<u8>,
data: &[u8],
) -> (Vec<u8>, MetadataPosition) {
let Some(mut file) = create_object_file(sess) else {
// This is used to handle all "other" targets. This includes targets
// in two categories:
Expand All @@ -241,11 +245,11 @@ pub fn create_rmeta_file(sess: &Session, metadata: &[u8]) -> (Vec<u8>, MetadataP
// WebAssembly and for targets not supported by the `object` crate
// yet it means that work will need to be done in the `object` crate
// to add a case above.
return (metadata.to_vec(), MetadataPosition::Last);
return (data.to_vec(), MetadataPosition::Last);
};
let section = file.add_section(
file.segment_name(StandardSegment::Debug).to_vec(),
b".rmeta".to_vec(),
section_name,
SectionKind::Debug,
);
match file.format() {
Expand All @@ -259,7 +263,7 @@ pub fn create_rmeta_file(sess: &Session, metadata: &[u8]) -> (Vec<u8>, MetadataP
}
_ => {}
};
file.append_section_data(section, metadata, 1);
file.append_section_data(section, data, 1);
(file.write().unwrap(), MetadataPosition::First)
}

Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_codegen_ssa/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,9 @@ pub enum ExtractBundledLibsError<'a> {

#[diag(codegen_ssa_extract_bundled_libs_write_file)]
WriteFile { rlib: &'a Path, error: Box<dyn std::error::Error> },

#[diag(codegen_ssa_extract_bundled_libs_write_file)]
ExtractSection { rlib: &'a Path, error: Box<dyn std::error::Error> },
}

#[derive(Diagnostic)]
Expand All @@ -521,3 +524,9 @@ pub enum AppleSdkRootError<'a> {
#[diag(codegen_ssa_apple_sdk_error_sdk_path)]
SdkPath { sdk_name: &'a str, error: Error },
}

#[derive(Diagnostic)]
#[diag(codegen_ssa_read_file)]
pub struct ReadFileError {
pub message: std::io::Error,
}
2 changes: 2 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,5 @@ codegen_ssa_extract_bundled_libs_write_file = failed to write file '{$rlib}': {$
codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}`

codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {error}

codegen_ssa_read_file = failed to read file: {message}
11 changes: 8 additions & 3 deletions compiler/rustc_metadata/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@ pub const METADATA_FILENAME: &str = "lib.rmeta";
/// building an `.rlib` (stomping over one another), or writing an `.rmeta` into a
/// directory being searched for `extern crate` (observing an incomplete file).
/// The returned path is the temporary file containing the complete metadata.
pub fn emit_metadata(sess: &Session, metadata: &[u8], tmpdir: &MaybeTempDir) -> PathBuf {
let out_filename = tmpdir.as_ref().join(METADATA_FILENAME);
let result = fs::write(&out_filename, metadata);
pub fn emit_wrapper_file(
sess: &Session,
data: &[u8],
tmpdir: &MaybeTempDir,
name: &str,
) -> PathBuf {
let out_filename = tmpdir.as_ref().join(name);
let result = fs::write(&out_filename, data);

if let Err(err) = result {
sess.emit_fatal(FailedWriteError { filename: out_filename, err });
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ pub mod errors;
pub mod fs;
pub mod locator;

pub use fs::{emit_metadata, METADATA_FILENAME};
pub use fs::{emit_wrapper_file, METADATA_FILENAME};
pub use native_libs::find_native_static_library;
pub use rmeta::{encode_metadata, EncodedMetadata, METADATA_HEADER};