mirror of
https://github.com/Kitware/CMake.git
synced 2026-11-06 05:16:58 +00:00
AutoGen: Use directory listings to rule out missing headers
AutoGen checked the disk for a header with every header extension, with and without a "_p" suffix, for each source file processed by moc or uic. Most of these files do not exist. Use a listing of each directory, cached while scanning sources, to rule them out, and check the disk only for names that are present or that Windows may resolve without a matching directory entry.
This commit is contained in:
3 files changed
+56
-2
No files matched your search
@@ -2,12 +2,15 @@
|
||||
file LICENSE.rst or https://cmake.org/licensing for details. */
|
||||
#include "cmQtAutoGenGlobalInitializer.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
#include <cm/memory>
|
||||
#include <cm/optional>
|
||||
|
||||
#include "cmsys/Directory.hxx"
|
||||
|
||||
#include "cmCustomCommand.h"
|
||||
#include "cmDiagnostics.h"
|
||||
#include "cmDuration.h"
|
||||
@@ -162,6 +165,46 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer(
|
||||
|
||||
cmQtAutoGenGlobalInitializer::~cmQtAutoGenGlobalInitializer() = default;
|
||||
|
||||
bool cmQtAutoGenGlobalInitializer::CachedFileExists(std::string const& path)
|
||||
{
|
||||
// Most of the header paths probed for a source file do not exist.
|
||||
// A file whose name is not in the directory, compared without regard
|
||||
// to case, cannot exist. Names that are present, and names whose case
|
||||
// cannot be folded reliably, are checked on disk as before. So are
|
||||
// names Windows may resolve without a matching directory entry: short
|
||||
// 8.3 names, and names with a trailing dot or space.
|
||||
//
|
||||
// The listings are kept only while the per target initializers scan
|
||||
// their sources. Nothing creates files in the probed directories
|
||||
// meanwhile; AUTOGEN writes only to its own build directories, and
|
||||
// file(GENERATE) outputs are written later.
|
||||
std::string const name = cmSystemTools::GetFilenameName(path);
|
||||
bool const listable = !name.empty() && name.back() != '.' &&
|
||||
name.back() != ' ' && name.find('~') == std::string::npos &&
|
||||
std::all_of(name.begin(), name.end(),
|
||||
[](char c) { return static_cast<unsigned char>(c) < 0x80; });
|
||||
if (listable) {
|
||||
std::string const dir = cmSystemTools::GetFilenamePath(path);
|
||||
auto it = this->DirectoryNames_.find(dir);
|
||||
if (it == this->DirectoryNames_.end()) {
|
||||
cmsys::Directory d;
|
||||
if (d.Load(dir)) {
|
||||
std::unordered_set<std::string> names;
|
||||
unsigned long const n = d.GetNumberOfFiles();
|
||||
for (unsigned long i = 0; i < n; ++i) {
|
||||
names.insert(cmSystemTools::LowerCase(d.GetFileName(i)));
|
||||
}
|
||||
it = this->DirectoryNames_.emplace(dir, std::move(names)).first;
|
||||
}
|
||||
}
|
||||
if (it != this->DirectoryNames_.end() &&
|
||||
!it->second.count(cmSystemTools::LowerCase(name))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return cmSystemTools::FileExists(path);
|
||||
}
|
||||
|
||||
void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget(
|
||||
cmLocalGenerator* localGen, std::string const& name,
|
||||
std::string const& comment)
|
||||
@@ -344,6 +387,8 @@ bool cmQtAutoGenGlobalInitializer::InitializeCustomTargets()
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// The directory listings are only valid while scanning sources.
|
||||
this->DirectoryNames_.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "cmQtAutoGen.h"
|
||||
@@ -66,6 +67,11 @@ private:
|
||||
void AddToGlobalAutoRcc(cmLocalGenerator* localGen,
|
||||
std::string const& targetName);
|
||||
|
||||
/// @brief Check whether a file exists, using a cached listing of its
|
||||
/// directory to rule out files that do not exist without querying
|
||||
/// the file system for each of them.
|
||||
bool CachedFileExists(std::string const& path);
|
||||
|
||||
cmQtAutoGen::ConfigStrings<cmQtAutoGen::CompilerFeaturesHandle>
|
||||
GetCompilerFeatures(std::string const& generator,
|
||||
cmQtAutoGen::ConfigString const& executable,
|
||||
@@ -79,4 +85,7 @@ private:
|
||||
std::unordered_map<std::string, cmQtAutoGen::CompilerFeaturesHandle>>
|
||||
CompilerFeatures_;
|
||||
Keywords const Keywords_;
|
||||
/// Lower case names in directories, see CachedFileExists.
|
||||
std::unordered_map<std::string, std::unordered_set<std::string>>
|
||||
DirectoryNames_;
|
||||
};
|
||||
@@ -1112,10 +1112,10 @@ bool cmQtAutoGenInitializer::InitScanFiles()
|
||||
}
|
||||
// We only accept not-GENERATED files that do exist.
|
||||
if (!sf->GetIsGenerated() &&
|
||||
!cmSystemTools::FileExists(fullPath)) {
|
||||
!this->GlobalInitializer->CachedFileExists(fullPath)) {
|
||||
continue;
|
||||
}
|
||||
} else if (cmSystemTools::FileExists(fullPath)) {
|
||||
} else if (this->GlobalInitializer->CachedFileExists(fullPath)) {
|
||||
// Create a new source file for the existing file
|
||||
sf = this->Makefile->CreateSource(fullPath, false, locationKind);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user