diff options
-rw-r--r-- | Source/cmQtAutoMocUic.cxx | 508 | ||||
-rw-r--r-- | Source/cmQtAutoMocUic.h | 70 |
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 |