Skip to content

Commit 4dca28c

Browse files
committed
Store only a metadata stub into rlibs and dylibs with -Zembed-metadata=no
1 parent a5057b7 commit 4dca28c

5 files changed

Lines changed: 101 additions & 28 deletions

File tree

‎compiler/rustc_codegen_ssa/src/back/link.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ fn link_rlib<'a>(
294294
let(metadata, metadata_position) = create_wrapper_file(
295295
sess,
296296
".rmeta".to_string(),
297-
codegen_results.metadata.raw_data(),
297+
codegen_results.metadata.stub_or_full(),
298298
);
299299
let metadata = emit_wrapper_file(sess,&metadata, tmpdir,METADATA_FILENAME);
300300
match metadata_position {

‎compiler/rustc_codegen_ssa/src/back/metadata.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -540,8 +540,8 @@ pub fn create_compressed_metadata_file(
540540
symbol_name:&str,
541541
) -> Vec<u8>{
542542
letmut packed_metadata = rustc_metadata::METADATA_HEADER.to_vec();
543-
packed_metadata.write_all(&(metadata.raw_data().len()asu64).to_le_bytes()).unwrap();
544-
packed_metadata.extend(metadata.raw_data());
543+
packed_metadata.write_all(&(metadata.stub_or_full().len()asu64).to_le_bytes()).unwrap();
544+
packed_metadata.extend(metadata.stub_or_full());
545545

546546
letSome(mut file) = create_object_file(sess)else{
547547
if sess.target.is_like_wasm{

‎compiler/rustc_metadata/src/fs.rs‎

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::{fs, io};
33

44
use rustc_data_structures::temp_dir::MaybeTempDir;
55
use rustc_middle::ty::TyCtxt;
6-
use rustc_session::config::{OutFileName,OutputType};
6+
use rustc_session::config::{CrateType,OutFileName,OutputType};
77
use rustc_session::output::filename_for_metadata;
88
use rustc_session::{MetadataKind,Session};
99
use tempfile::BuilderasTempFileBuilder;
@@ -50,7 +50,14 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
5050
.tempdir_in(out_filename.parent().unwrap_or_else(|| Path::new("")))
5151
.unwrap_or_else(|err| tcx.dcx().emit_fatal(FailedCreateTempdir{ err }));
5252
let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps);
53-
let metadata_filename = metadata_tmpdir.as_ref().join(METADATA_FILENAME);
53+
let metadata_filename = metadata_tmpdir.as_ref().join("full.rmeta");
54+
let metadata_stub_filename = if !tcx.sess.opts.unstable_opts.embed_metadata
55+
&& !tcx.crate_types().contains(&CrateType::ProcMacro)
56+
{
57+
Some(metadata_tmpdir.as_ref().join("stub.rmeta"))
58+
}else{
59+
None
60+
};
5461

5562
// Always create a file at `metadata_filename`, even if we have nothing to write to it.
5663
// This simplifies the creation of the output `out_filename` when requested.
@@ -60,9 +67,15 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
6067
std::fs::File::create(&metadata_filename).unwrap_or_else(|err| {
6168
tcx.dcx().emit_fatal(FailedCreateFile{filename:&metadata_filename, err });
6269
});
70+
ifletSome(metadata_stub_filename) = &metadata_stub_filename {
71+
std::fs::File::create(metadata_stub_filename).unwrap_or_else(|err| {
72+
tcx.dcx()
73+
.emit_fatal(FailedCreateFile{filename:&metadata_stub_filename, err });
74+
});
75+
}
6376
}
6477
MetadataKind::Uncompressed | MetadataKind::Compressed => {
65-
encode_metadata(tcx,&metadata_filename);
78+
encode_metadata(tcx,&metadata_filename, metadata_stub_filename.as_deref())
6679
}
6780
};
6881

@@ -100,9 +113,10 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
100113

101114
// Load metadata back to memory: codegen may need to include it in object files.
102115
let metadata =
103-
EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|err| {
104-
tcx.dcx().emit_fatal(FailedCreateEncodedMetadata{ err });
105-
});
116+
EncodedMetadata::from_path(metadata_filename, metadata_stub_filename, metadata_tmpdir)
117+
.unwrap_or_else(|err| {
118+
tcx.dcx().emit_fatal(FailedCreateEncodedMetadata{ err });
119+
});
106120

107121
let need_metadata_module = metadata_kind == MetadataKind::Compressed;
108122

‎compiler/rustc_metadata/src/rmeta/encoder.rs‎

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
701701
triple: tcx.sess.opts.target_triple.clone(),
702702
hash: tcx.crate_hash(LOCAL_CRATE),
703703
is_proc_macro_crate: proc_macro_data.is_some(),
704+
is_stub:false,
704705
},
705706
extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
706707
stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
@@ -2231,54 +2232,75 @@ fn prefetch_mir(tcx: TyCtxt<'_>) {
22312232
// generated regardless of trailing bytes that end up in it.
22322233

22332234
pubstructEncodedMetadata{
2234-
// The declaration order matters because `mmap` should be dropped before `_temp_dir`.
2235-
mmap:Option<Mmap>,
2235+
// The declaration order matters because `full_metadata` should be dropped
2236+
// before `_temp_dir`.
2237+
full_metadata:Option<Mmap>,
2238+
// This is an optional stub metadata containing only the crate header.
2239+
// The header should be very small, so we load it directly into memory.
2240+
stub_metadata:Option<Vec<u8>>,
22362241
// We need to carry MaybeTempDir to avoid deleting the temporary
22372242
// directory while accessing the Mmap.
22382243
_temp_dir:Option<MaybeTempDir>,
22392244
}
22402245

22412246
implEncodedMetadata{
22422247
#[inline]
2243-
pubfnfrom_path(path:PathBuf,temp_dir:Option<MaybeTempDir>) -> std::io::Result<Self>{
2248+
pubfnfrom_path(
2249+
path:PathBuf,
2250+
stub_path:Option<PathBuf>,
2251+
temp_dir:Option<MaybeTempDir>,
2252+
) -> std::io::Result<Self>{
22442253
let file = std::fs::File::open(&path)?;
22452254
let file_metadata = file.metadata()?;
22462255
if file_metadata.len() == 0{
2247-
returnOk(Self{mmap:None,_temp_dir:None});
2256+
returnOk(Self{full_metadata:None,stub_metadata:None,_temp_dir:None});
22482257
}
2249-
let mmap = unsafe{Some(Mmap::map(file)?)};
2250-
Ok(Self{ mmap,_temp_dir: temp_dir })
2258+
let full_mmap = unsafe{Some(Mmap::map(file)?)};
2259+
2260+
let stub =
2261+
ifletSome(stub_path) = stub_path {Some(std::fs::read(stub_path)?)}else{None};
2262+
2263+
Ok(Self{full_metadata: full_mmap,stub_metadata: stub,_temp_dir: temp_dir })
2264+
}
2265+
2266+
#[inline]
2267+
pubfnfull(&self) -> &[u8]{
2268+
&self.full_metadata.as_deref().unwrap_or_default()
22512269
}
22522270

22532271
#[inline]
2254-
pubfnraw_data(&self) -> &[u8]{
2255-
self.mmap.as_deref().unwrap_or_default()
2272+
pubfnstub_or_full(&self) -> &[u8]{
2273+
self.stub_metadata.as_deref().unwrap_or(self.full())
22562274
}
22572275
}
22582276

22592277
impl<S:Encoder>Encodable<S>forEncodedMetadata{
22602278
fnencode(&self,s:&mutS){
2261-
let slice = self.raw_data();
2279+
self.stub_metadata.encode(s);
2280+
2281+
let slice = self.full();
22622282
slice.encode(s)
22632283
}
22642284
}
22652285

22662286
impl<D:Decoder>Decodable<D>forEncodedMetadata{
22672287
fndecode(d:&mutD) -> Self{
2288+
let stub = <Option<Vec<u8>>>::decode(d);
2289+
22682290
let len = d.read_usize();
2269-
letmmap = if len > 0{
2291+
letfull_metadata = if len > 0{
22702292
letmut mmap = MmapMut::map_anon(len).unwrap();
22712293
mmap.copy_from_slice(d.read_raw_bytes(len));
22722294
Some(mmap.make_read_only().unwrap())
22732295
}else{
22742296
None
22752297
};
22762298

2277-
Self{mmap,_temp_dir:None}
2299+
Self{full_metadata,stub_metadata: stub,_temp_dir:None}
22782300
}
22792301
}
22802302

2281-
pubfnencode_metadata(tcx:TyCtxt<'_>,path:&Path){
2303+
pubfnencode_metadata(tcx:TyCtxt<'_>,path:&Path,ref_path:Option<&Path>){
22822304
let _prof_timer = tcx.prof.verbose_generic_activity("generate_crate_metadata");
22832305

22842306
// Since encoding metadata is not in a query, and nothing is cached,
@@ -2292,6 +2314,42 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
22922314
join(|| prefetch_mir(tcx), || tcx.exported_symbols(LOCAL_CRATE));
22932315
}
22942316

2317+
with_encode_metadata_header(tcx, path, |ecx| {
2318+
// Encode all the entries and extra information in the crate,
2319+
// culminating in the `CrateRoot` which points to all of it.
2320+
let root = ecx.encode_crate_root();
2321+
2322+
// Flush buffer to ensure backing file has the correct size.
2323+
ecx.opaque.flush();
2324+
// Record metadata size for self-profiling
2325+
tcx.prof.artifact_size(
2326+
"crate_metadata",
2327+
"crate_metadata",
2328+
ecx.opaque.file().metadata().unwrap().len(),
2329+
);
2330+
2331+
root.position.get()
2332+
});
2333+
2334+
ifletSome(ref_path) = ref_path {
2335+
with_encode_metadata_header(tcx, ref_path, |ecx| {
2336+
let header:LazyValue<CrateHeader> = ecx.lazy(CrateHeader{
2337+
name: tcx.crate_name(LOCAL_CRATE),
2338+
triple: tcx.sess.opts.target_triple.clone(),
2339+
hash: tcx.crate_hash(LOCAL_CRATE),
2340+
is_proc_macro_crate:false,
2341+
is_stub:true,
2342+
});
2343+
header.position.get()
2344+
});
2345+
}
2346+
}
2347+
2348+
fnwith_encode_metadata_header(
2349+
tcx:TyCtxt<'_>,
2350+
path:&Path,
2351+
f:implFnOnce(&mutEncodeContext<'_,'_>) -> usize,
2352+
){
22952353
letmut encoder = opaque::FileEncoder::new(path)
22962354
.unwrap_or_else(|err| tcx.dcx().emit_fatal(FailCreateFileEncoder{ err }));
22972355
encoder.emit_raw_bytes(METADATA_HEADER);
@@ -2326,9 +2384,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
23262384
// Encode the rustc version string in a predictable location.
23272385
rustc_version(tcx.sess.cfg_version).encode(&mut ecx);
23282386

2329-
// Encode all the entries and extra information in the crate,
2330-
// culminating in the `CrateRoot` which points to all of it.
2331-
let root = ecx.encode_crate_root();
2387+
let root_position = f(&mut ecx);
23322388

23332389
// Make sure we report any errors from writing to the file.
23342390
// If we forget this, compilation can succeed with an incomplete rmeta file,
@@ -2338,12 +2394,9 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
23382394
}
23392395

23402396
let file = ecx.opaque.file();
2341-
ifletErr(err) = encode_root_position(file,root.position.get()){
2397+
ifletErr(err) = encode_root_position(file,root_position){
23422398
tcx.dcx().emit_fatal(FailWriteFile{path: ecx.opaque.path(), err });
23432399
}
2344-
2345-
// Record metadata size for self-profiling
2346-
tcx.prof.artifact_size("crate_metadata","crate_metadata", file.metadata().unwrap().len());
23472400
}
23482401

23492402
fnencode_root_position(mutfile:&File,pos:usize) -> Result<(), std::io::Error>{

‎compiler/rustc_metadata/src/rmeta/mod.rs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,12 @@ pub(crate) struct CrateHeader {
221221
/// This is separate from [`ProcMacroData`] to avoid having to update [`METADATA_VERSION`] every
222222
/// time ProcMacroData changes.
223223
pub(crate)is_proc_macro_crate:bool,
224+
/// Whether this crate metadata section is just a stub.
225+
/// Stubs do not contain the full metadata (it will be typically stored
226+
/// in a separate rmeta file).
227+
///
228+
/// This is used inside rlibs and dylibs when using `-Zembed-metadata=no`.
229+
pub(crate)is_stub:bool,
224230
}
225231

226232
/// Serialized `.rmeta` data for a crate.

0 commit comments

Comments
 (0)