diff options
Diffstat (limited to 'Source/cmQtAutoGeneratorMocUic.cxx')
-rw-r--r-- | Source/cmQtAutoGeneratorMocUic.cxx | 1170 |
1 files changed, 435 insertions, 735 deletions
diff --git a/Source/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoGeneratorMocUic.cxx index ec1a1aa..80684b6 100644 --- a/Source/cmQtAutoGeneratorMocUic.cxx +++ b/Source/cmQtAutoGeneratorMocUic.cxx @@ -4,7 +4,7 @@ #include <algorithm> #include <array> -#include <cstddef> +#include <deque> #include <list> #include <memory> #include <set> @@ -153,11 +153,118 @@ bool cmQtAutoGeneratorMocUic::UicSettingsT::skipped( return (!Enabled || (SkipList.find(fileName) != SkipList.end())); } -void cmQtAutoGeneratorMocUic::JobParseT::Process(WorkerT& wrk) +void cmQtAutoGeneratorMocUic::JobT::LogError(GenT genType, + std::string const& message) const +{ + Gen()->AbortError(); + Gen()->Log().Error(genType, message); +} + +void cmQtAutoGeneratorMocUic::JobT::LogFileError( + GenT genType, std::string const& filename, std::string const& message) const +{ + Gen()->AbortError(); + Gen()->Log().ErrorFile(genType, filename, message); +} + +void cmQtAutoGeneratorMocUic::JobT::LogCommandError( + GenT genType, std::string const& message, + std::vector<std::string> const& command, std::string const& output) const +{ + Gen()->AbortError(); + Gen()->Log().ErrorCommand(genType, message, command, output); +} + +bool cmQtAutoGeneratorMocUic::JobT::RunProcess( + GenT genType, cmWorkerPool::ProcessResultT& result, + std::vector<std::string> const& command) +{ + // Log command + if (Log().Verbose()) { + std::string msg = "Running command:\n"; + msg += QuotedCommand(command); + msg += '\n'; + Log().Info(genType, msg); + } + return cmWorkerPool::JobT::RunProcess(result, command, + Gen()->Base().AutogenBuildDir); +} + +void cmQtAutoGeneratorMocUic::JobMocPredefsT::Process() +{ + // (Re)generate moc_predefs.h on demand + bool generate(false); + bool fileExists(FileSys().FileExists(Gen()->Moc().PredefsFileAbs)); + if (!fileExists) { + if (Log().Verbose()) { + std::string reason = "Generating "; + reason += Quoted(Gen()->Moc().PredefsFileRel); + reason += " because it doesn't exist"; + Log().Info(GenT::MOC, reason); + } + generate = true; + } else if (Gen()->Moc().SettingsChanged) { + if (Log().Verbose()) { + std::string reason = "Generating "; + reason += Quoted(Gen()->Moc().PredefsFileRel); + reason += " because the settings changed."; + Log().Info(GenT::MOC, reason); + } + generate = true; + } + if (generate) { + cmWorkerPool::ProcessResultT result; + { + // Compose command + std::vector<std::string> cmd = Gen()->Moc().PredefsCmd; + // Add includes + cmd.insert(cmd.end(), Gen()->Moc().Includes.begin(), + Gen()->Moc().Includes.end()); + // Add definitions + for (std::string const& def : Gen()->Moc().Definitions) { + cmd.push_back("-D" + def); + } + // Execute command + if (!RunProcess(GenT::MOC, result, cmd)) { + std::string emsg = "The content generation command for "; + emsg += Quoted(Gen()->Moc().PredefsFileRel); + emsg += " failed.\n"; + emsg += result.ErrorMessage; + LogCommandError(GenT::MOC, emsg, cmd, result.StdOut); + } + } + + // (Re)write predefs file only on demand + if (!result.error()) { + if (!fileExists || + FileSys().FileDiffers(Gen()->Moc().PredefsFileAbs, result.StdOut)) { + if (FileSys().FileWrite(Gen()->Moc().PredefsFileAbs, result.StdOut)) { + // Success + } else { + std::string emsg = "Writing "; + emsg += Quoted(Gen()->Moc().PredefsFileRel); + emsg += " failed."; + LogFileError(GenT::MOC, Gen()->Moc().PredefsFileAbs, emsg); + } + } else { + // Touch to update the time stamp + if (Log().Verbose()) { + std::string msg = "Touching "; + msg += Quoted(Gen()->Moc().PredefsFileRel); + msg += "."; + Log().Info(GenT::MOC, msg); + } + FileSys().Touch(Gen()->Moc().PredefsFileAbs); + } + } + } +} + +void cmQtAutoGeneratorMocUic::JobParseT::Process() { if (AutoMoc && Header) { // Don't parse header for moc if the file is included by a source already - if (wrk.Gen().ParallelMocIncluded(FileName)) { + if (Gen()->ParallelMocIncluded(FileName)) { AutoMoc = false; } } @@ -165,35 +272,32 @@ void cmQtAutoGeneratorMocUic::JobParseT::Process(WorkerT& wrk) if (AutoMoc || AutoUic) { std::string error; MetaT meta; - if (wrk.FileSys().FileRead(meta.Content, FileName, &error)) { + if (FileSys().FileRead(meta.Content, FileName, &error)) { if (!meta.Content.empty()) { - meta.FileDir = wrk.FileSys().SubDirPrefix(FileName); - meta.FileBase = - wrk.FileSys().GetFilenameWithoutLastExtension(FileName); + meta.FileDir = FileSys().SubDirPrefix(FileName); + meta.FileBase = FileSys().GetFilenameWithoutLastExtension(FileName); bool success = true; if (AutoMoc) { if (Header) { - success = ParseMocHeader(wrk, meta); + success = ParseMocHeader(meta); } else { - success = ParseMocSource(wrk, meta); + success = ParseMocSource(meta); } } if (AutoUic && success) { - ParseUic(wrk, meta); + ParseUic(meta); } } else { - wrk.LogFileWarning(GenT::GEN, FileName, "The source file is empty"); + Log().WarningFile(GenT::GEN, FileName, "The source file is empty"); } } else { - wrk.LogFileError(GenT::GEN, FileName, - "Could not read the file: " + error); + LogFileError(GenT::GEN, FileName, "Could not read the file: " + error); } } } -bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk, - MetaT const& meta) +bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(MetaT const& meta) { struct JobPre { @@ -211,7 +315,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk, }; // Check if this source file contains a relevant macro - std::string const ownMacro = wrk.Moc().FindMacro(meta.Content); + std::string const ownMacro = Gen()->Moc().FindMacro(meta.Content); // Extract moc includes from file std::deque<MocInclude> mocIncsUsc; @@ -220,11 +324,11 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk, if (meta.Content.find("moc") != std::string::npos) { const char* contentChars = meta.Content.c_str(); cmsys::RegularExpressionMatch match; - while (wrk.Moc().RegExpInclude.find(contentChars, match)) { + while (Gen()->Moc().RegExpInclude.find(contentChars, match)) { std::string incString = match.match(2); - std::string incDir(wrk.FileSys().SubDirPrefix(incString)); + std::string incDir(FileSys().SubDirPrefix(incString)); std::string incBase = - wrk.FileSys().GetFilenameWithoutLastExtension(incString); + FileSys().GetFilenameWithoutLastExtension(incString); if (cmHasLiteralPrefix(incBase, "moc_")) { // moc_<BASE>.cxx // Remove the moc_ part from the base name @@ -253,10 +357,10 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk, // Process moc_<BASE>.cxx includes for (const MocInclude& mocInc : mocIncsUsc) { std::string const header = - MocFindIncludedHeader(wrk, meta.FileDir, mocInc.Dir + mocInc.Base); + MocFindIncludedHeader(meta.FileDir, mocInc.Dir + mocInc.Base); if (!header.empty()) { // Check if header is skipped - if (wrk.Moc().skipped(header)) { + if (Gen()->Moc().skipped(header)) { continue; } // Register moc job @@ -271,9 +375,9 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk, std::string emsg = "The file includes the moc file "; emsg += Quoted(mocInc.Inc); emsg += ", but the header "; - emsg += Quoted(MocStringHeaders(wrk, mocInc.Base)); + emsg += Quoted(MocStringHeaders(mocInc.Base)); emsg += " could not be found."; - wrk.LogFileError(GenT::MOC, FileName, emsg); + LogFileError(GenT::MOC, FileName, emsg); } return false; } @@ -282,7 +386,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk, // Process <BASE>.moc includes for (const MocInclude& mocInc : mocIncsDot) { const bool ownMoc = (mocInc.Base == meta.FileBase); - if (wrk.Moc().RelaxedMode) { + if (Gen()->Moc().RelaxedMode) { // Relaxed mode if (!ownMacro.empty() && ownMoc) { // Add self @@ -292,10 +396,10 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk, // In relaxed mode try to find a header instead but issue a warning. // This is for KDE4 compatibility std::string const header = - MocFindIncludedHeader(wrk, meta.FileDir, mocInc.Dir + mocInc.Base); + MocFindIncludedHeader(meta.FileDir, mocInc.Dir + mocInc.Base); if (!header.empty()) { // Check if header is skipped - if (wrk.Moc().skipped(header)) { + if (Gen()->Moc().skipped(header)) { continue; } // Register moc job @@ -305,14 +409,14 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk, std::string emsg = "The file includes the moc file "; emsg += Quoted(mocInc.Inc); emsg += ", but does not contain a "; - emsg += wrk.Moc().MacrosString(); + emsg += Gen()->Moc().MacrosString(); emsg += " macro.\nRunning moc on\n "; emsg += Quoted(header); emsg += "!\nBetter include "; emsg += Quoted("moc_" + mocInc.Base + ".cpp"); emsg += " for a compatibility with strict mode.\n" "(CMAKE_AUTOMOC_RELAXED_MODE warning)\n"; - wrk.LogFileWarning(GenT::MOC, FileName, emsg); + Log().WarningFile(GenT::MOC, FileName, emsg); } else { std::string emsg = "The file includes the moc file "; emsg += Quoted(mocInc.Inc); @@ -324,7 +428,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk, emsg += Quoted("moc_" + mocInc.Base + ".cpp"); emsg += " for compatibility with strict mode.\n" "(CMAKE_AUTOMOC_RELAXED_MODE warning)\n"; - wrk.LogFileWarning(GenT::MOC, FileName, emsg); + Log().WarningFile(GenT::MOC, FileName, emsg); } } } else { @@ -334,9 +438,9 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk, emsg += ", which seems to be the moc file from a different " "source file.\nCMAKE_AUTOMOC_RELAXED_MODE: Also a " "matching header "; - emsg += Quoted(MocStringHeaders(wrk, mocInc.Base)); + emsg += Quoted(MocStringHeaders(mocInc.Base)); emsg += " could not be found."; - wrk.LogFileError(GenT::MOC, FileName, emsg); + LogFileError(GenT::MOC, FileName, emsg); } return false; } @@ -352,9 +456,9 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk, std::string emsg = "The file includes the moc file "; emsg += Quoted(mocInc.Inc); emsg += ", but does not contain a "; - emsg += wrk.Moc().MacrosString(); + emsg += Gen()->Moc().MacrosString(); emsg += " macro."; - wrk.LogFileWarning(GenT::MOC, FileName, emsg); + Log().WarningFile(GenT::MOC, FileName, emsg); } } else { // Don't allow <BASE>.moc include other than self in strict mode @@ -365,7 +469,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk, "source file.\nThis is not supported. Include "; emsg += Quoted(meta.FileBase + ".moc"); emsg += " to run moc on this source file."; - wrk.LogFileError(GenT::MOC, FileName, emsg); + LogFileError(GenT::MOC, FileName, emsg); } return false; } @@ -379,7 +483,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk, // foo.cpp instead of foo.h, because otherwise it won't build. // But warn, since this is not how it is supposed to be used. // This is for KDE4 compatibility. - if (wrk.Moc().RelaxedMode && ownMocUscIncluded) { + if (Gen()->Moc().RelaxedMode && ownMocUscIncluded) { JobPre uscJobPre; // Remove underscore job request { @@ -408,7 +512,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk, emsg += Quoted(meta.FileBase + ".moc"); emsg += " for compatibility with strict mode.\n" "(CMAKE_AUTOMOC_RELAXED_MODE warning)"; - wrk.LogFileWarning(GenT::MOC, FileName, emsg); + Log().WarningFile(GenT::MOC, FileName, emsg); } // Add own source job jobs.emplace_back( @@ -423,7 +527,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk, emsg += "!\nConsider to\n - add #include \""; emsg += meta.FileBase; emsg += ".moc\"\n - enable SKIP_AUTOMOC for this file"; - wrk.LogFileError(GenT::MOC, FileName, emsg); + LogFileError(GenT::MOC, FileName, emsg); } return false; } @@ -431,76 +535,80 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk, // Convert pre jobs to actual jobs for (JobPre& jobPre : jobs) { - JobHandleT jobHandle = cm::make_unique<JobMocT>( + cmWorkerPool::JobHandleT jobHandle = cm::make_unique<JobMocT>( std::move(jobPre.SourceFile), FileName, std::move(jobPre.IncludeString)); if (jobPre.self) { // Read dependencies from this source - static_cast<JobMocT&>(*jobHandle).FindDependencies(wrk, meta.Content); + JobMocT& jobMoc = static_cast<JobMocT&>(*jobHandle); + Gen()->Moc().FindDependencies(meta.Content, jobMoc.Depends); + jobMoc.DependsValid = true; } - if (!wrk.Gen().ParallelJobPushMoc(jobHandle)) { + if (!Gen()->ParallelJobPushMoc(std::move(jobHandle))) { return false; } } return true; } -bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocHeader(WorkerT& wrk, - MetaT const& meta) +bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocHeader(MetaT const& meta) { bool success = true; - std::string const macroName = wrk.Moc().FindMacro(meta.Content); + std::string const macroName = Gen()->Moc().FindMacro(meta.Content); if (!macroName.empty()) { - JobHandleT jobHandle = cm::make_unique<JobMocT>( + cmWorkerPool::JobHandleT jobHandle = cm::make_unique<JobMocT>( std::string(FileName), std::string(), std::string()); // Read dependencies from this source - static_cast<JobMocT&>(*jobHandle).FindDependencies(wrk, meta.Content); - success = wrk.Gen().ParallelJobPushMoc(jobHandle); + { + JobMocT& jobMoc = static_cast<JobMocT&>(*jobHandle); + Gen()->Moc().FindDependencies(meta.Content, jobMoc.Depends); + jobMoc.DependsValid = true; + } + success = Gen()->ParallelJobPushMoc(std::move(jobHandle)); } return success; } std::string cmQtAutoGeneratorMocUic::JobParseT::MocStringHeaders( - WorkerT& wrk, std::string const& fileBase) const + std::string const& fileBase) const { std::string res = fileBase; res += ".{"; - res += cmJoin(wrk.Base().HeaderExtensions, ","); + res += cmJoin(Gen()->Base().HeaderExtensions, ","); res += "}"; return res; } std::string cmQtAutoGeneratorMocUic::JobParseT::MocFindIncludedHeader( - WorkerT& wrk, std::string const& includerDir, std::string const& includeBase) + std::string const& includerDir, std::string const& includeBase) { std::string header; // Search in vicinity of the source - if (!wrk.Base().FindHeader(header, includerDir + includeBase)) { + if (!Gen()->Base().FindHeader(header, includerDir + includeBase)) { // Search in include directories - for (std::string const& path : wrk.Moc().IncludePaths) { + for (std::string const& path : Gen()->Moc().IncludePaths) { std::string fullPath = path; fullPath.push_back('/'); fullPath += includeBase; - if (wrk.Base().FindHeader(header, fullPath)) { + if (Gen()->Base().FindHeader(header, fullPath)) { break; } } } // Sanitize if (!header.empty()) { - header = wrk.FileSys().GetRealPath(header); + header = FileSys().GetRealPath(header); } return header; } -bool cmQtAutoGeneratorMocUic::JobParseT::ParseUic(WorkerT& wrk, - MetaT const& meta) +bool cmQtAutoGeneratorMocUic::JobParseT::ParseUic(MetaT const& meta) { bool success = true; if (meta.Content.find("ui_") != std::string::npos) { const char* contentChars = meta.Content.c_str(); cmsys::RegularExpressionMatch match; - while (wrk.Uic().RegExpInclude.find(contentChars, match)) { - if (!ParseUicInclude(wrk, meta, match.match(2))) { + while (Gen()->Uic().RegExpInclude.find(contentChars, match)) { + if (!ParseUicInclude(meta, match.match(2))) { success = false; break; } @@ -511,15 +619,15 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseUic(WorkerT& wrk, } bool cmQtAutoGeneratorMocUic::JobParseT::ParseUicInclude( - WorkerT& wrk, MetaT const& meta, std::string&& includeString) + MetaT const& meta, std::string&& includeString) { bool success = false; - std::string uiInputFile = UicFindIncludedFile(wrk, meta, includeString); + std::string uiInputFile = UicFindIncludedFile(meta, includeString); if (!uiInputFile.empty()) { - if (!wrk.Uic().skipped(uiInputFile)) { - JobHandleT jobHandle = cm::make_unique<JobUicT>( + if (!Gen()->Uic().skipped(uiInputFile)) { + cmWorkerPool::JobHandleT jobHandle = cm::make_unique<JobUicT>( std::move(uiInputFile), FileName, std::move(includeString)); - success = wrk.Gen().ParallelJobPushUic(jobHandle); + success = Gen()->ParallelJobPushUic(std::move(jobHandle)); } else { // A skipped file is successful success = true; @@ -529,16 +637,16 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseUicInclude( } std::string cmQtAutoGeneratorMocUic::JobParseT::UicFindIncludedFile( - WorkerT& wrk, MetaT const& meta, std::string const& includeString) + MetaT const& meta, std::string const& includeString) { std::string res; std::string searchFile = - wrk.FileSys().GetFilenameWithoutLastExtension(includeString).substr(3); + FileSys().GetFilenameWithoutLastExtension(includeString).substr(3); searchFile += ".ui"; // Collect search paths list std::deque<std::string> testFiles; { - std::string const searchPath = wrk.FileSys().SubDirPrefix(includeString); + std::string const searchPath = FileSys().SubDirPrefix(includeString); std::string searchFileFull; if (!searchPath.empty()) { @@ -554,12 +662,12 @@ std::string cmQtAutoGeneratorMocUic::JobParseT::UicFindIncludedFile( } } // AUTOUIC search paths - if (!wrk.Uic().SearchPaths.empty()) { - for (std::string const& sPath : wrk.Uic().SearchPaths) { + if (!Gen()->Uic().SearchPaths.empty()) { + for (std::string const& sPath : Gen()->Uic().SearchPaths) { testFiles.push_back((sPath + "/").append(searchFile)); } if (!searchPath.empty()) { - for (std::string const& sPath : wrk.Uic().SearchPaths) { + for (std::string const& sPath : Gen()->Uic().SearchPaths) { testFiles.push_back((sPath + "/").append(searchFileFull)); } } @@ -568,8 +676,8 @@ std::string cmQtAutoGeneratorMocUic::JobParseT::UicFindIncludedFile( // Search for the .ui file! for (std::string const& testFile : testFiles) { - if (wrk.FileSys().FileExists(testFile)) { - res = wrk.FileSys().GetRealPath(testFile); + if (FileSys().FileExists(testFile)) { + res = FileSys().GetRealPath(testFile); break; } } @@ -584,162 +692,141 @@ std::string cmQtAutoGeneratorMocUic::JobParseT::UicFindIncludedFile( emsg += Quoted(testFile); emsg += "\n"; } - wrk.LogFileError(GenT::UIC, FileName, emsg); + LogFileError(GenT::UIC, FileName, emsg); } return res; } -void cmQtAutoGeneratorMocUic::JobMocPredefsT::Process(WorkerT& wrk) +void cmQtAutoGeneratorMocUic::JobPostParseT::Process() { - // (Re)generate moc_predefs.h on demand - bool generate(false); - bool fileExists(wrk.FileSys().FileExists(wrk.Moc().PredefsFileAbs)); - if (!fileExists) { - if (wrk.Log().Verbose()) { - std::string reason = "Generating "; - reason += Quoted(wrk.Moc().PredefsFileRel); - reason += " because it doesn't exist"; - wrk.LogInfo(GenT::MOC, reason); - } - generate = true; - } else if (wrk.Moc().SettingsChanged) { - if (wrk.Log().Verbose()) { - std::string reason = "Generating "; - reason += Quoted(wrk.Moc().PredefsFileRel); - reason += " because the settings changed."; - wrk.LogInfo(GenT::MOC, reason); - } - generate = true; + if (Gen()->Moc().Enabled) { + // Add mocs compilations fence job + Gen()->WorkerPool().EmplaceJob<JobMocsCompilationT>(); } - if (generate) { - ProcessResultT result; - { - // Compose command - std::vector<std::string> cmd = wrk.Moc().PredefsCmd; - // Add includes - cmd.insert(cmd.end(), wrk.Moc().Includes.begin(), - wrk.Moc().Includes.end()); - // Add definitions - for (std::string const& def : wrk.Moc().Definitions) { - cmd.push_back("-D" + def); - } - // Execute command - if (!wrk.RunProcess(GenT::MOC, result, cmd)) { - std::string emsg = "The content generation command for "; - emsg += Quoted(wrk.Moc().PredefsFileRel); - emsg += " failed.\n"; - emsg += result.ErrorMessage; - wrk.LogCommandError(GenT::MOC, emsg, cmd, result.StdOut); - } + // Add finish job + Gen()->WorkerPool().EmplaceJob<JobFinishT>(); +} + +void cmQtAutoGeneratorMocUic::JobMocsCompilationT::Process() +{ + // Compose mocs compilation file content + std::string content = + "// This file is autogenerated. Changes will be overwritten.\n"; + if (Gen()->MocAutoFiles().empty()) { + // Placeholder content + content += "// No files found that require moc or the moc files are " + "included\n"; + content += "enum some_compilers { need_more_than_nothing };\n"; + } else { + // Valid content + char const sbeg = Gen()->Base().MultiConfig ? '<' : '"'; + char const send = Gen()->Base().MultiConfig ? '>' : '"'; + for (std::string const& mocfile : Gen()->MocAutoFiles()) { + content += "#include "; + content += sbeg; + content += mocfile; + content += send; + content += '\n'; } + } - // (Re)write predefs file only on demand - if (!result.error()) { - if (!fileExists || - wrk.FileSys().FileDiffers(wrk.Moc().PredefsFileAbs, result.StdOut)) { - std::string error; - if (wrk.FileSys().FileWrite(wrk.Moc().PredefsFileAbs, result.StdOut, - &error)) { - // Success - } else { - std::string emsg = "Writing "; - emsg += Quoted(wrk.Moc().PredefsFileRel); - emsg += " failed. "; - emsg += error; - wrk.LogFileError(GenT::MOC, wrk.Moc().PredefsFileAbs, emsg); - } - } else { - // Touch to update the time stamp - if (wrk.Log().Verbose()) { - std::string msg = "Touching "; - msg += Quoted(wrk.Moc().PredefsFileRel); - msg += "."; - wrk.LogInfo(GenT::MOC, msg); - } - wrk.FileSys().Touch(wrk.Moc().PredefsFileAbs); - } + std::string const& compAbs = Gen()->Moc().CompFileAbs; + if (FileSys().FileDiffers(compAbs, content)) { + // Actually write mocs compilation file + if (Log().Verbose()) { + Log().Info(GenT::MOC, "Generating MOC compilation " + compAbs); } + if (!FileSys().FileWrite(compAbs, content)) { + LogFileError(GenT::MOC, compAbs, + "mocs compilation file writing failed."); + } + } else if (Gen()->MocAutoFileUpdated()) { + // Only touch mocs compilation file + if (Log().Verbose()) { + Log().Info(GenT::MOC, "Touching mocs compilation " + compAbs); + } + FileSys().Touch(compAbs); } } void cmQtAutoGeneratorMocUic::JobMocT::FindDependencies( - WorkerT& wrk, std::string const& content) + std::string const& content) { - wrk.Moc().FindDependencies(content, Depends); + Gen()->Moc().FindDependencies(content, Depends); DependsValid = true; } -void cmQtAutoGeneratorMocUic::JobMocT::Process(WorkerT& wrk) +void cmQtAutoGeneratorMocUic::JobMocT::Process() { // Compute build file name if (!IncludeString.empty()) { - BuildFile = wrk.Base().AutogenIncludeDir; + BuildFile = Gen()->Base().AutogenIncludeDir; BuildFile += '/'; BuildFile += IncludeString; } else { // Relative build path - std::string relPath = wrk.FileSys().GetFilePathChecksum(SourceFile); + std::string relPath = FileSys().GetFilePathChecksum(SourceFile); relPath += "/moc_"; - relPath += wrk.FileSys().GetFilenameWithoutLastExtension(SourceFile); + relPath += FileSys().GetFilenameWithoutLastExtension(SourceFile); // Register relative file path with duplication check - relPath = wrk.Gen().ParallelMocAutoRegister(relPath); + relPath = Gen()->ParallelMocAutoRegister(relPath); // Absolute build path - if (wrk.Base().MultiConfig) { - BuildFile = wrk.Base().AutogenIncludeDir; + if (Gen()->Base().MultiConfig) { + BuildFile = Gen()->Base().AutogenIncludeDir; BuildFile += '/'; BuildFile += relPath; } else { - BuildFile = wrk.Base().AbsoluteBuildPath(relPath); + BuildFile = Gen()->Base().AbsoluteBuildPath(relPath); } } - if (UpdateRequired(wrk)) { - GenerateMoc(wrk); + if (UpdateRequired()) { + GenerateMoc(); } } -bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk) +bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired() { - bool const verbose = wrk.Gen().Log().Verbose(); + bool const verbose = Log().Verbose(); // Test if the build file exists - if (!wrk.FileSys().FileExists(BuildFile)) { + if (!FileSys().FileExists(BuildFile)) { if (verbose) { std::string reason = "Generating "; reason += Quoted(BuildFile); reason += " from its source file "; reason += Quoted(SourceFile); reason += " because it doesn't exist"; - wrk.LogInfo(GenT::MOC, reason); + Log().Info(GenT::MOC, reason); } return true; } // Test if any setting changed - if (wrk.Moc().SettingsChanged) { + if (Gen()->Moc().SettingsChanged) { if (verbose) { std::string reason = "Generating "; reason += Quoted(BuildFile); reason += " from "; reason += Quoted(SourceFile); reason += " because the MOC settings changed"; - wrk.LogInfo(GenT::MOC, reason); + Log().Info(GenT::MOC, reason); } return true; } // Test if the moc_predefs file is newer - if (!wrk.Moc().PredefsFileAbs.empty()) { + if (!Gen()->Moc().PredefsFileAbs.empty()) { bool isOlder = false; { std::string error; - isOlder = wrk.FileSys().FileIsOlderThan( - BuildFile, wrk.Moc().PredefsFileAbs, &error); + isOlder = FileSys().FileIsOlderThan(BuildFile, + Gen()->Moc().PredefsFileAbs, &error); if (!isOlder && !error.empty()) { - wrk.LogError(GenT::MOC, error); + LogError(GenT::MOC, error); return false; } } @@ -748,8 +835,8 @@ bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk) std::string reason = "Generating "; reason += Quoted(BuildFile); reason += " because it's older than: "; - reason += Quoted(wrk.Moc().PredefsFileAbs); - wrk.LogInfo(GenT::MOC, reason); + reason += Quoted(Gen()->Moc().PredefsFileAbs); + Log().Info(GenT::MOC, reason); } return true; } @@ -760,9 +847,9 @@ bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk) bool isOlder = false; { std::string error; - isOlder = wrk.FileSys().FileIsOlderThan(BuildFile, SourceFile, &error); + isOlder = FileSys().FileIsOlderThan(BuildFile, SourceFile, &error); if (!isOlder && !error.empty()) { - wrk.LogError(GenT::MOC, error); + LogError(GenT::MOC, error); return false; } } @@ -772,7 +859,7 @@ bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk) reason += Quoted(BuildFile); reason += " because it's older than its source file "; reason += Quoted(SourceFile); - wrk.LogInfo(GenT::MOC, reason); + Log().Info(GenT::MOC, reason); } return true; } @@ -785,7 +872,7 @@ bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk) std::string content; { std::string error; - if (!wrk.FileSys().FileRead(content, SourceFile, &error)) { + if (!FileSys().FileRead(content, SourceFile, &error)) { std::string emsg = "Could not read file\n "; emsg += Quoted(SourceFile); emsg += "\nrequired by moc include "; @@ -794,20 +881,20 @@ bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk) emsg += Quoted(IncluderFile); emsg += ".\n"; emsg += error; - wrk.LogError(GenT::MOC, emsg); + LogError(GenT::MOC, emsg); return false; } } - FindDependencies(wrk, content); + FindDependencies(content); } // Check dependency timestamps std::string error; - std::string sourceDir = wrk.FileSys().SubDirPrefix(SourceFile); + std::string sourceDir = FileSys().SubDirPrefix(SourceFile); for (std::string const& depFileRel : Depends) { std::string depFileAbs = - wrk.Moc().FindIncludedFile(sourceDir, depFileRel); + Gen()->Moc().FindIncludedFile(sourceDir, depFileRel); if (!depFileAbs.empty()) { - if (wrk.FileSys().FileIsOlderThan(BuildFile, depFileAbs, &error)) { + if (FileSys().FileIsOlderThan(BuildFile, depFileAbs, &error)) { if (verbose) { std::string reason = "Generating "; reason += Quoted(BuildFile); @@ -815,18 +902,18 @@ bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk) reason += Quoted(SourceFile); reason += " because it is older than it's dependency file "; reason += Quoted(depFileAbs); - wrk.LogInfo(GenT::MOC, reason); + Log().Info(GenT::MOC, reason); } return true; } if (!error.empty()) { - wrk.LogError(GenT::MOC, error); + LogError(GenT::MOC, error); return false; } } else { std::string message = "Could not find dependency file "; message += Quoted(depFileRel); - wrk.LogFileWarning(GenT::MOC, SourceFile, message); + Log().WarningFile(GenT::MOC, SourceFile, message); } } } @@ -834,41 +921,40 @@ bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk) return false; } -void cmQtAutoGeneratorMocUic::JobMocT::GenerateMoc(WorkerT& wrk) +void cmQtAutoGeneratorMocUic::JobMocT::GenerateMoc() { // Make sure the parent directory exists - if (!wrk.FileSys().MakeParentDirectory(BuildFile)) { - wrk.LogFileError(GenT::MOC, BuildFile, - "Could not create parent directory."); + if (!FileSys().MakeParentDirectory(BuildFile)) { + LogFileError(GenT::MOC, BuildFile, "Could not create parent directory."); return; } { // Compose moc command std::vector<std::string> cmd; - cmd.push_back(wrk.Moc().Executable); + cmd.push_back(Gen()->Moc().Executable); // Add options - cmd.insert(cmd.end(), wrk.Moc().AllOptions.begin(), - wrk.Moc().AllOptions.end()); + cmd.insert(cmd.end(), Gen()->Moc().AllOptions.begin(), + Gen()->Moc().AllOptions.end()); // Add predefs include - if (!wrk.Moc().PredefsFileAbs.empty()) { + if (!Gen()->Moc().PredefsFileAbs.empty()) { cmd.emplace_back("--include"); - cmd.push_back(wrk.Moc().PredefsFileAbs); + cmd.push_back(Gen()->Moc().PredefsFileAbs); } cmd.emplace_back("-o"); cmd.push_back(BuildFile); cmd.push_back(SourceFile); // Execute moc command - ProcessResultT result; - if (wrk.RunProcess(GenT::MOC, result, cmd)) { + cmWorkerPool::ProcessResultT result; + if (RunProcess(GenT::MOC, result, cmd)) { // Moc command success // Print moc output if (!result.StdOut.empty()) { - wrk.LogInfo(GenT::MOC, result.StdOut); + Log().Info(GenT::MOC, result.StdOut); } // Notify the generator that a not included file changed (on demand) if (IncludeString.empty()) { - wrk.Gen().ParallelMocAutoUpdated(); + Gen()->ParallelMocAutoUpdated(); } } else { // Moc command failed @@ -879,51 +965,51 @@ void cmQtAutoGeneratorMocUic::JobMocT::GenerateMoc(WorkerT& wrk) emsg += Quoted(BuildFile); emsg += ".\n"; emsg += result.ErrorMessage; - wrk.LogCommandError(GenT::MOC, emsg, cmd, result.StdOut); + LogCommandError(GenT::MOC, emsg, cmd, result.StdOut); } - wrk.FileSys().FileRemove(BuildFile); + FileSys().FileRemove(BuildFile); } } } -void cmQtAutoGeneratorMocUic::JobUicT::Process(WorkerT& wrk) +void cmQtAutoGeneratorMocUic::JobUicT::Process() { // Compute build file name - BuildFile = wrk.Base().AutogenIncludeDir; + BuildFile = Gen()->Base().AutogenIncludeDir; BuildFile += '/'; BuildFile += IncludeString; - if (UpdateRequired(wrk)) { - GenerateUic(wrk); + if (UpdateRequired()) { + GenerateUic(); } } -bool cmQtAutoGeneratorMocUic::JobUicT::UpdateRequired(WorkerT& wrk) +bool cmQtAutoGeneratorMocUic::JobUicT::UpdateRequired() { - bool const verbose = wrk.Gen().Log().Verbose(); + bool const verbose = Log().Verbose(); // Test if the build file exists - if (!wrk.FileSys().FileExists(BuildFile)) { + if (!FileSys().FileExists(BuildFile)) { if (verbose) { std::string reason = "Generating "; reason += Quoted(BuildFile); reason += " from its source file "; reason += Quoted(SourceFile); reason += " because it doesn't exist"; - wrk.LogInfo(GenT::UIC, reason); + Log().Info(GenT::UIC, reason); } return true; } // Test if the uic settings changed - if (wrk.Uic().SettingsChanged) { + if (Gen()->Uic().SettingsChanged) { if (verbose) { std::string reason = "Generating "; reason += Quoted(BuildFile); reason += " from "; reason += Quoted(SourceFile); reason += " because the UIC settings changed"; - wrk.LogInfo(GenT::UIC, reason); + Log().Info(GenT::UIC, reason); } return true; } @@ -933,9 +1019,9 @@ bool cmQtAutoGeneratorMocUic::JobUicT::UpdateRequired(WorkerT& wrk) bool isOlder = false; { std::string error; - isOlder = wrk.FileSys().FileIsOlderThan(BuildFile, SourceFile, &error); + isOlder = FileSys().FileIsOlderThan(BuildFile, SourceFile, &error); if (!isOlder && !error.empty()) { - wrk.LogError(GenT::UIC, error); + LogError(GenT::UIC, error); return false; } } @@ -945,7 +1031,7 @@ bool cmQtAutoGeneratorMocUic::JobUicT::UpdateRequired(WorkerT& wrk) reason += Quoted(BuildFile); reason += " because it's older than its source file "; reason += Quoted(SourceFile); - wrk.LogInfo(GenT::UIC, reason); + Log().Info(GenT::UIC, reason); } return true; } @@ -954,37 +1040,36 @@ bool cmQtAutoGeneratorMocUic::JobUicT::UpdateRequired(WorkerT& wrk) return false; } -void cmQtAutoGeneratorMocUic::JobUicT::GenerateUic(WorkerT& wrk) +void cmQtAutoGeneratorMocUic::JobUicT::GenerateUic() { // Make sure the parent directory exists - if (!wrk.FileSys().MakeParentDirectory(BuildFile)) { - wrk.LogFileError(GenT::UIC, BuildFile, - "Could not create parent directory."); + if (!FileSys().MakeParentDirectory(BuildFile)) { + LogFileError(GenT::UIC, BuildFile, "Could not create parent directory."); return; } { // Compose uic command std::vector<std::string> cmd; - cmd.push_back(wrk.Uic().Executable); + cmd.push_back(Gen()->Uic().Executable); { - std::vector<std::string> allOpts = wrk.Uic().TargetOptions; - auto optionIt = wrk.Uic().Options.find(SourceFile); - if (optionIt != wrk.Uic().Options.end()) { + std::vector<std::string> allOpts = Gen()->Uic().TargetOptions; + auto optionIt = Gen()->Uic().Options.find(SourceFile); + if (optionIt != Gen()->Uic().Options.end()) { UicMergeOptions(allOpts, optionIt->second, - (wrk.Base().QtVersionMajor == 5)); + (Gen()->Base().QtVersionMajor == 5)); } cmd.insert(cmd.end(), allOpts.begin(), allOpts.end()); } cmd.emplace_back("-o"); - cmd.push_back(BuildFile); - cmd.push_back(SourceFile); + cmd.emplace_back(BuildFile); + cmd.emplace_back(SourceFile); - ProcessResultT result; - if (wrk.RunProcess(GenT::UIC, result, cmd)) { + cmWorkerPool::ProcessResultT result; + if (RunProcess(GenT::UIC, result, cmd)) { // Uic command success // Print uic output if (!result.StdOut.empty()) { - wrk.LogInfo(GenT::UIC, result.StdOut); + Log().Info(GenT::UIC, result.StdOut); } } else { // Uic command failed @@ -997,144 +1082,16 @@ void cmQtAutoGeneratorMocUic::JobUicT::GenerateUic(WorkerT& wrk) emsg += Quoted(IncluderFile); emsg += ".\n"; emsg += result.ErrorMessage; - wrk.LogCommandError(GenT::UIC, emsg, cmd, result.StdOut); + LogCommandError(GenT::UIC, emsg, cmd, result.StdOut); } - wrk.FileSys().FileRemove(BuildFile); - } - } -} - -cmQtAutoGeneratorMocUic::WorkerT::WorkerT(cmQtAutoGeneratorMocUic* gen, - uv_loop_t* uvLoop) - : Gen_(gen) -{ - // Initialize uv asynchronous callback for process starting - ProcessRequest_.init(*uvLoop, &WorkerT::UVProcessStart, this); - // Start thread - Thread_ = std::thread(&WorkerT::Loop, this); -} - -cmQtAutoGeneratorMocUic::WorkerT::~WorkerT() -{ - // Join thread - if (Thread_.joinable()) { - Thread_.join(); - } -} - -void cmQtAutoGeneratorMocUic::WorkerT::LogInfo( - GenT genType, std::string const& message) const -{ - Log().Info(genType, message); -} - -void cmQtAutoGeneratorMocUic::WorkerT::LogWarning( - GenT genType, std::string const& message) const -{ - Log().Warning(genType, message); -} - -void cmQtAutoGeneratorMocUic::WorkerT::LogFileWarning( - GenT genType, std::string const& filename, std::string const& message) const -{ - Log().WarningFile(genType, filename, message); -} - -void cmQtAutoGeneratorMocUic::WorkerT::LogError( - GenT genType, std::string const& message) const -{ - Gen().ParallelRegisterJobError(); - Log().Error(genType, message); -} - -void cmQtAutoGeneratorMocUic::WorkerT::LogFileError( - GenT genType, std::string const& filename, std::string const& message) const -{ - Gen().ParallelRegisterJobError(); - Log().ErrorFile(genType, filename, message); -} - -void cmQtAutoGeneratorMocUic::WorkerT::LogCommandError( - GenT genType, std::string const& message, - std::vector<std::string> const& command, std::string const& output) const -{ - Gen().ParallelRegisterJobError(); - Log().ErrorCommand(genType, message, command, output); -} - -bool cmQtAutoGeneratorMocUic::WorkerT::RunProcess( - GenT genType, ProcessResultT& result, - std::vector<std::string> const& command) -{ - if (command.empty()) { - return false; - } - - // Create process instance - { - std::lock_guard<std::mutex> lock(ProcessMutex_); - Process_ = cm::make_unique<ReadOnlyProcessT>(); - Process_->setup(&result, true, command, Gen().Base().AutogenBuildDir); - } - - // Send asynchronous process start request to libuv loop - ProcessRequest_.send(); - - // Log command - if (this->Log().Verbose()) { - std::string msg = "Running command:\n"; - msg += QuotedCommand(command); - msg += '\n'; - this->LogInfo(genType, msg); - } - - // Wait until the process has been finished and destroyed - { - std::unique_lock<std::mutex> ulock(ProcessMutex_); - while (Process_) { - ProcessCondition_.wait(ulock); + FileSys().FileRemove(BuildFile); } } - return !result.error(); } -void cmQtAutoGeneratorMocUic::WorkerT::Loop() +void cmQtAutoGeneratorMocUic::JobFinishT::Process() { - while (true) { - Gen().WorkerSwapJob(JobHandle_); - if (JobHandle_) { - JobHandle_->Process(*this); - } else { - break; - } - } -} - -void cmQtAutoGeneratorMocUic::WorkerT::UVProcessStart(uv_async_t* handle) -{ - auto& wrk = *reinterpret_cast<WorkerT*>(handle->data); - { - std::lock_guard<std::mutex> lock(wrk.ProcessMutex_); - if (wrk.Process_ && !wrk.Process_->IsStarted()) { - wrk.Process_->start(handle->loop, [&wrk] { wrk.UVProcessFinished(); }); - } - } - - if (!wrk.Process_->IsStarted()) { - wrk.UVProcessFinished(); - } -} - -void cmQtAutoGeneratorMocUic::WorkerT::UVProcessFinished() -{ - { - std::lock_guard<std::mutex> lock(ProcessMutex_); - if (Process_ && (Process_->IsFinished() || !Process_->IsStarted())) { - Process_.reset(); - } - } - // Notify idling thread - ProcessCondition_.notify_one(); + Gen()->AbortSuccess(); } cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic() @@ -1147,24 +1104,9 @@ cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic() "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]"); Uic_.RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+" "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]"); - - // Initialize libuv loop - uv_disable_stdio_inheritance(); -#ifdef CMAKE_UV_SIGNAL_HACK - UVHackRAII_ = cm::make_unique<cmUVSignalHackRAII>(); -#endif - UVLoop_ = cm::make_unique<uv_loop_t>(); - uv_loop_init(UVLoop()); - - // Initialize libuv asynchronous iteration request - UVRequest().init(*UVLoop(), &cmQtAutoGeneratorMocUic::UVPollStage, this); } -cmQtAutoGeneratorMocUic::~cmQtAutoGeneratorMocUic() -{ - // Close libuv loop - uv_loop_close(UVLoop()); -} +cmQtAutoGeneratorMocUic::~cmQtAutoGeneratorMocUic() = default; bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) { @@ -1364,7 +1306,7 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) Moc_.PredefsCmd = InfoGetList("AM_MOC_PREDEFS_CMD"); // Install moc predefs job if (!Moc().PredefsCmd.empty()) { - JobQueues_.MocPredefs.emplace_back(cm::make_unique<JobMocPredefsT>()); + WorkerPool().EmplaceJob<JobMocPredefsT>(); } } @@ -1400,46 +1342,48 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) } // - Headers and sources + // Add sources { - auto addHeader = [this](std::string&& hdr, bool moc, bool uic) { - this->JobQueues_.Headers.emplace_back( - cm::make_unique<JobParseT>(std::move(hdr), moc, uic, true)); - }; auto addSource = [this](std::string&& src, bool moc, bool uic) { - this->JobQueues_.Sources.emplace_back( - cm::make_unique<JobParseT>(std::move(src), moc, uic, false)); + WorkerPool().EmplaceJob<JobParseT>(std::move(src), moc, uic, false); }; - - // Add headers - for (std::string& hdr : InfoGetList("AM_HEADERS")) { - addHeader(std::move(hdr), true, true); + for (std::string& src : InfoGetList("AM_SOURCES")) { + addSource(std::move(src), true, true); } if (Moc().Enabled) { - for (std::string& hdr : InfoGetList("AM_MOC_HEADERS")) { - addHeader(std::move(hdr), true, false); + for (std::string& src : InfoGetList("AM_MOC_SOURCES")) { + addSource(std::move(src), true, false); } } if (Uic().Enabled) { - for (std::string& hdr : InfoGetList("AM_UIC_HEADERS")) { - addHeader(std::move(hdr), false, true); + for (std::string& src : InfoGetList("AM_UIC_SOURCES")) { + addSource(std::move(src), false, true); } } - - // Add sources - for (std::string& src : InfoGetList("AM_SOURCES")) { - addSource(std::move(src), true, true); + } + // Add Fence job + WorkerPool().EmplaceJob<JobFenceT>(); + // Add headers + { + auto addHeader = [this](std::string&& hdr, bool moc, bool uic) { + WorkerPool().EmplaceJob<JobParseT>(std::move(hdr), moc, uic, true); + }; + for (std::string& hdr : InfoGetList("AM_HEADERS")) { + addHeader(std::move(hdr), true, true); } if (Moc().Enabled) { - for (std::string& src : InfoGetList("AM_MOC_SOURCES")) { - addSource(std::move(src), true, false); + for (std::string& hdr : InfoGetList("AM_MOC_HEADERS")) { + addHeader(std::move(hdr), true, false); } } if (Uic().Enabled) { - for (std::string& src : InfoGetList("AM_UIC_SOURCES")) { - addSource(std::move(src), false, true); + for (std::string& hdr : InfoGetList("AM_UIC_HEADERS")) { + addHeader(std::move(hdr), false, true); } } } + // Addpost parse fence job + WorkerPool().EmplaceJob<JobPostParseT>(); // Init derived information // ------------------------ @@ -1536,93 +1480,20 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) bool cmQtAutoGeneratorMocUic::Process() { - // Run libuv event loop - UVRequest().send(); - if (uv_run(UVLoop(), UV_RUN_DEFAULT) == 0) { - if (JobError_) { - return false; - } - } else { + SettingsFileRead(); + if (!CreateDirectories()) { return false; } - return true; -} - -void cmQtAutoGeneratorMocUic::UVPollStage(uv_async_t* handle) -{ - reinterpret_cast<cmQtAutoGeneratorMocUic*>(handle->data)->PollStage(); -} -void cmQtAutoGeneratorMocUic::PollStage() -{ - switch (Stage_) { - case StageT::SETTINGS_READ: - SettingsFileRead(); - SetStage(StageT::CREATE_DIRECTORIES); - break; - case StageT::CREATE_DIRECTORIES: - CreateDirectories(); - SetStage(StageT::PARSE_SOURCES); - break; - case StageT::PARSE_SOURCES: - if (ThreadsStartJobs(JobQueues_.Sources)) { - SetStage(StageT::PARSE_HEADERS); - } - break; - case StageT::PARSE_HEADERS: - if (ThreadsStartJobs(JobQueues_.Headers)) { - SetStage(StageT::MOC_PREDEFS); - } - break; - case StageT::MOC_PREDEFS: - if (ThreadsStartJobs(JobQueues_.MocPredefs)) { - SetStage(StageT::MOC_PROCESS); - } - break; - case StageT::MOC_PROCESS: - if (ThreadsStartJobs(JobQueues_.Moc)) { - SetStage(StageT::MOCS_COMPILATION); - } - break; - case StageT::MOCS_COMPILATION: - if (ThreadsJobsDone()) { - MocGenerateCompilation(); - SetStage(StageT::UIC_PROCESS); - } - break; - case StageT::UIC_PROCESS: - if (ThreadsStartJobs(JobQueues_.Uic)) { - SetStage(StageT::SETTINGS_WRITE); - } - break; - case StageT::SETTINGS_WRITE: - SettingsFileWrite(); - SetStage(StageT::FINISH); - break; - case StageT::FINISH: - if (ThreadsJobsDone()) { - // Clear all libuv handles - ThreadsStop(); - UVRequest().reset(); - // Set highest END stage manually - Stage_ = StageT::END; - } - break; - case StageT::END: - break; + if (!WorkerPool_.Process(Base().NumThreads, this)) { + return false; } -} -void cmQtAutoGeneratorMocUic::SetStage(StageT stage) -{ if (JobError_) { - stage = StageT::FINISH; - } - // Only allow to increase the stage - if (Stage_ < stage) { - Stage_ = stage; - UVRequest().send(); + return false; } + + return SettingsFileWrite(); } void cmQtAutoGeneratorMocUic::SettingsFileRead() @@ -1691,11 +1562,10 @@ void cmQtAutoGeneratorMocUic::SettingsFileRead() } } -void cmQtAutoGeneratorMocUic::SettingsFileWrite() +bool cmQtAutoGeneratorMocUic::SettingsFileWrite() { - std::lock_guard<std::mutex> jobsLock(JobsMutex_); // Only write if any setting changed - if (!JobError_ && (Moc().SettingsChanged || Uic().SettingsChanged)) { + if (Moc().SettingsChanged || Uic().SettingsChanged) { if (Log().Verbose()) { Log().Info(GenT::GEN, "Writing settings file " + Quoted(SettingsFile_)); } @@ -1721,246 +1591,136 @@ void cmQtAutoGeneratorMocUic::SettingsFileWrite() "Settings file writing failed. " + error); // Remove old settings file to trigger a full rebuild on the next run FileSys().FileRemove(SettingsFile_); - RegisterJobError(); + return false; } } + return true; } -void cmQtAutoGeneratorMocUic::CreateDirectories() +bool cmQtAutoGeneratorMocUic::CreateDirectories() { // Create AUTOGEN include directory if (!FileSys().MakeDirectory(Base().AutogenIncludeDir)) { Log().ErrorFile(GenT::GEN, Base().AutogenIncludeDir, "Could not create directory."); - RegisterJobError(); + return false; } + return true; } -bool cmQtAutoGeneratorMocUic::ThreadsStartJobs(JobQueueT& queue) +// Private method that requires cmQtAutoGeneratorMocUic::JobsMutex_ to be +// locked +void cmQtAutoGeneratorMocUic::Abort(bool error) { - bool done = false; - std::size_t queueSize = queue.size(); - - // Change the active queue - { - std::lock_guard<std::mutex> jobsLock(JobsMutex_); - // Check if there are still unfinished jobs from the previous queue - if (JobsRemain_ == 0) { - if (!JobThreadsAbort_) { - JobQueue_.swap(queue); - JobsRemain_ = queueSize; - } else { - // Abort requested - queue.clear(); - queueSize = 0; - } - done = true; - } + if (error) { + JobError_.store(true); } + WorkerPool_.Abort(); +} - if (done && (queueSize != 0)) { - // Start new threads on demand - if (Workers_.empty()) { - Workers_.resize(Base().NumThreads); - for (auto& item : Workers_) { - item = cm::make_unique<WorkerT>(this, UVLoop()); +bool cmQtAutoGeneratorMocUic::ParallelJobPushMoc( + cmWorkerPool::JobHandleT&& jobHandle) +{ + JobMocT const& mocJob(static_cast<JobMocT&>(*jobHandle)); + // Do additional tests if this is an included moc job + if (!mocJob.IncludeString.empty()) { + std::lock_guard<std::mutex> guard(MocMetaMutex_); + // Register included moc file + MocIncludedFiles_.emplace(mocJob.SourceFile); + + // Check if the same moc file would be generated from a different + // source file. + auto const range = MocIncludes_.equal_range(mocJob.IncludeString); + for (auto it = range.first; it != range.second; ++it) { + if (it->second[0] == mocJob.SourceFile) { + // The output file already gets generated + return true; } - } else { - // Notify threads - if (queueSize == 1) { - JobsConditionRead_.notify_one(); - } else { - JobsConditionRead_.notify_all(); + { + // The output file already gets generated - from a different source + // file! + std::string error = "The two source files\n "; + error += Quoted(mocJob.IncluderFile); + error += " and\n "; + error += Quoted(it->second[1]); + error += "\ncontain the same moc include string "; + error += Quoted(mocJob.IncludeString); + error += "\nbut the moc file would be generated from different " + "source files\n "; + error += Quoted(mocJob.SourceFile); + error += " and\n "; + error += Quoted(it->second[0]); + error += ".\nConsider to\n" + "- not include the \"moc_<NAME>.cpp\" file\n" + "- add a directory prefix to a \"<NAME>.moc\" include " + "(e.g \"sub/<NAME>.moc\")\n" + "- rename the source file(s)\n"; + Log().Error(GenT::MOC, error); + AbortError(); + return false; } } - } - - return done; -} -void cmQtAutoGeneratorMocUic::ThreadsStop() -{ - if (!Workers_.empty()) { - // Clear all jobs - { - std::lock_guard<std::mutex> jobsLock(JobsMutex_); - JobThreadsAbort_ = true; - JobsRemain_ -= JobQueue_.size(); - JobQueue_.clear(); - - JobQueues_.Sources.clear(); - JobQueues_.Headers.clear(); - JobQueues_.MocPredefs.clear(); - JobQueues_.Moc.clear(); - JobQueues_.Uic.clear(); - } - // Wake threads - JobsConditionRead_.notify_all(); - // Join and clear threads - Workers_.clear(); + // We're still here so register this job + MocIncludes_.emplace_hint(range.first, mocJob.IncludeString, + std::array<std::string, 2>{ + { mocJob.SourceFile, mocJob.IncluderFile } }); } + return WorkerPool_.PushJob(std::move(jobHandle)); } -bool cmQtAutoGeneratorMocUic::ThreadsJobsDone() +bool cmQtAutoGeneratorMocUic::ParallelJobPushUic( + cmWorkerPool::JobHandleT&& jobHandle) { - std::lock_guard<std::mutex> jobsLock(JobsMutex_); - return (JobsRemain_ == 0); -} - -void cmQtAutoGeneratorMocUic::WorkerSwapJob(JobHandleT& jobHandle) -{ - bool const jobProcessed(jobHandle); - if (jobProcessed) { - jobHandle.reset(); - } + const JobUicT& uicJob(static_cast<JobUicT&>(*jobHandle)); { - std::unique_lock<std::mutex> jobsLock(JobsMutex_); - // Reduce the remaining job count and notify the libuv loop - // when all jobs are done - if (jobProcessed) { - --JobsRemain_; - if (JobsRemain_ == 0) { - UVRequest().send(); + std::lock_guard<std::mutex> guard(UicMetaMutex_); + // Check if the same uic file would be generated from a different + // source file. + auto const range = UicIncludes_.equal_range(uicJob.IncludeString); + for (auto it = range.first; it != range.second; ++it) { + if (it->second[0] == uicJob.SourceFile) { + // The output file already gets generated + return true; } - } - // Wait for new jobs - while (!JobThreadsAbort_ && JobQueue_.empty()) { - JobsConditionRead_.wait(jobsLock); - } - // Try to pick up a new job handle - if (!JobThreadsAbort_ && !JobQueue_.empty()) { - jobHandle = std::move(JobQueue_.front()); - JobQueue_.pop_front(); - } - } -} - -void cmQtAutoGeneratorMocUic::ParallelRegisterJobError() -{ - std::lock_guard<std::mutex> jobsLock(JobsMutex_); - RegisterJobError(); -} - -// Private method that requires cmQtAutoGeneratorMocUic::JobsMutex_ to be -// locked -void cmQtAutoGeneratorMocUic::RegisterJobError() -{ - JobError_ = true; - if (!JobThreadsAbort_) { - JobThreadsAbort_ = true; - // Clear remaining jobs - if (JobsRemain_ != 0) { - JobsRemain_ -= JobQueue_.size(); - JobQueue_.clear(); - } - } -} - -bool cmQtAutoGeneratorMocUic::ParallelJobPushMoc(JobHandleT& jobHandle) -{ - std::lock_guard<std::mutex> jobsLock(JobsMutex_); - if (!JobThreadsAbort_) { - bool pushJobHandle = true; - // Do additional tests if this is an included moc job - const JobMocT& mocJob(static_cast<JobMocT&>(*jobHandle)); - if (!mocJob.IncludeString.empty()) { - // Register included moc file and look for collisions - MocIncludedFiles_.emplace(mocJob.SourceFile); - if (!MocIncludedStrings_.emplace(mocJob.IncludeString).second) { - // Another source file includes the same moc file! - for (const JobHandleT& otherHandle : JobQueues_.Moc) { - const JobMocT& otherJob(static_cast<JobMocT&>(*otherHandle)); - if (otherJob.IncludeString == mocJob.IncludeString) { - // Check if the same moc file would be generated from different - // source files which is an error. - if (otherJob.SourceFile != mocJob.SourceFile) { - // Include string collision - std::string error = "The two source files\n "; - error += Quoted(mocJob.IncluderFile); - error += " and\n "; - error += Quoted(otherJob.IncluderFile); - error += "\ncontain the same moc include string "; - error += Quoted(mocJob.IncludeString); - error += "\nbut the moc file would be generated from different " - "source files\n "; - error += Quoted(mocJob.SourceFile); - error += " and\n "; - error += Quoted(otherJob.SourceFile); - error += ".\nConsider to\n" - "- not include the \"moc_<NAME>.cpp\" file\n" - "- add a directory prefix to a \"<NAME>.moc\" include " - "(e.g \"sub/<NAME>.moc\")\n" - "- rename the source file(s)\n"; - Log().Error(GenT::MOC, error); - RegisterJobError(); - } - // Do not push this job in since the included moc file already - // gets generated by an other job. - pushJobHandle = false; - break; - } - } + { + // The output file already gets generated - from a different .ui + // file! + std::string error = "The two source files\n "; + error += Quoted(uicJob.IncluderFile); + error += " and\n "; + error += Quoted(it->second[1]); + error += "\ncontain the same uic include string "; + error += Quoted(uicJob.IncludeString); + error += "\nbut the uic file would be generated from different " + "source files\n "; + error += Quoted(uicJob.SourceFile); + error += " and\n "; + error += Quoted(it->second[0]); + error += + ".\nConsider to\n" + "- add a directory prefix to a \"ui_<NAME>.h\" include " + "(e.g \"sub/ui_<NAME>.h\")\n" + "- rename the <NAME>.ui file(s) and adjust the \"ui_<NAME>.h\" " + "include(s)\n"; + Log().Error(GenT::UIC, error); + AbortError(); + return false; } } - // Push job on demand - if (pushJobHandle) { - JobQueues_.Moc.emplace_back(std::move(jobHandle)); - } - } - return !JobError_; -} -bool cmQtAutoGeneratorMocUic::ParallelJobPushUic(JobHandleT& jobHandle) -{ - std::lock_guard<std::mutex> jobsLock(JobsMutex_); - if (!JobThreadsAbort_) { - bool pushJobHandle = true; - // Look for include collisions. - const JobUicT& uicJob(static_cast<JobUicT&>(*jobHandle)); - for (const JobHandleT& otherHandle : JobQueues_.Uic) { - const JobUicT& otherJob(static_cast<JobUicT&>(*otherHandle)); - if (otherJob.IncludeString == uicJob.IncludeString) { - // Check if the same uic file would be generated from different - // source files which would be an error. - if (otherJob.SourceFile != uicJob.SourceFile) { - // Include string collision - std::string error = "The two source files\n "; - error += Quoted(uicJob.IncluderFile); - error += " and\n "; - error += Quoted(otherJob.IncluderFile); - error += "\ncontain the same uic include string "; - error += Quoted(uicJob.IncludeString); - error += "\nbut the uic file would be generated from different " - "source files\n "; - error += Quoted(uicJob.SourceFile); - error += " and\n "; - error += Quoted(otherJob.SourceFile); - error += - ".\nConsider to\n" - "- add a directory prefix to a \"ui_<NAME>.h\" include " - "(e.g \"sub/ui_<NAME>.h\")\n" - "- rename the <NAME>.ui file(s) and adjust the \"ui_<NAME>.h\" " - "include(s)\n"; - Log().Error(GenT::UIC, error); - RegisterJobError(); - } - // Do not push this job in since the uic file already - // gets generated by an other job. - pushJobHandle = false; - break; - } - } - if (pushJobHandle) { - JobQueues_.Uic.emplace_back(std::move(jobHandle)); - } + // We're still here so register this job + UicIncludes_.emplace_hint(range.first, uicJob.IncludeString, + std::array<std::string, 2>{ + { uicJob.SourceFile, uicJob.IncluderFile } }); } - return !JobError_; + return WorkerPool_.PushJob(std::move(jobHandle)); } bool cmQtAutoGeneratorMocUic::ParallelMocIncluded( std::string const& sourceFile) { - std::lock_guard<std::mutex> mocLock(JobsMutex_); + std::lock_guard<std::mutex> guard(MocMetaMutex_); return (MocIncludedFiles_.find(sourceFile) != MocIncludedFiles_.end()); } @@ -1969,7 +1729,7 @@ std::string cmQtAutoGeneratorMocUic::ParallelMocAutoRegister( { std::string res; { - std::lock_guard<std::mutex> mocLock(JobsMutex_); + std::lock_guard<std::mutex> mocLock(MocMetaMutex_); res = baseName; res += ".cpp"; if (MocAutoFiles_.find(res) == MocAutoFiles_.end()) { @@ -1990,63 +1750,3 @@ std::string cmQtAutoGeneratorMocUic::ParallelMocAutoRegister( } return res; } - -void cmQtAutoGeneratorMocUic::ParallelMocAutoUpdated() -{ - std::lock_guard<std::mutex> mocLock(JobsMutex_); - MocAutoFileUpdated_ = true; -} - -void cmQtAutoGeneratorMocUic::MocGenerateCompilation() -{ - std::lock_guard<std::mutex> mocLock(JobsMutex_); - if (!JobError_ && Moc().Enabled) { - // Write mocs compilation build file - { - // Compose mocs compilation file content - std::string content = - "// This file is autogenerated. Changes will be overwritten.\n"; - if (MocAutoFiles_.empty()) { - // Placeholder content - content += "// No files found that require moc or the moc files are " - "included\n"; - content += "enum some_compilers { need_more_than_nothing };\n"; - } else { - // Valid content - char const sbeg = Base().MultiConfig ? '<' : '"'; - char const send = Base().MultiConfig ? '>' : '"'; - for (std::string const& mocfile : MocAutoFiles_) { - content += "#include "; - content += sbeg; - content += mocfile; - content += send; - content += '\n'; - } - } - - std::string const& compAbs = Moc().CompFileAbs; - if (FileSys().FileDiffers(compAbs, content)) { - // Actually write mocs compilation file - if (Log().Verbose()) { - Log().Info(GenT::MOC, "Generating MOC compilation " + compAbs); - } - std::string error; - if (!FileSys().FileWrite(compAbs, content, &error)) { - Log().ErrorFile(GenT::MOC, compAbs, - "mocs compilation file writing failed. " + error); - RegisterJobError(); - return; - } - } else if (MocAutoFileUpdated_) { - // Only touch mocs compilation file - if (Log().Verbose()) { - Log().Info(GenT::MOC, "Touching mocs compilation " + compAbs); - } - FileSys().Touch(compAbs); - } - } - // Write mocs compilation wrapper file - if (Base().MultiConfig) { - } - } -} |