diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 18789d00fd3a4..2b1b06d1644c9 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -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}; @@ -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::::from(e) } + })?; std::fs::write(&outdir.join(&name), data) .map_err(|e| ExtractBundledLibsError::WriteFile { rlib, error: Box::new(e) })?; } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 2bd9023395dbd..4445e5f6c3a64 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -8,7 +8,7 @@ use rustc_errors::{ErrorGuaranteed, Handler}; use rustc_fs_util::fix_windows_verbatim_for_gcc; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; 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}; @@ -29,7 +29,7 @@ use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo}; 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, @@ -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}; use std::ops::Deref; use std::path::{Path, PathBuf}; @@ -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 @@ -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| { diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 99ddd1764785d..780a385003681 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -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"); } } @@ -69,11 +69,11 @@ impl MetadataLoader for DefaultMetadataLoader { } fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result { - 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, @@ -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, MetadataPosition) { +pub fn create_wrapper_file( + sess: &Session, + section_name: Vec, + data: &[u8], +) -> (Vec, MetadataPosition) { let Some(mut file) = create_object_file(sess) else { // This is used to handle all "other" targets. This includes targets // in two categories: @@ -241,11 +245,11 @@ pub fn create_rmeta_file(sess: &Session, metadata: &[u8]) -> (Vec, 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() { @@ -259,7 +263,7 @@ pub fn create_rmeta_file(sess: &Session, metadata: &[u8]) -> (Vec, MetadataP } _ => {} }; - file.append_section_data(section, metadata, 1); + file.append_section_data(section, data, 1); (file.write().unwrap(), MetadataPosition::First) } diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 36c94462b0b3e..bfc4515de0984 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -507,6 +507,9 @@ pub enum ExtractBundledLibsError<'a> { #[diag(codegen_ssa_extract_bundled_libs_write_file)] WriteFile { rlib: &'a Path, error: Box }, + + #[diag(codegen_ssa_extract_bundled_libs_write_file)] + ExtractSection { rlib: &'a Path, error: Box }, } #[derive(Diagnostic)] @@ -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, +} diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index ad0d758210175..eb6b403d00e88 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -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} diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index f360a586476e7..c41ae8d55cdad 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -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 }); diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 98cf6fef54a8f..1987f88e6b8cc 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -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};