From 8b387d84fe6ba00561ca00f6553c46598e3f2d68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 14 Aug 2025 22:24:37 +0200 Subject: [PATCH 1/2] Deduplicate `-L` paths passed to rustc --- compiler/rustc_session/src/config.rs | 31 +++++++++++++++++++--------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index c665c85d1fea4..a0b214d4a2536 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2828,16 +2828,27 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M // This is the location used by the `rustc-dev` `rustup` component. real_source_base_dir("lib/rustlib/rustc-src/rust", "compiler/rustc/src/main.rs"); - let mut search_paths = vec![]; - for s in &matches.opt_strs("L") { - search_paths.push(SearchPath::from_cli_opt( - sysroot.path(), - &target_triple, - early_dcx, - s, - unstable_opts.unstable_options, - )); - } + // We eagerly scan all files in each passed -L path. If the same directory is passed multiple + // times, and the directory contains a lot of files, this can take a lot of time. + // So we remove -L paths that were passed multiple times, and keep only the first occurrence. + // We still have to keep the original order of the -L arguments. + let search_paths: Vec = { + let mut seen_search_paths = FxHashSet::default(); + let search_path_matches: Vec = matches.opt_strs("L"); + search_path_matches + .iter() + .filter(|p| seen_search_paths.insert(*p)) + .map(|path| { + SearchPath::from_cli_opt( + sysroot.path(), + &target_triple, + early_dcx, + &path, + unstable_opts.unstable_options, + ) + }) + .collect() + }; let working_dir = std::env::current_dir().unwrap_or_else(|e| { early_dcx.early_fatal(format!("Current directory is invalid: {e}")); From fd5b7373db2093be7e1c906d8f92627689cc1eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 14 Aug 2025 22:30:10 +0200 Subject: [PATCH 2/2] Do not pass duplicated `-L` arguments to merged doctests --- src/librustdoc/doctest.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 73ce62cdcde6a..95bd31729de18 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -16,7 +16,7 @@ use std::{fmt, panic, str}; pub(crate) use make::{BuildDocTestBuilder, DocTestBuilder}; pub(crate) use markdown::test as test_markdown; -use rustc_data_structures::fx::{FxHashMap, FxHasher, FxIndexMap, FxIndexSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxHasher, FxIndexMap, FxIndexSet}; use rustc_errors::emitter::HumanReadableErrorType; use rustc_errors::{ColorConfig, DiagCtxtHandle}; use rustc_hir as hir; @@ -689,6 +689,10 @@ fn run_test( "--extern=doctest_bundle_{edition}=", edition = doctest.edition )); + + // Deduplicate passed -L directory paths, since usually all dependencies will be in the + // same directory (e.g. target/debug/deps from Cargo). + let mut seen_search_dirs = FxHashSet::default(); for extern_str in &rustdoc_options.extern_strs { if let Some((_cratename, path)) = extern_str.split_once('=') { // Direct dependencies of the tests themselves are @@ -698,7 +702,9 @@ fn run_test( .parent() .filter(|x| x.components().count() > 0) .unwrap_or(Path::new(".")); - runner_compiler.arg("-L").arg(dir); + if seen_search_dirs.insert(dir) { + runner_compiler.arg("-L").arg(dir); + } } } let output_bundle_file = doctest