linker: Avoid some allocations in search directory iteration

This commit is contained in:
Vadim Petrochenkov 2024-04-12 00:09:43 +03:00
parent aa6a697a1c
commit 4ded0b82ca
4 changed files with 21 additions and 22 deletions

View File

@ -56,8 +56,13 @@
pub struct SearchPaths(OnceCell<Vec<PathBuf>>); pub struct SearchPaths(OnceCell<Vec<PathBuf>>);
impl SearchPaths { impl SearchPaths {
pub(super) fn get(&self, sess: &Session) -> &[PathBuf] { pub(super) fn get(&self, sess: &Session) -> impl Iterator<Item = &Path> {
self.0.get_or_init(|| archive_search_paths(sess)) let native_search_paths = || {
Vec::from_iter(
sess.target_filesearch(PathKind::Native).search_path_dirs().map(|p| p.to_owned()),
)
};
self.0.get_or_init(native_search_paths).iter().map(|p| &**p)
} }
} }
@ -310,8 +315,6 @@ fn link_rlib<'a>(
flavor: RlibFlavor, flavor: RlibFlavor,
tmpdir: &MaybeTempDir, tmpdir: &MaybeTempDir,
) -> Result<Box<dyn ArchiveBuilder + 'a>, ErrorGuaranteed> { ) -> Result<Box<dyn ArchiveBuilder + 'a>, ErrorGuaranteed> {
let lib_search_paths = archive_search_paths(sess);
let mut ab = archive_builder_builder.new_archive_builder(sess); let mut ab = archive_builder_builder.new_archive_builder(sess);
let trailing_metadata = match flavor { let trailing_metadata = match flavor {
@ -378,26 +381,24 @@ fn link_rlib<'a>(
// feature then we'll need to figure out how to record what objects were // feature then we'll need to figure out how to record what objects were
// loaded from the libraries found here and then encode that into the // loaded from the libraries found here and then encode that into the
// metadata of the rlib we're generating somehow. // metadata of the rlib we're generating somehow.
let search_paths = SearchPaths::default();
for lib in codegen_results.crate_info.used_libraries.iter() { for lib in codegen_results.crate_info.used_libraries.iter() {
let NativeLibKind::Static { bundle: None | Some(true), .. } = lib.kind else { let NativeLibKind::Static { bundle: None | Some(true), .. } = lib.kind else {
continue; continue;
}; };
let search_paths = search_paths.get(sess);
if flavor == RlibFlavor::Normal if flavor == RlibFlavor::Normal
&& let Some(filename) = lib.filename && let Some(filename) = lib.filename
{ {
let path = find_native_static_library(filename.as_str(), true, &lib_search_paths, sess); let path = find_native_static_library(filename.as_str(), true, search_paths, sess);
let src = read(path) let src = read(path)
.map_err(|e| sess.dcx().emit_fatal(errors::ReadFileError { message: e }))?; .map_err(|e| sess.dcx().emit_fatal(errors::ReadFileError { message: e }))?;
let (data, _) = create_wrapper_file(sess, ".bundled_lib".to_string(), &src); let (data, _) = create_wrapper_file(sess, ".bundled_lib".to_string(), &src);
let wrapper_file = emit_wrapper_file(sess, &data, tmpdir, filename.as_str()); let wrapper_file = emit_wrapper_file(sess, &data, tmpdir, filename.as_str());
packed_bundled_libs.push(wrapper_file); packed_bundled_libs.push(wrapper_file);
} else { } else {
let path = find_native_static_library( let path =
lib.name.as_str(), find_native_static_library(lib.name.as_str(), lib.verbatim, search_paths, sess);
lib.verbatim,
&lib_search_paths,
sess,
);
ab.add_archive(&path, Box::new(|_| false)).unwrap_or_else(|error| { ab.add_archive(&path, Box::new(|_| false)).unwrap_or_else(|error| {
sess.dcx().emit_fatal(errors::AddNativeLibrary { library_path: path, error }) sess.dcx().emit_fatal(errors::AddNativeLibrary { library_path: path, error })
}); });
@ -1445,10 +1446,6 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> (bool, bool) {
} }
} }
fn archive_search_paths(sess: &Session) -> Vec<PathBuf> {
sess.target_filesearch(PathKind::Native).search_path_dirs()
}
#[derive(PartialEq)] #[derive(PartialEq)]
enum RlibFlavor { enum RlibFlavor {
Normal, Normal,

View File

@ -170,7 +170,9 @@ fn configure_and_expand(
let mut old_path = OsString::new(); let mut old_path = OsString::new();
if cfg!(windows) { if cfg!(windows) {
old_path = env::var_os("PATH").unwrap_or(old_path); old_path = env::var_os("PATH").unwrap_or(old_path);
let mut new_path = sess.host_filesearch(PathKind::All).search_path_dirs(); let mut new_path = Vec::from_iter(
sess.host_filesearch(PathKind::All).search_path_dirs().map(|p| p.to_owned()),
);
for path in env::split_paths(&old_path) { for path in env::split_paths(&old_path) {
if !new_path.contains(&path) { if !new_path.contains(&path) {
new_path.push(path); new_path.push(path);

View File

@ -17,12 +17,12 @@
use crate::errors; use crate::errors;
use std::path::PathBuf; use std::path::{Path, PathBuf};
pub fn find_native_static_library( pub fn find_native_static_library<'a>(
name: &str, name: &str,
verbatim: bool, verbatim: bool,
search_paths: &[PathBuf], search_paths: impl Iterator<Item = &'a Path>,
sess: &Session, sess: &Session,
) -> PathBuf { ) -> PathBuf {
let formats = if verbatim { let formats = if verbatim {
@ -60,7 +60,7 @@ fn find_bundled_library(
&& (sess.opts.unstable_opts.packed_bundled_libs || has_cfg || whole_archive == Some(true)) && (sess.opts.unstable_opts.packed_bundled_libs || has_cfg || whole_archive == Some(true))
{ {
let verbatim = verbatim.unwrap_or(false); let verbatim = verbatim.unwrap_or(false);
let search_paths = &sess.target_filesearch(PathKind::Native).search_path_dirs(); let search_paths = sess.target_filesearch(PathKind::Native).search_path_dirs();
return find_native_static_library(name.as_str(), verbatim, search_paths, sess) return find_native_static_library(name.as_str(), verbatim, search_paths, sess)
.file_name() .file_name()
.and_then(|s| s.to_str()) .and_then(|s| s.to_str())

View File

@ -47,8 +47,8 @@ pub fn new(
} }
/// Returns just the directories within the search paths. /// Returns just the directories within the search paths.
pub fn search_path_dirs(&self) -> Vec<PathBuf> { pub fn search_path_dirs(&self) -> impl Iterator<Item = &'a Path> {
self.search_paths().map(|sp| sp.dir.to_path_buf()).collect() self.search_paths().map(|sp| &*sp.dir)
} }
} }