From 6591abb0b2f366289fbb8139a7ab746ba7a80916 Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Sat, 10 Oct 2026 08:56:55 +0200 Subject: [PATCH] cmSourceFileLocation: Avoid checking the disk repeatedly Source file lookups with unknown extensions checked the disk every time. Skip the check when neither the directory nor the extension is ambiguous, and remember files found to exist until files may have been removed or renamed. --- Source/cmGlobalGenerator.cxx | 13 +++++++++++++ Source/cmGlobalGenerator.h | 12 ++++++++++++ Source/cmSourceFileLocation.cxx | 8 +++++--- Source/cmake.cxx | 4 +++- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 0c6d54ffe6..ec681a6500 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -2603,6 +2603,7 @@ void cmGlobalGenerator::ClearGeneratorMembers() this->ProjectMap.clear(); this->RuleHashes.clear(); this->DirectoryContentMap.clear(); + this->ExistingSourceFiles.clear(); this->XcFrameworkPListContentMap.clear(); this->BinaryDirectories.clear(); this->GeneratedFiles.clear(); @@ -4518,6 +4519,18 @@ void cmGlobalGenerator::AddToManifest(std::string const& f) dc.All.insert(file); } +bool cmGlobalGenerator::SourceFileExists(std::string const& path) +{ + if (this->ExistingSourceFiles.count(path)) { + return true; + } + if (cmSystemTools::FileExists(path, true)) { + this->ExistingSourceFiles.insert(path); + return true; + } + return false; +} + std::set const& cmGlobalGenerator::GetDirectoryContent( std::string const& dir, bool needDisk) { diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 51874f068f..7b87ec46c8 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -584,6 +584,15 @@ public: std::set const& GetDirectoryContent(std::string const& dir, bool needDisk = true); + /** Check whether a file exists for the purpose of resolving the + location of a source file. Files found to exist are remembered until + the next configure, or until cmake::InvalidateFileSystemCaches, + because the same source file is typically looked up many times. + Missing files are always checked again so that files created later + are still found. */ + bool SourceFileExists(std::string const& path); + void ClearSourceFileExistsCache() { this->ExistingSourceFiles.clear(); } + void IndexTarget(cmTarget* t); void IndexGeneratorTarget(cmGeneratorTarget* gt); @@ -1136,6 +1145,9 @@ private: }; std::map DirectoryContentMap; + // Files known to exist, see SourceFileExists. + std::unordered_set ExistingSourceFiles; + // Cache parsed PList files std::map XcFrameworkPListContentMap; diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx index f1d2106a52..98c8b303ec 100644 --- a/Source/cmSourceFileLocation.cxx +++ b/Source/cmSourceFileLocation.cxx @@ -117,9 +117,11 @@ void cmSourceFileLocation::UpdateExtension(std::string const& name) // This is a known extension. Use the given filename with extension. this->Name = cmSystemTools::GetFilenameName(name); this->AmbiguousExtension = false; - } else { + } else if (this->AmbiguousExtension || this->AmbiguousDirectory) { // This is not a known extension. See if the file exists on disk as - // named. + // named. This is not needed if neither the extension nor the + // directory is ambiguous, because finding the file would not change + // the location. std::string tryPath; if (this->AmbiguousDirectory) { // Check the source tree only because a file in the build tree should @@ -132,7 +134,7 @@ void cmSourceFileLocation::UpdateExtension(std::string const& name) tryPath += "/"; } tryPath += this->Name; - if (cmSystemTools::FileExists(tryPath, true)) { + if (gg->SourceFileExists(tryPath)) { // We found a source file named by the user on disk. Trust it's // extension. this->Name = cmSystemTools::GetFilenameName(name); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index c48750b4d3..30e079b65a 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -2577,7 +2577,9 @@ int cmake::Configure() void cmake::InvalidateFileSystemCaches() { - // Caches of file system state are cleared here as they are added. + if (this->GlobalGenerator) { + this->GlobalGenerator->ClearSourceFileExistsCache(); + } } int cmake::ActualConfigure()