Skip to content

Commit e30103a

Browse files
committed
Move NativeLib::filename to the rmeta-link archive member
1 parent c397dae commit e30103a

6 files changed

Lines changed: 152 additions & 45 deletions

File tree

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 84 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use rustc_lint_defs::builtin::LINKER_INFO;
2626
use rustc_macros::Diagnostic;
2727
use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file};
2828
use rustc_metadata::{
29-
EncodedMetadata, NativeLibSearchFallback, find_native_static_library,
29+
EncodedMetadata, NativeLibSearchFallback, find_bundled_library, find_native_static_library,
3030
walk_native_lib_search_dirs,
3131
};
3232
use rustc_middle::bug;
@@ -329,8 +329,25 @@ fn link_rlib<'a>(
329329
.map(|obj| obj.file_name().unwrap().to_str().unwrap().to_string())
330330
.collect();
331331

332+
let native_lib_filenames: Vec<Option<Symbol>> = crate_info
333+
.used_libraries
334+
.iter()
335+
.map(|lib| {
336+
find_bundled_library(
337+
lib.name,
338+
Some(lib.verbatim),
339+
lib.kind,
340+
lib.cfg.is_some(),
341+
sess,
342+
&crate_info.crate_types,
343+
)
344+
})
345+
.collect();
346+
332347
let metadata_link_file = if matches!(flavor, RlibFlavor::Normal) {
333-
let metadata_link = rmeta_link::RmetaLink { rust_object_files };
348+
let native_lib_filenames: Vec<Option<String>> =
349+
native_lib_filenames.iter().map(|f| f.map(|s| s.to_string())).collect();
350+
let metadata_link = rmeta_link::RmetaLink { rust_object_files, native_lib_filenames };
334351
let metadata_link_data = metadata_link.encode();
335352
let (wrapper, _) =
336353
create_wrapper_file(sess, rmeta_link::SECTION.to_string(), &metadata_link_data);
@@ -413,12 +430,12 @@ fn link_rlib<'a>(
413430
// feature then we'll need to figure out how to record what objects were
414431
// loaded from the libraries found here and then encode that into the
415432
// metadata of the rlib we're generating somehow.
416-
for lib in crate_info.used_libraries.iter() {
433+
for (i, lib) in crate_info.used_libraries.iter().enumerate() {
417434
let NativeLibKind::Static { bundle: None | Some(true), .. } = lib.kind else {
418435
continue;
419436
};
420437
if flavor == RlibFlavor::Normal
421-
&& let Some(filename) = lib.filename
438+
&& let Some(filename) = native_lib_filenames[i]
422439
{
423440
let path = find_native_static_library(filename.as_str(), true, sess);
424441
let src = read(path)
@@ -532,11 +549,21 @@ fn link_staticlib(
532549
let lto = are_upstream_rust_objects_already_included(sess)
533550
&& !ignored_for_lto(sess, crate_info, cnum);
534551

535-
let native_libs = crate_info.native_libraries[&cnum].iter();
536-
let relevant = native_libs.clone().filter(|lib| relevant_lib(sess, lib));
537-
let relevant_libs: FxIndexSet<_> = relevant.filter_map(|lib| lib.filename).collect();
552+
let native_libs = &crate_info.native_libraries[&cnum];
553+
let bundled_filenames =
554+
rmeta_link_cache.native_lib_filenames(&sess.target, path, native_libs);
555+
let relevant_libs: FxIndexSet<_> = native_libs
556+
.iter()
557+
.enumerate()
558+
.filter(|(_, lib)| relevant_lib(sess, lib))
559+
.filter_map(|(i, _)| bundled_filenames.get(i).copied().flatten())
560+
.collect();
538561

539-
let bundled_libs: FxIndexSet<_> = native_libs.filter_map(|lib| lib.filename).collect();
562+
let bundled_libs: FxIndexSet<_> = native_libs
563+
.iter()
564+
.enumerate()
565+
.filter_map(|(i, _)| bundled_filenames.get(i).copied().flatten())
566+
.collect();
540567
ab.add_archive(
541568
path,
542569
AddArchiveKind::Rlib(rmeta_link_cache, &|fname: &str, entry_kind| {
@@ -2739,6 +2766,7 @@ fn linker_with_args(
27392766
cmd,
27402767
sess,
27412768
archive_builder_builder,
2769+
rmeta_link_cache,
27422770
crate_info,
27432771
tmpdir,
27442772
link_output_kind,
@@ -2761,6 +2789,7 @@ fn linker_with_args(
27612789
cmd,
27622790
sess,
27632791
archive_builder_builder,
2792+
rmeta_link_cache,
27642793
crate_info,
27652794
tmpdir,
27662795
link_output_kind,
@@ -3060,6 +3089,7 @@ fn add_native_libs_from_crate(
30603089
cmd: &mut dyn Linker,
30613090
sess: &Session,
30623091
archive_builder_builder: &dyn ArchiveBuilderBuilder,
3092+
rmeta_link_cache: &mut RmetaLinkCache,
30633093
crate_info: &CrateInfo,
30643094
tmpdir: &Path,
30653095
bundled_libs: &FxIndexSet<Symbol>,
@@ -3083,13 +3113,38 @@ fn add_native_libs_from_crate(
30833113
.unwrap_or_else(|e| sess.dcx().emit_fatal(e));
30843114
}
30853115

3086-
let native_libs = match cnum {
3087-
LOCAL_CRATE => &crate_info.used_libraries,
3088-
_ => &crate_info.native_libraries[&cnum],
3116+
let (native_libs, bundled_filenames): (&Vec<NativeLib>, Vec<Option<Symbol>>) = match cnum {
3117+
LOCAL_CRATE => {
3118+
let libs = &crate_info.used_libraries;
3119+
let filenames = libs
3120+
.iter()
3121+
.map(|lib| {
3122+
find_bundled_library(
3123+
lib.name,
3124+
Some(lib.verbatim),
3125+
lib.kind,
3126+
lib.cfg.is_some(),
3127+
sess,
3128+
&crate_info.crate_types,
3129+
)
3130+
})
3131+
.collect();
3132+
(libs, filenames)
3133+
}
3134+
_ => {
3135+
let native_libs = &crate_info.native_libraries[&cnum];
3136+
let filenames =
3137+
if let Some(rlib_path) = crate_info.used_crate_source[&cnum].rlib.as_ref() {
3138+
rmeta_link_cache.native_lib_filenames(&sess.target, rlib_path, native_libs)
3139+
} else {
3140+
Vec::new()
3141+
};
3142+
(native_libs, filenames)
3143+
}
30893144
};
30903145

30913146
let mut last = (None, NativeLibKind::Unspecified, false);
3092-
for lib in native_libs {
3147+
for (i, lib) in native_libs.iter().enumerate() {
30933148
if !relevant_lib(sess, lib) {
30943149
continue;
30953150
}
@@ -3109,7 +3164,7 @@ fn add_native_libs_from_crate(
31093164
let bundle = bundle.unwrap_or(true);
31103165
let whole_archive = whole_archive == Some(true);
31113166
if bundle && cnum != LOCAL_CRATE {
3112-
if let Some(filename) = lib.filename {
3167+
if let Some(filename) = bundled_filenames.get(i).copied().flatten() {
31133168
// If rlib contains native libs as archives, they are unpacked to tmpdir.
31143169
let path = tmpdir.join(filename.as_str());
31153170
cmd.link_staticlib_by_path(&path, whole_archive);
@@ -3161,6 +3216,7 @@ fn add_local_native_libraries(
31613216
cmd: &mut dyn Linker,
31623217
sess: &Session,
31633218
archive_builder_builder: &dyn ArchiveBuilderBuilder,
3219+
rmeta_link_cache: &mut RmetaLinkCache,
31643220
crate_info: &CrateInfo,
31653221
tmpdir: &Path,
31663222
link_output_kind: LinkOutputKind,
@@ -3172,6 +3228,7 @@ fn add_local_native_libraries(
31723228
cmd,
31733229
sess,
31743230
archive_builder_builder,
3231+
rmeta_link_cache,
31753232
crate_info,
31763233
tmpdir,
31773234
&Default::default(),
@@ -3231,10 +3288,17 @@ fn add_upstream_rust_crates(
32313288
match linkage {
32323289
Linkage::Static | Linkage::IncludedFromDylib | Linkage::NotLinked => {
32333290
if link_static_crate {
3234-
bundled_libs = crate_info.native_libraries[&cnum]
3235-
.iter()
3236-
.filter_map(|lib| lib.filename)
3237-
.collect();
3291+
if let Some(rlib_path) = crate_info.used_crate_source[&cnum].rlib.as_ref() {
3292+
bundled_libs = rmeta_link_cache
3293+
.native_lib_filenames(
3294+
&sess.target,
3295+
rlib_path,
3296+
&crate_info.native_libraries[&cnum],
3297+
)
3298+
.into_iter()
3299+
.flatten()
3300+
.collect();
3301+
}
32383302
add_static_crate(
32393303
cmd,
32403304
sess,
@@ -3268,6 +3332,7 @@ fn add_upstream_rust_crates(
32683332
cmd,
32693333
sess,
32703334
archive_builder_builder,
3335+
rmeta_link_cache,
32713336
crate_info,
32723337
tmpdir,
32733338
&bundled_libs,
@@ -3283,6 +3348,7 @@ fn add_upstream_native_libraries(
32833348
cmd: &mut dyn Linker,
32843349
sess: &Session,
32853350
archive_builder_builder: &dyn ArchiveBuilderBuilder,
3351+
rmeta_link_cache: &mut RmetaLinkCache,
32863352
crate_info: &CrateInfo,
32873353
tmpdir: &Path,
32883354
link_output_kind: LinkOutputKind,
@@ -3306,6 +3372,7 @@ fn add_upstream_native_libraries(
33063372
cmd,
33073373
sess,
33083374
archive_builder_builder,
3375+
rmeta_link_cache,
33093376
crate_info,
33103377
tmpdir,
33113378
&Default::default(),

compiler/rustc_codegen_ssa/src/back/rmeta_link.rs

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,38 @@
22
//! and potentially other data collected and used when building or linking a rlib.
33
//! See <https://github.com/rust-lang/rust/issues/138243>.
44
5+
use std::fs::File;
56
use std::path::{Path, PathBuf};
67

78
use object::read::archive::ArchiveFile;
89
use rustc_data_structures::fx::FxHashMap;
10+
use rustc_data_structures::memmap::Mmap;
11+
use rustc_hir::attrs::NativeLibKind;
912
use rustc_serialize::opaque::mem_encoder::MemEncoder;
1013
use rustc_serialize::opaque::{MAGIC_END_BYTES, MemDecoder};
1114
use rustc_serialize::{Decodable, Encodable};
15+
use rustc_span::Symbol;
16+
use rustc_target::spec::Target;
17+
use tracing::debug;
1218

13-
use super::metadata::search_for_section;
19+
use super::metadata::{get_metadata_xcoff, search_for_section};
20+
use crate::NativeLib;
1421

1522
pub(crate) const FILENAME: &str = "lib.rmeta-link";
1623
pub(crate) const SECTION: &str = ".rmeta-link";
1724

1825
pub struct RmetaLink {
1926
pub rust_object_files: Vec<String>,
27+
/// Positionally aligned with `native_libraries` in regular metadata: index `i` is the
28+
/// bundled filename for native library `i`, or `None` if that library needs no bundling.
29+
pub native_lib_filenames: Vec<Option<String>>,
2030
}
2131

2232
impl RmetaLink {
2333
pub(crate) fn encode(&self) -> Vec<u8> {
2434
let mut encoder = MemEncoder::new();
2535
self.rust_object_files.encode(&mut encoder);
36+
self.native_lib_filenames.encode(&mut encoder);
2637
let mut data = encoder.finish();
2738
data.extend_from_slice(MAGIC_END_BYTES);
2839
data
@@ -31,7 +42,8 @@ impl RmetaLink {
3142
pub(crate) fn decode(data: &[u8]) -> Option<RmetaLink> {
3243
let mut decoder = MemDecoder::new(data, 0).ok()?;
3344
let rust_object_files = Vec::<String>::decode(&mut decoder);
34-
Some(RmetaLink { rust_object_files })
45+
let native_lib_filenames = Vec::<Option<String>>::decode(&mut decoder);
46+
Some(RmetaLink { rust_object_files, native_lib_filenames })
3547
}
3648
}
3749

@@ -69,4 +81,52 @@ impl RmetaLinkCache {
6981
) -> Option<&RmetaLink> {
7082
self.cache.entry(rlib_path.to_path_buf()).or_insert_with(load).as_ref()
7183
}
84+
85+
pub fn native_lib_filenames(
86+
&mut self,
87+
target: &Target,
88+
rlib_path: &Path,
89+
native_libs: &[NativeLib],
90+
) -> Vec<Option<Symbol>> {
91+
if !crate_may_have_bundled_libs(native_libs) {
92+
return Vec::new();
93+
}
94+
self.get_or_insert_with(rlib_path, || read_from_path(target, rlib_path))
95+
.map(|rl| {
96+
rl.native_lib_filenames.iter().map(|f| f.as_deref().map(Symbol::intern)).collect()
97+
})
98+
.unwrap_or_default()
99+
}
100+
}
101+
102+
fn crate_may_have_bundled_libs(libs: &[NativeLib]) -> bool {
103+
libs.iter()
104+
.any(|lib| matches!(lib.kind, NativeLibKind::Static { bundle: Some(true) | None, .. }))
105+
}
106+
107+
// FIXME: this is mostly a copy-paste of `DefaultMetadataLoader::get_rlib_metadata`.
108+
fn read_from_path(target: &Target, path: &Path) -> Option<RmetaLink> {
109+
let Ok(file) = File::open(path) else {
110+
debug!("failed to open rlib for rmeta-link: {}", path.display());
111+
return None;
112+
};
113+
let Ok(mmap) = (unsafe { Mmap::map(file) }) else {
114+
debug!("failed to mmap rlib for rmeta-link: {}", path.display());
115+
return None;
116+
};
117+
118+
if target.is_like_aix {
119+
let archive = ArchiveFile::parse(&*mmap).ok()?;
120+
for entry in archive.members() {
121+
let entry = entry.ok()?;
122+
if entry.name() == FILENAME.as_bytes() {
123+
let member_data = entry.data(&*mmap).ok()?;
124+
let section_data = get_metadata_xcoff(path, member_data).ok()?;
125+
return RmetaLink::decode(section_data);
126+
}
127+
}
128+
return None;
129+
}
130+
131+
read_from_data(&mmap, path)
72132
}

compiler/rustc_codegen_ssa/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,6 @@ bitflags::bitflags! {
214214
pub struct NativeLib {
215215
pub kind: NativeLibKind,
216216
pub name: Symbol,
217-
pub filename: Option<Symbol>,
218217
pub cfg: Option<CfgEntry>,
219218
pub verbatim: bool,
220219
pub dll_imports: Vec<cstore::DllImport>,
@@ -224,7 +223,6 @@ impl From<&cstore::NativeLib> for NativeLib {
224223
fn from(lib: &cstore::NativeLib) -> Self {
225224
NativeLib {
226225
kind: lib.kind,
227-
filename: lib.filename,
228226
name: lib.name,
229227
cfg: lib.cfg.clone(),
230228
verbatim: lib.verbatim.unwrap_or(false),

compiler/rustc_metadata/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub mod locator;
2929
pub use fs::{METADATA_FILENAME, emit_wrapper_file};
3030
pub use host_dylib::{DylibError, load_symbol_from_dylib};
3131
pub use native_libs::{
32-
NativeLibSearchFallback, find_native_static_library, try_find_native_dynamic_library,
33-
try_find_native_static_library, walk_native_lib_search_dirs,
32+
NativeLibSearchFallback, find_bundled_library, find_native_static_library,
33+
try_find_native_dynamic_library, try_find_native_static_library, walk_native_lib_search_dirs,
3434
};
3535
pub use rmeta::{EncodedMetadata, METADATA_HEADER, ProcMacroKind, encode_metadata, rendered_const};

compiler/rustc_metadata/src/native_libs.rs

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -168,16 +168,16 @@ pub fn find_native_static_library(name: &str, verbatim: bool, sess: &Session) ->
168168
})
169169
}
170170

171-
fn find_bundled_library(
171+
pub fn find_bundled_library(
172172
name: Symbol,
173173
verbatim: Option<bool>,
174174
kind: NativeLibKind,
175175
has_cfg: bool,
176-
tcx: TyCtxt<'_>,
176+
sess: &Session,
177+
crate_types: &[CrateType],
177178
) -> Option<Symbol> {
178-
let sess = tcx.sess;
179179
if let NativeLibKind::Static { bundle: Some(true) | None, whole_archive, .. } = kind
180-
&& tcx.crate_types().iter().any(|t| matches!(t, &CrateType::Rlib | CrateType::StaticLib))
180+
&& crate_types.iter().any(|t| matches!(t, &CrateType::Rlib | CrateType::StaticLib))
181181
&& (sess.opts.unstable_opts.packed_bundled_libs || has_cfg || whole_archive == Some(true))
182182
{
183183
let verbatim = verbatim.unwrap_or(false);
@@ -275,16 +275,8 @@ impl<'tcx> Collector<'tcx> {
275275
}
276276
};
277277

278-
let filename = find_bundled_library(
279-
attr.name,
280-
attr.verbatim,
281-
attr.kind,
282-
attr.cfg.is_some(),
283-
self.tcx,
284-
);
285278
self.libs.push(NativeLib {
286279
name: attr.name,
287-
filename,
288280
kind: attr.kind,
289281
cfg: attr.cfg.clone(),
290282
foreign_module: Some(def_id.to_def_id()),
@@ -366,16 +358,8 @@ impl<'tcx> Collector<'tcx> {
366358
// Add if not found
367359
let new_name: Option<&str> = passed_lib.new_name.as_deref();
368360
let name = Symbol::intern(new_name.unwrap_or(&passed_lib.name));
369-
let filename = find_bundled_library(
370-
name,
371-
passed_lib.verbatim,
372-
passed_lib.kind,
373-
false,
374-
self.tcx,
375-
);
376361
self.libs.push(NativeLib {
377362
name,
378-
filename,
379363
kind: passed_lib.kind,
380364
cfg: None,
381365
foreign_module: None,

0 commit comments

Comments
 (0)