summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/cmQtAutoMocUic.cxx508
-rw-r--r--Source/cmQtAutoMocUic.h70
2 files changed, 319 insertions, 259 deletions
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 6265777..7b65429 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -551,49 +551,35 @@ void cmQtAutoMocUic::JobParseSourceT::Process()
}
}
-void cmQtAutoMocUic::JobEvalCacheT::Process()
+std::string cmQtAutoMocUic::JobEvalCacheT::MessageSearchLocations() const
{
- // Evaluate for moc
- if (MocConst().Enabled) {
- // Evaluate headers
- for (auto const& pair : BaseEval().Headers) {
- if (!MocEvalHeader(pair.second)) {
- return;
- }
- }
- // Evaluate sources
- for (auto const& pair : BaseEval().Sources) {
- if (!MocEvalSource(pair.second)) {
- return;
- }
- }
+ std::string res;
+ res.reserve(512);
+ for (std::string const& path : SearchLocations) {
+ res += " ";
+ res += Quoted(path);
+ res += '\n';
}
- // Evaluate for uic
- if (UicConst().Enabled) {
- if (!UicEval(BaseEval().Headers) || !UicEval(BaseEval().Sources)) {
+ return res;
+}
+
+void cmQtAutoMocUic::JobEvalCacheMocT::Process()
+{
+ // Evaluate headers
+ for (auto const& pair : BaseEval().Headers) {
+ if (!EvalHeader(pair.second)) {
return;
}
}
-
- // Add discovered header parse jobs
- Gen()->CreateParseJobs<JobParseHeaderT>(MocEval().HeadersDiscovered);
-
- // Add dependency probing jobs
- {
- // Add fence job to ensure all parsing has finished
- Gen()->WorkerPool().EmplaceJob<JobFenceT>();
- if (MocConst().Enabled) {
- Gen()->WorkerPool().EmplaceJob<JobProbeDepsMocT>();
- }
- if (UicConst().Enabled) {
- Gen()->WorkerPool().EmplaceJob<JobProbeDepsUicT>();
+ // Evaluate sources
+ for (auto const& pair : BaseEval().Sources) {
+ if (!EvalSource(pair.second)) {
+ return;
}
- // Add probe finish job
- Gen()->WorkerPool().EmplaceJob<JobProbeDepsFinishT>();
}
}
-bool cmQtAutoMocUic::JobEvalCacheT::MocEvalHeader(SourceFileHandleT source)
+bool cmQtAutoMocUic::JobEvalCacheMocT::EvalHeader(SourceFileHandleT source)
{
SourceFileT const& sourceFile = *source;
auto const& parseData = sourceFile.ParseData->Moc;
@@ -614,13 +600,13 @@ bool cmQtAutoMocUic::JobEvalCacheT::MocEvalHeader(SourceFileHandleT source)
}
// Register mapping in headers map
- MocRegisterMapping(handle, true);
+ RegisterMapping(handle, true);
}
return true;
}
-bool cmQtAutoMocUic::JobEvalCacheT::MocEvalSource(
+bool cmQtAutoMocUic::JobEvalCacheMocT::EvalSource(
SourceFileHandleT const& source)
{
SourceFileT const& sourceFile = *source;
@@ -631,7 +617,7 @@ bool cmQtAutoMocUic::JobEvalCacheT::MocEvalSource(
return true;
}
- std::string const sourceDir = SubDirPrefix(sourceFile.FileName);
+ std::string const sourceDirPrefix = SubDirPrefix(sourceFile.FileName);
std::string const sourceBase =
cmSystemTools::GetFilenameWithoutLastExtension(sourceFile.FileName);
@@ -658,27 +644,30 @@ bool cmQtAutoMocUic::JobEvalCacheT::MocEvalSource(
// Check if this source needs to be moc processed but doesn't.
if (!sourceIncludesDotMoc && !parseData.Macro.empty() &&
!(relaxedMode && sourceIncludesMocUnderscore)) {
- LogFileError(GenT::MOC, sourceFile.FileName,
- cmStrCat("The file contains a ", Quoted(parseData.Macro),
- " macro, but does not include ",
- Quoted(sourceBase + ".moc"),
- "!\nConsider to\n - add #include \"", sourceBase,
- ".moc\"\n - enable SKIP_AUTOMOC for this file"));
+ LogError(GenT::MOC,
+ cmStrCat(sourceFile.FileName, "\ncontains a ",
+ Quoted(parseData.Macro), " macro, but does not include ",
+ Quoted(sourceBase + ".moc"),
+ "!\nConsider to\n - add #include \"", sourceBase,
+ ".moc\"\n - enable SKIP_AUTOMOC for this file"));
return false;
}
// Evaluate "moc_" includes
for (IncludeKeyT const& incKey : parseData.Include.Underscore) {
- std::string const headerBase = incKey.Dir + incKey.Base;
- SourceFileHandleT header = MocFindIncludedHeader(sourceDir, headerBase);
- if (!header) {
- LogFileError(GenT::MOC, sourceFile.FileName,
- cmStrCat("The file includes the moc file ",
- Quoted(incKey.Key),
- ",\nbut the header could not be found "
- "in the following locations\n",
- MocMessageTestHeaders(headerBase)));
- return false;
+ SourceFileHandleT headerHandle;
+ {
+ std::string const headerBase = cmStrCat(incKey.Dir, incKey.Base);
+ if (!FindIncludedHeader(headerHandle, sourceDirPrefix, headerBase)) {
+ LogError(GenT::MOC,
+ cmStrCat(Quoted(sourceFile.FileName),
+ "\nincludes the moc file ", Quoted(incKey.Key),
+ ",\nbut a header ", MessageHeader(headerBase),
+ "\ncould not be found "
+ "in the following directories\n",
+ MessageSearchLocations()));
+ return false;
+ }
}
// The include might be handled differently in relaxed mode
if (relaxedMode && !sourceIncludesDotMoc && !parseData.Macro.empty() &&
@@ -690,9 +679,9 @@ bool cmQtAutoMocUic::JobEvalCacheT::MocEvalSource(
// used. This is for KDE4 compatibility.
// Issue a warning
- Log().WarningFile(
- GenT::MOC, sourceFile.FileName,
- cmStrCat("The file contains a ", Quoted(parseData.Macro),
+ Log().Warning(
+ GenT::MOC,
+ cmStrCat(sourceFile.FileName, "\ncontains a ", Quoted(parseData.Macro),
" macro, but does not include ", Quoted(sourceBase + ".moc"),
".\nInstead it includes ", Quoted(incKey.Key),
".\nRunning moc on the source\n ",
@@ -702,18 +691,18 @@ bool cmQtAutoMocUic::JobEvalCacheT::MocEvalSource(
"This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"));
// Create mapping
- if (!MocRegisterIncluded(incKey.Key, source, source, false)) {
+ if (!RegisterIncluded(incKey.Key, source, source, false)) {
return false;
}
continue;
}
// Check if header is skipped
- if (MocConst().skipped(header->FileName)) {
+ if (MocConst().skipped(headerHandle->FileName)) {
continue;
}
// Create mapping
- if (!MocRegisterIncluded(incKey.Key, source, std::move(header), true)) {
+ if (!RegisterIncluded(incKey.Key, source, std::move(headerHandle), true)) {
return false;
}
}
@@ -726,53 +715,61 @@ bool cmQtAutoMocUic::JobEvalCacheT::MocEvalSource(
bool const ownMoc = (incKey.Base == sourceBase);
if (ownMoc && !parseData.Macro.empty()) {
// Create mapping for the regular use case
- if (!MocRegisterIncluded(incKey.Key, source, source, false)) {
+ if (!RegisterIncluded(incKey.Key, source, source, false)) {
return false;
}
continue;
}
// Try to find a header instead but issue a warning.
// This is for KDE4 compatibility.
- std::string const headerBase = incKey.Dir + incKey.Base;
- SourceFileHandleT header = MocFindIncludedHeader(sourceDir, headerBase);
- if (!header) {
- LogFileError(
- GenT::MOC, sourceFile.FileName,
- cmStrCat("The file includes the moc file ", Quoted(incKey.Key),
- ",\nwhich seems to be the moc file from a different source "
- "file.\nCMAKE_AUTOMOC_RELAXED_MODE: Also a matching header"
- "could not be found in the following locations\n",
- MocMessageTestHeaders(headerBase)));
- return false;
+ SourceFileHandleT headerHandle;
+ {
+ std::string const headerBase = cmStrCat(incKey.Dir, incKey.Base);
+ if (!FindIncludedHeader(headerHandle, sourceDirPrefix, headerBase)) {
+ LogError(
+ GenT::MOC,
+ cmStrCat(
+ Quoted(sourceFile.FileName), "\nincludes the moc file ",
+ Quoted(incKey.Key),
+ ",\nwhich seems to be the moc file from a different source "
+ "file.\nCMAKE_AUTOMOC_RELAXED_MODE:\nAlso a matching header ",
+ MessageHeader(headerBase),
+ "\ncould not be found in the following directories\n",
+ MessageSearchLocations()));
+ return false;
+ }
}
// Check if header is skipped
- if (MocConst().skipped(header->FileName)) {
+ if (MocConst().skipped(headerHandle->FileName)) {
continue;
}
// Issue a warning
if (ownMoc && parseData.Macro.empty()) {
- Log().WarningFile(
- GenT::MOC, sourceFile.FileName,
- cmStrCat("The file includes the moc file ", Quoted(incKey.Key),
- ", but does not contain a\n", MocConst().MacrosString(),
+ Log().Warning(
+ GenT::MOC,
+ cmStrCat(sourceFile.FileName, "\nincludes the moc file ",
+ Quoted(incKey.Key), ", but does not contain a\n",
+ MocConst().MacrosString(),
" macro.\nRunning moc on the header\n ",
- Quoted(header->FileName), "!\nBetter include ",
+ Quoted(headerHandle->FileName), "!\nBetter include ",
Quoted("moc_" + incKey.Base + ".cpp"),
" for a compatibility with regular mode.\n",
"This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"));
} else {
- Log().WarningFile(
- GenT::MOC, sourceFile.FileName,
- cmStrCat("The file includes the moc file ", Quoted(incKey.Key),
- " instead of ", Quoted("moc_" + incKey.Base + ".cpp"),
+ Log().Warning(
+ GenT::MOC,
+ cmStrCat(sourceFile.FileName, "\nincludes the moc file ",
+ Quoted(incKey.Key), " instead of ",
+ Quoted("moc_" + incKey.Base + ".cpp"),
".\nRunning moc on the header\n ",
- Quoted(header->FileName), "!\nBetter include ",
+ Quoted(headerHandle->FileName), "!\nBetter include ",
Quoted("moc_" + incKey.Base + ".cpp"),
" for compatibility with regular mode.\n",
"This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"));
}
// Create mapping
- if (!MocRegisterIncluded(incKey.Key, source, std::move(header), true)) {
+ if (!RegisterIncluded(incKey.Key, source, std::move(headerHandle),
+ true)) {
return false;
}
}
@@ -783,25 +780,24 @@ bool cmQtAutoMocUic::JobEvalCacheT::MocEvalSource(
bool const ownMoc = (incKey.Base == sourceBase);
if (!ownMoc) {
// Don't allow <BASE>.moc include other than own in regular mode
- LogFileError(
- GenT::MOC, sourceFile.FileName,
- cmStrCat("The file includes the moc file ", Quoted(incKey.Key),
- ",\nwhich seems to be the moc file from a different "
- "source file.\nThis is not supported. Include ",
- Quoted(sourceBase + ".moc"),
- " to run moc on this source file."));
+ LogError(GenT::MOC,
+ cmStrCat(sourceFile.FileName, "\nincludes the moc file ",
+ Quoted(incKey.Key),
+ ",\nwhich seems to be the moc file from a different "
+ "source file.\nThis is not supported. Include ",
+ Quoted(sourceBase + ".moc"),
+ " to run moc on this source file."));
return false;
}
// Accept but issue a warning if moc isn't required
if (parseData.Macro.empty()) {
- Log().WarningFile(GenT::MOC, sourceFile.FileName,
- cmStrCat("The file includes the moc file ",
- Quoted(incKey.Key),
- ", but does not contain a ",
- MocConst().MacrosString(), " macro."));
+ Log().Warning(GenT::MOC,
+ cmStrCat(sourceFile.FileName, "\nincludes the moc file ",
+ Quoted(incKey.Key), ", but does not contain a ",
+ MocConst().MacrosString(), " macro."));
}
// Create mapping
- if (!MocRegisterIncluded(incKey.Key, source, source, false)) {
+ if (!RegisterIncluded(incKey.Key, source, source, false)) {
return false;
}
}
@@ -810,79 +806,71 @@ bool cmQtAutoMocUic::JobEvalCacheT::MocEvalSource(
return true;
}
-cmQtAutoMocUic::SourceFileHandleT
-cmQtAutoMocUic::JobEvalCacheT::MocFindIncludedHeader(
- std::string const& includerDir, std::string const& includeBase) const
+bool cmQtAutoMocUic::JobEvalCacheMocT::FindIncludedHeader(
+ SourceFileHandleT& headerHandle, cm::string_view includerDir,
+ cm::string_view includeBase)
{
- // Search in vicinity of the source
- {
- SourceFileHandleT res = MocFindHeader(includerDir + includeBase);
- if (res) {
- return res;
- }
- }
- // Search in include directories
- for (std::string const& path : MocConst().IncludePaths) {
- std::string testPath = cmStrCat(path, '/', includeBase);
- SourceFileHandleT res = MocFindHeader(testPath);
- if (res) {
- return res;
- }
- }
- // Return without success
- return SourceFileHandleT();
-}
+ // Clear search locations
+ SearchLocations.clear();
+
+ auto findHeader = [this,
+ &headerHandle](std::string const& basePath) -> bool {
+ bool found = false;
+ std::string const baseCollapsed =
+ this->Gen()->CollapseFullPathTS(cmStrCat(basePath, '.'));
+ for (std::string const& ext : this->BaseConst().HeaderExtensions) {
+ std::string const testPath = cmStrCat(baseCollapsed, ext);
+ cmFileTime fileTime;
+ if (!fileTime.Load(testPath)) {
+ // File not found
+ continue;
+ }
-cmQtAutoMocUic::SourceFileHandleT cmQtAutoMocUic::JobEvalCacheT::MocFindHeader(
- std::string const& basePath) const
-{
- std::string testPath;
- testPath.reserve(basePath.size() + 8);
- for (std::string const& ext : BaseConst().HeaderExtensions) {
- testPath.clear();
- testPath += basePath;
- testPath += '.';
- testPath += ext;
- cmFileTime fileTime;
- if (fileTime.Load(testPath)) {
- // Compute real path of the file
- testPath = cmSystemTools::CollapseFullPath(testPath,
- BaseConst().CurrentSourceDir);
// Return a known file if it exists already
{
auto it = BaseEval().Headers.find(testPath);
if (it != BaseEval().Headers.end()) {
- return it->second;
+ headerHandle = it->second;
+ found = true;
+ break;
}
}
+
// Created and return discovered file entry
- SourceFileHandleT& res = MocEval().HeadersDiscovered[testPath];
- if (!res) {
- res = std::make_shared<SourceFileT>(testPath);
- res->FileTime = fileTime;
- res->Moc = true;
+ {
+ SourceFileHandleT& handle = MocEval().HeadersDiscovered[testPath];
+ if (!handle) {
+ handle = std::make_shared<SourceFileT>(testPath);
+ handle->FileTime = fileTime;
+ handle->Moc = true;
+ }
+ headerHandle = handle;
+ found = true;
+ break;
}
- return res;
}
- }
- // Return without success
- return SourceFileHandleT();
-}
+ if (!found) {
+ this->SearchLocations.emplace_back(
+ cmQtAutoGen::ParentDir(baseCollapsed));
+ }
+ return found;
+ };
-std::string cmQtAutoMocUic::JobEvalCacheT::MocMessageTestHeaders(
- cm::string_view fileBase) const
-{
- std::string const exts =
- cmStrCat(".{", cmJoin(BaseConst().HeaderExtensions, ","), '}');
- // Compose result string
- std::string res = cmStrCat(" ", fileBase, exts, '\n');
+ // Search in vicinity of the source
+ if (findHeader(cmStrCat(includerDir, includeBase))) {
+ return true;
+ }
+ // Search in include directories
for (std::string const& path : MocConst().IncludePaths) {
- res += cmStrCat(" ", path, '/', fileBase, exts, '\n');
+ if (findHeader(cmStrCat(path, '/', includeBase))) {
+ return true;
+ }
}
- return res;
+ // Return without success
+ return false;
}
-bool cmQtAutoMocUic::JobEvalCacheT::MocRegisterIncluded(
+bool cmQtAutoMocUic::JobEvalCacheMocT::RegisterIncluded(
std::string const& includeString, SourceFileHandleT includerFileHandle,
SourceFileHandleT sourceFileHandle, bool sourceIsHeader) const
{
@@ -925,11 +913,11 @@ bool cmQtAutoMocUic::JobEvalCacheT::MocRegisterIncluded(
handle->OutputFile = Gen()->AbsoluteIncludePath(includeString);
// Register mapping in sources/headers map
- MocRegisterMapping(handle, sourceIsHeader);
+ RegisterMapping(handle, sourceIsHeader);
return true;
}
-void cmQtAutoMocUic::JobEvalCacheT::MocRegisterMapping(
+void cmQtAutoMocUic::JobEvalCacheMocT::RegisterMapping(
MappingHandleT mappingHandle, bool sourceIsHeader) const
{
auto& regMap =
@@ -947,17 +935,33 @@ void cmQtAutoMocUic::JobEvalCacheT::MocRegisterMapping(
}
}
-bool cmQtAutoMocUic::JobEvalCacheT::UicEval(SourceFileMapT const& fileMap)
+std::string cmQtAutoMocUic::JobEvalCacheMocT::MessageHeader(
+ cm::string_view headerBase) const
{
- for (auto const& pair : fileMap) {
- if (!UicEvalFile(pair.second)) {
- return false;
+ return Quoted(cmStrCat(
+ headerBase, ".{", cmJoin(this->BaseConst().HeaderExtensions, ","), '}'));
+}
+
+void cmQtAutoMocUic::JobEvalCacheUicT::Process()
+{
+ // Prepare buffers
+ SearchLocations.reserve((UicConst().SearchPaths.size() + 1) * 2);
+
+ // Evaluate headers
+ for (auto const& pair : BaseEval().Headers) {
+ if (!EvalFile(pair.second)) {
+ return;
+ }
+ }
+ // Evaluate sources
+ for (auto const& pair : BaseEval().Sources) {
+ if (!EvalFile(pair.second)) {
+ return;
}
}
- return true;
}
-bool cmQtAutoMocUic::JobEvalCacheT::UicEvalFile(
+bool cmQtAutoMocUic::JobEvalCacheUicT::EvalFile(
SourceFileHandleT const& sourceFileHandle)
{
SourceFileT const& sourceFile = *sourceFileHandle;
@@ -966,17 +970,25 @@ bool cmQtAutoMocUic::JobEvalCacheT::UicEvalFile(
return true;
}
- std::string const sourceDir = SubDirPrefix(sourceFile.FileName);
+ std::string const sourceDirPrefix = SubDirPrefix(sourceFile.FileName);
for (IncludeKeyT const& incKey : Include) {
- // Find .ui file name
- SourceFileHandleT uiFileHandle =
- UicFindIncludedUi(sourceFile.FileName, sourceDir, incKey);
- if (!uiFileHandle || UicConst().skipped(uiFileHandle->FileName)) {
+ // Find .ui file
+ UiName = cmStrCat(incKey.Base, ".ui");
+ if (!FindIncludedUi(sourceDirPrefix, incKey.Dir)) {
+ LogError(GenT::UIC,
+ cmStrCat(sourceFile.FileName, "\nincludes the uic file ",
+ Quoted(incKey.Key), ",\nbut the user interface file ",
+ Quoted(UiName),
+ "\ncould not be found in the following directories\n",
+ MessageSearchLocations()));
+ return false;
+ }
+ // Check if the file is skipped
+ if (UicConst().skipped(UiFileHandle->FileName)) {
continue;
}
// Register mapping
- if (!UicRegisterMapping(incKey.Key, std::move(uiFileHandle),
- sourceFileHandle)) {
+ if (!RegisterMapping(incKey.Key, sourceFileHandle)) {
return false;
}
}
@@ -984,15 +996,68 @@ bool cmQtAutoMocUic::JobEvalCacheT::UicEvalFile(
return true;
}
-bool cmQtAutoMocUic::JobEvalCacheT::UicRegisterMapping(
- std::string const& includeString, SourceFileHandleT uiFileHandle,
- SourceFileHandleT includerFileHandle)
+bool cmQtAutoMocUic::JobEvalCacheUicT::FindIncludedUi(
+ cm::string_view sourceDirPrefix, cm::string_view includePrefix)
+{
+ // Clear locations buffer
+ SearchLocations.clear();
+
+ auto findUi = [this](std::string const& testPath) -> bool {
+ std::string const fullPath = this->Gen()->CollapseFullPathTS(testPath);
+ cmFileTime fileTime;
+ if (!fileTime.Load(fullPath)) {
+ this->SearchLocations.emplace_back(cmQtAutoGen::ParentDir(fullPath));
+ return false;
+ }
+ // .ui file found in files system!
+ // Get or create .ui file handle
+ SourceFileHandleT& handle = this->UicEval().UiFiles[fullPath];
+ if (!handle) {
+ // The file wasn't registered, yet
+ handle = std::make_shared<SourceFileT>(fullPath);
+ handle->FileTime = fileTime;
+ }
+ this->UiFileHandle = handle;
+ return true;
+ };
+
+ // Vicinity of the source
+ if (findUi(cmStrCat(sourceDirPrefix, UiName))) {
+ return true;
+ }
+ if (!includePrefix.empty()) {
+ if (findUi(cmStrCat(sourceDirPrefix, includePrefix, UiName))) {
+ return true;
+ }
+ }
+ // Additional AUTOUIC search paths
+ auto const& searchPaths = UicConst().SearchPaths;
+ if (!searchPaths.empty()) {
+ for (std::string const& sPath : searchPaths) {
+ if (findUi(cmStrCat(sPath, '/', UiName))) {
+ return true;
+ }
+ }
+ if (!includePrefix.empty()) {
+ for (std::string const& sPath : searchPaths) {
+ if (findUi(cmStrCat(sPath, '/', includePrefix, UiName))) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+bool cmQtAutoMocUic::JobEvalCacheUicT::RegisterMapping(
+ std::string const& includeString, SourceFileHandleT includerFileHandle)
{
auto& Includes = Gen()->UicEval().Includes;
auto it = Includes.find(includeString);
if (it != Includes.end()) {
MappingHandleT const& handle = it->second;
- if (handle->SourceFile != uiFileHandle) {
+ if (handle->SourceFile != UiFileHandle) {
// The output file already gets generated - from a different .ui file!
std::string files =
cmStrCat(" ", Quoted(includerFileHandle->FileName), '\n');
@@ -1006,7 +1071,7 @@ bool cmQtAutoMocUic::JobEvalCacheT::UicRegisterMapping(
Quoted(includeString),
", but\nthe uic file would be generated from different "
"user interface files\n ",
- Quoted(uiFileHandle->FileName), " and\n ",
+ Quoted(UiFileHandle->FileName), " and\n ",
Quoted(handle->SourceFile->FileName),
".\nConsider to\n"
" - add a directory prefix to a \"ui_<NAME>.h\" include "
@@ -1022,7 +1087,7 @@ bool cmQtAutoMocUic::JobEvalCacheT::UicRegisterMapping(
MappingHandleT handle = std::make_shared<MappingT>();
handle->IncludeString = includeString;
handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
- handle->SourceFile = std::move(uiFileHandle);
+ handle->SourceFile = UiFileHandle;
handle->OutputFile = Gen()->AbsoluteIncludePath(includeString);
// Register mapping
Includes.emplace(includeString, std::move(handle));
@@ -1030,69 +1095,24 @@ bool cmQtAutoMocUic::JobEvalCacheT::UicRegisterMapping(
return true;
}
-cmQtAutoMocUic::SourceFileHandleT
-cmQtAutoMocUic::JobEvalCacheT::UicFindIncludedUi(
- std::string const& sourceFile, std::string const& sourceDir,
- IncludeKeyT const& incKey) const
+void cmQtAutoMocUic::JobEvalCacheFinishT::Process()
{
- std::string searchFileName = cmStrCat(incKey.Base, ".ui");
- // Collect search paths list
- std::vector<std::string> testFiles;
- {
- auto& searchPaths = UicConst().SearchPaths;
- testFiles.reserve((searchPaths.size() + 1) * 2);
-
- // Vicinity of the source
- testFiles.emplace_back(sourceDir + searchFileName);
- if (!incKey.Dir.empty()) {
- testFiles.emplace_back(cmStrCat(sourceDir, incKey.Dir, searchFileName));
- }
- // AUTOUIC search paths
- if (!searchPaths.empty()) {
- for (std::string const& sPath : searchPaths) {
- testFiles.emplace_back(cmStrCat(sPath, '/', searchFileName));
- }
- if (!incKey.Dir.empty()) {
- for (std::string const& sPath : searchPaths) {
- testFiles.emplace_back(
- cmStrCat(sPath, '/', incKey.Dir, searchFileName));
- }
- }
- }
- }
-
- // Search for the .ui file!
- for (std::string const& testFile : testFiles) {
- cmFileTime fileTime;
- if (fileTime.Load(testFile)) {
- // .ui file found in files system!
- std::string fullPath = cmSystemTools::CollapseFullPath(
- testFile, BaseConst().CurrentSourceDir);
- // Get or create .ui file handle
- SourceFileHandleT& handle = Gen()->UicEval().UiFiles[fullPath];
- if (!handle) {
- // The file wasn't registered, yet
- handle = std::make_shared<SourceFileT>(fullPath);
- handle->FileTime = fileTime;
- }
- return handle;
- }
- }
+ // Add discovered header parse jobs
+ Gen()->CreateParseJobs<JobParseHeaderT>(MocEval().HeadersDiscovered);
- // Log error
+ // Add dependency probing jobs
{
- std::string files;
- for (std::string const& testFile : testFiles) {
- files += cmStrCat(" ", Quoted(testFile), '\n');
+ // Add fence job to ensure all parsing has finished
+ Gen()->WorkerPool().EmplaceJob<JobFenceT>();
+ if (MocConst().Enabled) {
+ Gen()->WorkerPool().EmplaceJob<JobProbeDepsMocT>();
+ }
+ if (UicConst().Enabled) {
+ Gen()->WorkerPool().EmplaceJob<JobProbeDepsUicT>();
}
- LogFileError(
- GenT::UIC, sourceFile,
- cmStrCat("The file includes the uic file ", Quoted(incKey.Key),
- ",\nbut the user interface file ", Quoted(searchFileName),
- "\ncould not be found in the following locations\n", files));
+ // Add probe finish job
+ Gen()->WorkerPool().EmplaceJob<JobProbeDepsFinishT>();
}
-
- return SourceFileHandleT();
}
void cmQtAutoMocUic::JobProbeDepsMocT::Process()
@@ -1863,18 +1883,38 @@ void cmQtAutoMocUic::CreateParseJobs(SourceFileMapT const& sourceMap)
}
}
+/** Concurrently callable implementation of cmSystemTools::CollapseFullPath */
+std::string cmQtAutoMocUic::CollapseFullPathTS(std::string const& path) const
+{
+ std::lock_guard<std::mutex> guard(CMakeLibMutex_);
+ return cmSystemTools::CollapseFullPath(path, BaseConst().CurrentSourceDir);
+}
+
void cmQtAutoMocUic::InitJobs()
{
// Add moc_predefs.h job
if (MocConst().Enabled && !MocConst().PredefsCmd.empty()) {
WorkerPool().EmplaceJob<JobMocPredefsT>();
}
+
// Add header parse jobs
CreateParseJobs<JobParseHeaderT>(BaseEval().Headers);
// Add source parse jobs
CreateParseJobs<JobParseSourceT>(BaseEval().Sources);
- // Add evaluate job
- WorkerPool().EmplaceJob<JobEvalCacheT>();
+
+ // Add parse cache evaluations jobs
+ {
+ // Add a fence job to ensure all parsing has finished
+ WorkerPool().EmplaceJob<JobFenceT>();
+ if (MocConst().Enabled) {
+ WorkerPool().EmplaceJob<JobEvalCacheMocT>();
+ }
+ if (UicConst().Enabled) {
+ WorkerPool().EmplaceJob<JobEvalCacheUicT>();
+ }
+ // Add evaluate job
+ WorkerPool().EmplaceJob<JobEvalCacheFinishT>();
+ }
}
bool cmQtAutoMocUic::Process()
diff --git a/Source/cmQtAutoMocUic.h b/Source/cmQtAutoMocUic.h
index 3af1846..e480751 100644
--- a/Source/cmQtAutoMocUic.h
+++ b/Source/cmQtAutoMocUic.h
@@ -16,6 +16,7 @@
#include <cstddef>
#include <map>
#include <memory>
+#include <mutex>
#include <set>
#include <string>
#include <unordered_map>
@@ -384,34 +385,50 @@ public:
void Process() override;
};
- /** Evaluate cached file parse data. */
- class JobEvalCacheT : public JobFenceT
+ /** Evaluate cached file parse data - moc. */
+ class JobEvalCacheT : public JobT
+ {
+ protected:
+ std::string MessageSearchLocations() const;
+ std::vector<std::string> SearchLocations;
+ };
+
+ /** Evaluate cached file parse data - moc. */
+ class JobEvalCacheMocT : public JobEvalCacheT
{
void Process() override;
+ bool EvalHeader(SourceFileHandleT source);
+ bool EvalSource(SourceFileHandleT const& source);
+ bool FindIncludedHeader(SourceFileHandleT& headerHandle,
+ cm::string_view includerDir,
+ cm::string_view includeBase);
+ bool RegisterIncluded(std::string const& includeString,
+ SourceFileHandleT includerFileHandle,
+ SourceFileHandleT sourceFileHandle,
+ bool sourceIsHeader) const;
+ void RegisterMapping(MappingHandleT mappingHandle,
+ bool sourceIsHeader) const;
+ std::string MessageHeader(cm::string_view headerBase) const;
+ };
- // -- Moc
- bool MocEvalHeader(SourceFileHandleT source);
- bool MocEvalSource(SourceFileHandleT const& source);
- SourceFileHandleT MocFindIncludedHeader(
- std::string const& includerDir, std::string const& includeBase) const;
- SourceFileHandleT MocFindHeader(std::string const& basePath) const;
- std::string MocMessageTestHeaders(cm::string_view fileBase) const;
- bool MocRegisterIncluded(std::string const& includeString,
- SourceFileHandleT includerFileHandle,
- SourceFileHandleT sourceFileHandle,
- bool sourceIsHeader) const;
- void MocRegisterMapping(MappingHandleT mappingHandle,
- bool sourceIsHeader) const;
-
- // -- Uic
- bool UicEval(SourceFileMapT const& fileMap);
- bool UicEvalFile(SourceFileHandleT const& sourceFileHandle);
- SourceFileHandleT UicFindIncludedUi(std::string const& sourceFile,
- std::string const& sourceDir,
- IncludeKeyT const& incKey) const;
- bool UicRegisterMapping(std::string const& includeString,
- SourceFileHandleT uiFileHandle,
- SourceFileHandleT includerFileHandle);
+ /** Evaluate cached file parse data - uic. */
+ class JobEvalCacheUicT : public JobEvalCacheT
+ {
+ void Process() override;
+ bool EvalFile(SourceFileHandleT const& sourceFileHandle);
+ bool FindIncludedUi(cm::string_view sourceDirPrefix,
+ cm::string_view includePrefix);
+ bool RegisterMapping(std::string const& includeString,
+ SourceFileHandleT includerFileHandle);
+
+ std::string UiName;
+ SourceFileHandleT UiFileHandle;
+ };
+
+ /** Evaluate cached file parse data - finish */
+ class JobEvalCacheFinishT : public JobFenceT
+ {
+ void Process() override;
};
/** Dependency probing base job. */
@@ -505,6 +522,7 @@ public:
std::string AbsoluteIncludePath(cm::string_view relativePath) const;
template <class JOBTYPE>
void CreateParseJobs(SourceFileMapT const& sourceMap);
+ std::string CollapseFullPathTS(std::string const& path) const;
private:
// -- Utility accessors
@@ -541,6 +559,8 @@ private:
// -- Worker thread pool
std::atomic<bool> JobError_ = ATOMIC_VAR_INIT(false);
cmWorkerPool WorkerPool_;
+ // -- Concurrent processing
+ mutable std::mutex CMakeLibMutex_;
};
#endif