summaryrefslogtreecommitdiffstats
path: root/Source/cmQtAutoMocUic.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmQtAutoMocUic.cxx')
-rw-r--r--Source/cmQtAutoMocUic.cxx1129
1 files changed, 614 insertions, 515 deletions
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 40ebdde..4e4875e 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -2,14 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmQtAutoMocUic.h"
-#include <algorithm>
-#include <initializer_list>
-#include <list>
-#include <set>
-#include <utility>
-
-#include "cm_memory.hxx"
-
#include "cmAlgorithms.h"
#include "cmCryptoHash.h"
#include "cmGeneratedFileStream.h"
@@ -17,9 +9,13 @@
#include "cmQtAutoGen.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cm_memory.hxx"
#include "cmake.h"
#include "cmsys/FStream.hxx"
+#include <algorithm>
+#include <set>
+#include <utility>
#if defined(__APPLE__)
# include <unistd.h>
#endif
@@ -238,13 +234,6 @@ void cmQtAutoMocUic::JobT::LogError(GenT genType,
Gen()->Log().Error(genType, message);
}
-void cmQtAutoMocUic::JobT::LogFileError(GenT genType, cm::string_view filename,
- cm::string_view message) const
-{
- Gen()->AbortError();
- Gen()->Log().ErrorFile(genType, filename, message);
-}
-
void cmQtAutoMocUic::JobT::LogCommandError(
GenT genType, cm::string_view message,
std::vector<std::string> const& command, std::string const& output) const
@@ -269,6 +258,7 @@ bool cmQtAutoMocUic::JobT::RunProcess(GenT genType,
info.empty() || cmHasSuffix(info, '\n') ? "" : "\n",
QuotedCommand(command), '\n'));
}
+ // Run command
return cmWorkerPool::JobT::RunProcess(result, command,
BaseConst().AutogenBuildDir);
}
@@ -283,24 +273,21 @@ void cmQtAutoMocUic::JobMocPredefsT::Process()
if (!Update(reason.get())) {
return;
}
- std::string const& predefsFileRel = MocConst().PredefsFileRel;
std::string const& predefsFileAbs = MocConst().PredefsFileAbs;
{
cmWorkerPool::ProcessResultT result;
{
// Compose command
std::vector<std::string> cmd = MocConst().PredefsCmd;
- // Add includes
- cmAppend(cmd, MocConst().Includes);
// Add definitions
- for (std::string const& def : MocConst().Definitions) {
- cmd.emplace_back("-D" + def);
- }
+ cmAppend(cmd, MocConst().OptionsDefinitions);
+ // Add includes
+ cmAppend(cmd, MocConst().OptionsIncludes);
// Execute command
if (!RunProcess(GenT::MOC, result, cmd, reason.get())) {
LogCommandError(GenT::MOC,
cmStrCat("The content generation command for ",
- Quoted(predefsFileRel), " failed.\n",
+ MessagePath(predefsFileAbs), " failed.\n",
result.ErrorMessage),
cmd, result.StdOut);
return;
@@ -310,19 +297,20 @@ void cmQtAutoMocUic::JobMocPredefsT::Process()
// (Re)write predefs file only on demand
if (cmQtAutoGenerator::FileDiffers(predefsFileAbs, result.StdOut)) {
if (!cmQtAutoGenerator::FileWrite(predefsFileAbs, result.StdOut)) {
- LogFileError(GenT::MOC, predefsFileAbs,
- cmStrCat("Writing ", Quoted(predefsFileRel), " failed."));
+ LogError(
+ GenT::MOC,
+ cmStrCat("Writing ", MessagePath(predefsFileAbs), " failed."));
return;
}
} else {
// Touch to update the time stamp
if (Log().Verbose()) {
- Log().Info(GenT::MOC, "Touching " + Quoted(predefsFileRel));
+ Log().Info(GenT::MOC, "Touching " + MessagePath(predefsFileAbs));
}
if (!cmSystemTools::Touch(predefsFileAbs, false)) {
- LogFileError(
- GenT::MOC, predefsFileAbs,
- cmStrCat("Touching ", Quoted(predefsFileAbs), " failed."));
+ LogError(
+ GenT::MOC,
+ cmStrCat("Touching ", MessagePath(predefsFileAbs), " failed."));
return;
}
}
@@ -330,7 +318,9 @@ void cmQtAutoMocUic::JobMocPredefsT::Process()
// Read file time afterwards
if (!MocEval().PredefsTime.Load(predefsFileAbs)) {
- LogFileError(GenT::MOC, predefsFileAbs, "File time reading failed.");
+ LogError(GenT::MOC,
+ cmStrCat("Reading the file time of ", MessagePath(predefsFileAbs),
+ " failed."));
return;
}
}
@@ -340,7 +330,7 @@ bool cmQtAutoMocUic::JobMocPredefsT::Update(std::string* reason) const
// Test if the file exists
if (!MocEval().PredefsTime.Load(MocConst().PredefsFileAbs)) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", Quoted(MocConst().PredefsFileRel),
+ *reason = cmStrCat("Generating ", MessagePath(MocConst().PredefsFileAbs),
", because it doesn't exist.");
}
return true;
@@ -349,7 +339,7 @@ bool cmQtAutoMocUic::JobMocPredefsT::Update(std::string* reason) const
// Test if the settings changed
if (MocConst().SettingsChanged) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", Quoted(MocConst().PredefsFileRel),
+ *reason = cmStrCat("Generating ", MessagePath(MocConst().PredefsFileAbs),
", because the moc settings changed.");
}
return true;
@@ -362,8 +352,9 @@ bool cmQtAutoMocUic::JobMocPredefsT::Update(std::string* reason) const
if (execTime.Load(exec)) {
if (MocEval().PredefsTime.Older(execTime)) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", Quoted(MocConst().PredefsFileRel),
- " because it is older than ", Quoted(exec), '.');
+ *reason =
+ cmStrCat("Generating ", MessagePath(MocConst().PredefsFileAbs),
+ " because it is older than ", MessagePath(exec), '.');
}
return true;
}
@@ -380,19 +371,21 @@ bool cmQtAutoMocUic::JobParseT::ReadFile()
std::string const& fileName = FileHandle->FileName;
// Write info
if (Log().Verbose()) {
- Log().Info(GenT::GEN, "Parsing " + Quoted(fileName));
+ Log().Info(GenT::GEN, cmStrCat("Parsing ", MessagePath(fileName)));
}
// Read file content
{
std::string error;
if (!cmQtAutoGenerator::FileRead(Content, fileName, &error)) {
- LogFileError(GenT::GEN, fileName, "Could not read the file: " + error);
+ LogError(
+ GenT::GEN,
+ cmStrCat("Could not read ", MessagePath(fileName), ".\n", error));
return false;
}
}
// Warn if empty
if (Content.empty()) {
- Log().WarningFile(GenT::GEN, fileName, "The file is empty.");
+ Log().Warning(GenT::GEN, cmStrCat(MessagePath(fileName), " is empty."));
return false;
}
return true;
@@ -555,37 +548,35 @@ void cmQtAutoMocUic::JobParseSourceT::Process()
}
}
-void cmQtAutoMocUic::JobEvaluateT::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 += MessagePath(path);
+ res += '\n';
+ }
+ return res;
+}
+
+void cmQtAutoMocUic::JobEvalCacheMocT::Process()
+{
+ // Evaluate headers
+ for (auto const& pair : BaseEval().Headers) {
+ if (!EvalHeader(pair.second)) {
+ return;
}
}
- // Evaluate for uic
- if (UicConst().Enabled) {
- if (!UicEval(BaseEval().Headers) || !UicEval(BaseEval().Sources)) {
+ // Evaluate sources
+ for (auto const& pair : BaseEval().Sources) {
+ if (!EvalSource(pair.second)) {
return;
}
}
-
- // Add discovered header parse jobs
- Gen()->CreateParseJobs<JobParseHeaderT>(MocEval().HeadersDiscovered);
- // Add generate job after
- Gen()->WorkerPool().EmplaceJob<JobGenerateT>();
}
-bool cmQtAutoMocUic::JobEvaluateT::MocEvalHeader(SourceFileHandleT source)
+bool cmQtAutoMocUic::JobEvalCacheMocT::EvalHeader(SourceFileHandleT source)
{
SourceFileT const& sourceFile = *source;
auto const& parseData = sourceFile.ParseData->Moc;
@@ -606,13 +597,13 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalHeader(SourceFileHandleT source)
}
// Register mapping in headers map
- MocRegisterMapping(handle, true);
+ RegisterMapping(handle);
}
return true;
}
-bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource(
+bool cmQtAutoMocUic::JobEvalCacheMocT::EvalSource(
SourceFileHandleT const& source)
{
SourceFileT const& sourceFile = *source;
@@ -623,7 +614,7 @@ bool cmQtAutoMocUic::JobEvaluateT::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);
@@ -650,27 +641,30 @@ bool cmQtAutoMocUic::JobEvaluateT::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(MessagePath(sourceFile.FileName), "\ncontains a ",
+ Quoted(parseData.Macro), " macro, but does not include ",
+ MessagePath(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(MessagePath(sourceFile.FileName),
+ "\nincludes the moc file ", MessagePath(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() &&
@@ -682,30 +676,30 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource(
// used. This is for KDE4 compatibility.
// Issue a warning
- Log().WarningFile(
- GenT::MOC, sourceFile.FileName,
- cmStrCat("The file contains a ", Quoted(parseData.Macro),
- " macro, but does not include ", Quoted(sourceBase + ".moc"),
- ".\nInstead it includes ", Quoted(incKey.Key),
- ".\nRunning moc on the source\n ",
- Quoted(sourceFile.FileName), "!\nBetter include ",
- Quoted(sourceBase + ".moc"),
+ Log().Warning(
+ GenT::MOC,
+ cmStrCat(MessagePath(sourceFile.FileName), "\ncontains a ",
+ Quoted(parseData.Macro), " macro, but does not include ",
+ MessagePath(sourceBase + ".moc"), ".\nInstead it includes ",
+ MessagePath(incKey.Key), ".\nRunning moc on the source\n ",
+ MessagePath(sourceFile.FileName), "!\nBetter include ",
+ MessagePath(sourceBase + ".moc"),
" for compatibility with regular mode.\n",
"This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"));
// Create mapping
- if (!MocRegisterIncluded(incKey.Key, source, source, false)) {
+ if (!RegisterIncluded(incKey.Key, source, source)) {
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))) {
return false;
}
}
@@ -718,53 +712,60 @@ bool cmQtAutoMocUic::JobEvaluateT::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)) {
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(
+ MessagePath(sourceFile.FileName), "\nincludes the moc file ",
+ MessagePath(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),
+ Log().Warning(
+ GenT::MOC,
+ cmStrCat(MessagePath(sourceFile.FileName),
+ "\nincludes the moc file ", MessagePath(incKey.Key),
", but does not contain a\n", MocConst().MacrosString(),
" macro.\nRunning moc on the header\n ",
- Quoted(header->FileName), "!\nBetter include ",
- Quoted("moc_" + incKey.Base + ".cpp"),
+ MessagePath(headerHandle->FileName), "!\nBetter include ",
+ MessagePath("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(MessagePath(sourceFile.FileName),
+ "\nincludes the moc file ", MessagePath(incKey.Key),
+ " instead of ", MessagePath("moc_" + incKey.Base + ".cpp"),
".\nRunning moc on the header\n ",
- Quoted(header->FileName), "!\nBetter include ",
- Quoted("moc_" + incKey.Base + ".cpp"),
+ MessagePath(headerHandle->FileName), "!\nBetter include ",
+ MessagePath("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))) {
return false;
}
}
@@ -775,25 +776,26 @@ bool cmQtAutoMocUic::JobEvaluateT::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(MessagePath(sourceFile.FileName),
+ "\nincludes the moc file ", MessagePath(incKey.Key),
+ ",\nwhich seems to be the moc file from a different "
+ "source file.\nThis is not supported. Include ",
+ MessagePath(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(MessagePath(sourceFile.FileName),
+ "\nincludes the moc file ",
+ MessagePath(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)) {
return false;
}
}
@@ -802,80 +804,74 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource(
return true;
}
-cmQtAutoMocUic::SourceFileHandleT
-cmQtAutoMocUic::JobEvaluateT::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::JobEvaluateT::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::GetRealPath(testPath);
// 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->IsHeader = true;
+ 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::JobEvaluateT::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::JobEvaluateT::MocRegisterIncluded(
+bool cmQtAutoMocUic::JobEvalCacheMocT::RegisterIncluded(
std::string const& includeString, SourceFileHandleT includerFileHandle,
- SourceFileHandleT sourceFileHandle, bool sourceIsHeader) const
+ SourceFileHandleT sourceFileHandle) const
{
// Check if this file is already included
MappingHandleT& handle = MocEval().Includes[includeString];
@@ -883,18 +879,19 @@ bool cmQtAutoMocUic::JobEvaluateT::MocRegisterIncluded(
// Check if the output file would be generated from different source files
if (handle->SourceFile != sourceFileHandle) {
std::string files =
- cmStrCat(" ", Quoted(includerFileHandle->FileName), '\n');
+ cmStrCat(" ", MessagePath(includerFileHandle->FileName), '\n');
for (auto const& item : handle->IncluderFiles) {
- files += cmStrCat(" ", Quoted(item->FileName), '\n');
+ files += cmStrCat(" ", MessagePath(item->FileName), '\n');
}
LogError(
GenT::MOC,
cmStrCat("The source files\n", files,
- "contain the same include string ", Quoted(includeString),
+ "contain the same include string ",
+ MessagePath(includeString),
", but\nthe moc file would be generated from different "
"source files\n ",
- Quoted(sourceFileHandle->FileName), " and\n ",
- Quoted(handle->SourceFile->FileName),
+ MessagePath(sourceFileHandle->FileName), " and\n ",
+ MessagePath(handle->SourceFile->FileName),
".\nConsider to\n"
" - not include the \"moc_<NAME>.cpp\" file\n"
" - add a directory prefix to a \"<NAME>.moc\" include "
@@ -916,15 +913,16 @@ bool cmQtAutoMocUic::JobEvaluateT::MocRegisterIncluded(
handle->OutputFile = Gen()->AbsoluteIncludePath(includeString);
// Register mapping in sources/headers map
- MocRegisterMapping(handle, sourceIsHeader);
+ RegisterMapping(handle);
return true;
}
-void cmQtAutoMocUic::JobEvaluateT::MocRegisterMapping(
- MappingHandleT mappingHandle, bool sourceIsHeader) const
+void cmQtAutoMocUic::JobEvalCacheMocT::RegisterMapping(
+ MappingHandleT mappingHandle) const
{
- auto& regMap =
- sourceIsHeader ? MocEval().HeaderMappings : MocEval().SourceMappings;
+ auto& regMap = mappingHandle->SourceFile->IsHeader
+ ? MocEval().HeaderMappings
+ : MocEval().SourceMappings;
// Check if source file already gets mapped
auto& regHandle = regMap[mappingHandle->SourceFile->FileName];
if (!regHandle) {
@@ -938,17 +936,33 @@ void cmQtAutoMocUic::JobEvaluateT::MocRegisterMapping(
}
}
-bool cmQtAutoMocUic::JobEvaluateT::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 MessagePath(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::JobEvaluateT::UicEvalFile(
+bool cmQtAutoMocUic::JobEvalCacheUicT::EvalFile(
SourceFileHandleT const& sourceFileHandle)
{
SourceFileT const& sourceFile = *sourceFileHandle;
@@ -957,17 +971,25 @@ bool cmQtAutoMocUic::JobEvaluateT::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(MessagePath(sourceFile.FileName),
+ "\nincludes the uic file ", MessagePath(incKey.Key),
+ ",\nbut the user interface file ", MessagePath(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;
}
}
@@ -975,20 +997,73 @@ bool cmQtAutoMocUic::JobEvaluateT::UicEvalFile(
return true;
}
-bool cmQtAutoMocUic::JobEvaluateT::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');
+ cmStrCat(" ", MessagePath(includerFileHandle->FileName), '\n');
for (auto const& item : handle->IncluderFiles) {
- files += cmStrCat(" ", Quoted(item->FileName), '\n');
+ files += cmStrCat(" ", MessagePath(item->FileName), '\n');
}
LogError(
GenT::UIC,
@@ -997,8 +1072,8 @@ bool cmQtAutoMocUic::JobEvaluateT::UicRegisterMapping(
Quoted(includeString),
", but\nthe uic file would be generated from different "
"user interface files\n ",
- Quoted(uiFileHandle->FileName), " and\n ",
- Quoted(handle->SourceFile->FileName),
+ MessagePath(UiFileHandle->FileName), " and\n ",
+ MessagePath(handle->SourceFile->FileName),
".\nConsider to\n"
" - add a directory prefix to a \"ui_<NAME>.h\" include "
"(e.g \"sub/ui_<NAME>.h\")\n"
@@ -1013,7 +1088,7 @@ bool cmQtAutoMocUic::JobEvaluateT::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));
@@ -1021,123 +1096,60 @@ bool cmQtAutoMocUic::JobEvaluateT::UicRegisterMapping(
return true;
}
-cmQtAutoMocUic::SourceFileHandleT
-cmQtAutoMocUic::JobEvaluateT::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 realPath = cmSystemTools::GetRealPath(testFile);
- // Get or create .ui file handle
- SourceFileHandleT& handle = Gen()->UicEval().UiFiles[realPath];
- if (!handle) {
- // The file wasn't registered, yet
- handle = std::make_shared<SourceFileT>(realPath);
- 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>();
}
- 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));
+ if (UicConst().Enabled) {
+ Gen()->WorkerPool().EmplaceJob<JobProbeDepsUicT>();
+ }
+ // Add probe finish job
+ Gen()->WorkerPool().EmplaceJob<JobProbeDepsFinishT>();
}
-
- return SourceFileHandleT();
}
-void cmQtAutoMocUic::JobGenerateT::Process()
+void cmQtAutoMocUic::JobProbeDepsMocT::Process()
{
- // Add moc compile jobs
- if (MocConst().Enabled) {
- for (auto const& pair : MocEval().HeaderMappings) {
- // Register if this mapping is a candidate for mocs_compilation.cpp
- bool const compFile = pair.second->IncludeString.empty();
- if (compFile) {
- MocEval().CompFiles.emplace_back(pair.second->SourceFile->BuildPath);
- }
- if (!MocGenerate(pair.second, compFile)) {
- return;
- }
+ // Create moc header jobs
+ for (auto const& pair : MocEval().HeaderMappings) {
+ // Register if this mapping is a candidate for mocs_compilation.cpp
+ bool const compFile = pair.second->IncludeString.empty();
+ if (compFile) {
+ MocEval().CompFiles.emplace_back(pair.second->SourceFile->BuildPath);
}
- for (auto const& pair : MocEval().SourceMappings) {
- if (!MocGenerate(pair.second, false)) {
- return;
- }
+ if (!Generate(pair.second, compFile)) {
+ return;
}
-
- // Add mocs compilations job on demand
- Gen()->WorkerPool().EmplaceJob<JobMocsCompilationT>();
}
- // Add uic compile jobs
- if (UicConst().Enabled) {
- for (auto const& pair : Gen()->UicEval().Includes) {
- if (!UicGenerate(pair.second)) {
- return;
- }
+ // Create moc source jobs
+ for (auto const& pair : MocEval().SourceMappings) {
+ if (!Generate(pair.second, false)) {
+ return;
}
}
-
- // Add finish job
- Gen()->WorkerPool().EmplaceJob<JobFinishT>();
}
-bool cmQtAutoMocUic::JobGenerateT::MocGenerate(MappingHandleT const& mapping,
- bool compFile) const
+bool cmQtAutoMocUic::JobProbeDepsMocT::Generate(MappingHandleT const& mapping,
+ bool compFile) const
{
std::unique_ptr<std::string> reason;
if (Log().Verbose()) {
reason = cm::make_unique<std::string>();
}
- if (MocUpdate(*mapping, reason.get())) {
- // Create the parent directory
- if (!MakeParentDirectory(mapping->OutputFile)) {
- LogFileError(GenT::MOC, mapping->OutputFile,
- "Could not create parent directory.");
- return false;
- }
+ if (Probe(*mapping, reason.get())) {
+ // Register the parent directory for creation
+ MocEval().OutputDirs.emplace(cmQtAutoGen::ParentDir(mapping->OutputFile));
// Add moc job
- Gen()->WorkerPool().EmplaceJob<JobMocT>(mapping, std::move(reason));
+ Gen()->WorkerPool().EmplaceJob<JobCompileMocT>(mapping, std::move(reason));
// Check if a moc job for a mocs_compilation.cpp entry was generated
if (compFile) {
MocEval().CompUpdated = true;
@@ -1146,7 +1158,7 @@ bool cmQtAutoMocUic::JobGenerateT::MocGenerate(MappingHandleT const& mapping,
return true;
}
-bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping,
+bool cmQtAutoMocUic::JobProbeDepsMocT::Probe(MappingT const& mapping,
std::string* reason) const
{
std::string const& sourceFile = mapping.SourceFile->FileName;
@@ -1157,8 +1169,8 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping,
if (!outputFileTime.Load(outputFile)) {
if (reason != nullptr) {
*reason =
- cmStrCat("Generating ", Quoted(outputFile),
- ", because it doesn't exist, from ", Quoted(sourceFile));
+ cmStrCat("Generating ", MessagePath(outputFile),
+ ", because it doesn't exist, from ", MessagePath(sourceFile));
}
return true;
}
@@ -1166,9 +1178,9 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping,
// Test if any setting changed
if (MocConst().SettingsChanged) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", Quoted(outputFile),
+ *reason = cmStrCat("Generating ", MessagePath(outputFile),
", because the uic settings changed, from ",
- Quoted(sourceFile));
+ MessagePath(sourceFile));
}
return true;
}
@@ -1176,9 +1188,9 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping,
// Test if the source file is newer
if (outputFileTime.Older(mapping.SourceFile->FileTime)) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", Quoted(outputFile),
+ *reason = cmStrCat("Generating ", MessagePath(outputFile),
", because it's older than its source file, from ",
- Quoted(sourceFile));
+ MessagePath(sourceFile));
}
return true;
}
@@ -1187,9 +1199,10 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping,
if (!MocConst().PredefsFileAbs.empty()) {
if (outputFileTime.Older(MocEval().PredefsTime)) {
if (reason != nullptr) {
- *reason = cmStrCat(
- "Generating ", Quoted(outputFile), ", because it's older than ",
- Quoted(MocConst().PredefsFileAbs), ", from ", Quoted(sourceFile));
+ *reason = cmStrCat("Generating ", MessagePath(outputFile),
+ ", because it's older than ",
+ MessagePath(MocConst().PredefsFileAbs), ", from ",
+ MessagePath(sourceFile));
}
return true;
}
@@ -1198,9 +1211,9 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping,
// Test if the moc executable is newer
if (outputFileTime.Older(MocConst().ExecutableTime)) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", Quoted(outputFile),
+ *reason = cmStrCat("Generating ", MessagePath(outputFile),
", because it's older than the moc executable, from ",
- Quoted(sourceFile));
+ MessagePath(sourceFile));
}
return true;
}
@@ -1211,19 +1224,21 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping,
std::string const sourceDir = SubDirPrefix(sourceFile);
for (std::string const& dep : mapping.SourceFile->ParseData->Moc.Depends) {
// Find dependency file
- auto const depMatch = MocFindDependency(sourceDir, dep);
+ auto const depMatch = FindDependency(sourceDir, dep);
if (depMatch.first.empty()) {
- Log().WarningFile(GenT::MOC, sourceFile,
- "Could not find dependency file " + Quoted(dep));
+ Log().Warning(GenT::MOC,
+ cmStrCat(MessagePath(sourceFile), " depends on ",
+ MessagePath(dep),
+ " but the file does not exist."));
continue;
}
// Test if dependency file is older
if (outputFileTime.Older(depMatch.second)) {
if (reason != nullptr) {
- *reason =
- cmStrCat("Generating ", Quoted(outputFile),
- ", because it's older than its dependency file ",
- Quoted(depMatch.first), ", from ", Quoted(sourceFile));
+ *reason = cmStrCat("Generating ", MessagePath(outputFile),
+ ", because it's older than its dependency file ",
+ MessagePath(depMatch.first), ", from ",
+ MessagePath(sourceFile));
}
return true;
}
@@ -1234,7 +1249,7 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping,
}
std::pair<std::string, cmFileTime>
-cmQtAutoMocUic::JobGenerateT::MocFindDependency(
+cmQtAutoMocUic::JobProbeDepsMocT::FindDependency(
std::string const& sourceDir, std::string const& includeString) const
{
using ResPair = std::pair<std::string, cmFileTime>;
@@ -1256,27 +1271,26 @@ cmQtAutoMocUic::JobGenerateT::MocFindDependency(
return ResPair();
}
-bool cmQtAutoMocUic::JobGenerateT::UicGenerate(
- MappingHandleT const& mapping) const
+void cmQtAutoMocUic::JobProbeDepsUicT::Process()
{
- std::unique_ptr<std::string> reason;
- if (Log().Verbose()) {
- reason = cm::make_unique<std::string>();
- }
- if (UicUpdate(*mapping, reason.get())) {
- // Create the parent directory
- if (!MakeParentDirectory(mapping->OutputFile)) {
- LogFileError(GenT::UIC, mapping->OutputFile,
- "Could not create parent directory.");
- return false;
+ for (auto const& pair : Gen()->UicEval().Includes) {
+ MappingHandleT const& mapping = pair.second;
+ std::unique_ptr<std::string> reason;
+ if (Log().Verbose()) {
+ reason = cm::make_unique<std::string>();
}
+ if (!Probe(*mapping, reason.get())) {
+ continue;
+ }
+
+ // Register the parent directory for creation
+ UicEval().OutputDirs.emplace(cmQtAutoGen::ParentDir(mapping->OutputFile));
// Add uic job
- Gen()->WorkerPool().EmplaceJob<JobUicT>(mapping, std::move(reason));
+ Gen()->WorkerPool().EmplaceJob<JobCompileUicT>(mapping, std::move(reason));
}
- return true;
}
-bool cmQtAutoMocUic::JobGenerateT::UicUpdate(MappingT const& mapping,
+bool cmQtAutoMocUic::JobProbeDepsUicT::Probe(MappingT const& mapping,
std::string* reason) const
{
std::string const& sourceFile = mapping.SourceFile->FileName;
@@ -1287,8 +1301,8 @@ bool cmQtAutoMocUic::JobGenerateT::UicUpdate(MappingT const& mapping,
if (!outputFileTime.Load(outputFile)) {
if (reason != nullptr) {
*reason =
- cmStrCat("Generating ", Quoted(outputFile),
- ", because it doesn't exist, from ", Quoted(sourceFile));
+ cmStrCat("Generating ", MessagePath(outputFile),
+ ", because it doesn't exist, from ", MessagePath(sourceFile));
}
return true;
}
@@ -1296,9 +1310,9 @@ bool cmQtAutoMocUic::JobGenerateT::UicUpdate(MappingT const& mapping,
// Test if the uic settings changed
if (UicConst().SettingsChanged) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", Quoted(outputFile),
+ *reason = cmStrCat("Generating ", MessagePath(outputFile),
", because the uic settings changed, from ",
- Quoted(sourceFile));
+ MessagePath(sourceFile));
}
return true;
}
@@ -1306,9 +1320,9 @@ bool cmQtAutoMocUic::JobGenerateT::UicUpdate(MappingT const& mapping,
// Test if the source file is newer
if (outputFileTime.Older(mapping.SourceFile->FileTime)) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", Quoted(outputFile),
+ *reason = cmStrCat("Generating ", MessagePath(outputFile),
" because it's older than the source file ",
- Quoted(sourceFile));
+ MessagePath(sourceFile));
}
return true;
}
@@ -1316,9 +1330,9 @@ bool cmQtAutoMocUic::JobGenerateT::UicUpdate(MappingT const& mapping,
// Test if the uic executable is newer
if (outputFileTime.Older(UicConst().ExecutableTime)) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", Quoted(outputFile),
+ *reason = cmStrCat("Generating ", MessagePath(outputFile),
", because it's older than the uic executable, from ",
- Quoted(sourceFile));
+ MessagePath(sourceFile));
}
return true;
}
@@ -1326,24 +1340,93 @@ bool cmQtAutoMocUic::JobGenerateT::UicUpdate(MappingT const& mapping,
return false;
}
-void cmQtAutoMocUic::JobMocT::Process()
+void cmQtAutoMocUic::JobProbeDepsFinishT::Process()
+{
+ // Create output directories
+ {
+ using StringSet = std::unordered_set<std::string>;
+ auto createDirs = [this](GenT genType, StringSet const& dirSet) {
+ for (std::string const& dirName : dirSet) {
+ if (!cmSystemTools::MakeDirectory(dirName)) {
+ this->LogError(
+ genType,
+ cmStrCat("Creating directory ", MessagePath(dirName), " failed."));
+ return;
+ }
+ }
+ };
+ if (MocConst().Enabled && UicConst().Enabled) {
+ StringSet outputDirs = MocEval().OutputDirs;
+ outputDirs.insert(UicEval().OutputDirs.begin(),
+ UicEval().OutputDirs.end());
+ createDirs(GenT::GEN, outputDirs);
+ } else if (MocConst().Enabled) {
+ createDirs(GenT::MOC, MocEval().OutputDirs);
+ } else if (UicConst().Enabled) {
+ createDirs(GenT::UIC, UicEval().OutputDirs);
+ }
+ }
+
+ if (MocConst().Enabled) {
+ // Add mocs compilations job
+ Gen()->WorkerPool().EmplaceJob<JobMocsCompilationT>();
+ }
+
+ // Add finish job
+ Gen()->WorkerPool().EmplaceJob<JobFinishT>();
+}
+
+void cmQtAutoMocUic::JobCompileMocT::Process()
{
std::string const& sourceFile = Mapping->SourceFile->FileName;
std::string const& outputFile = Mapping->OutputFile;
// Compose moc command
std::vector<std::string> cmd;
- cmd.push_back(MocConst().Executable);
- // Add options
- cmAppend(cmd, MocConst().AllOptions);
- // Add predefs include
- if (!MocConst().PredefsFileAbs.empty()) {
- cmd.emplace_back("--include");
- cmd.push_back(MocConst().PredefsFileAbs);
+ {
+ // Reserve large enough
+ cmd.reserve(MocConst().OptionsDefinitions.size() +
+ MocConst().OptionsIncludes.size() +
+ MocConst().OptionsExtra.size() + 16);
+ cmd.push_back(MocConst().Executable);
+ // Add definitions
+ cmAppend(cmd, MocConst().OptionsDefinitions);
+ // Add includes
+ cmAppend(cmd, MocConst().OptionsIncludes);
+ // Add predefs include
+ if (!MocConst().PredefsFileAbs.empty()) {
+ cmd.emplace_back("--include");
+ cmd.push_back(MocConst().PredefsFileAbs);
+ }
+ // Add path prefix on demand
+ if (MocConst().PathPrefix && Mapping->SourceFile->IsHeader) {
+ for (std::string const& dir : MocConst().IncludePaths) {
+ cm::string_view prefix = sourceFile;
+ if (cmHasPrefix(prefix, dir)) {
+ prefix.remove_prefix(dir.size());
+ if (cmHasPrefix(prefix, '/')) {
+ prefix.remove_prefix(1);
+ auto slashPos = prefix.rfind('/');
+ if (slashPos != cm::string_view::npos) {
+ cmd.emplace_back("-p");
+ cmd.emplace_back(prefix.substr(0, slashPos));
+ } else {
+ cmd.emplace_back("-p");
+ cmd.emplace_back("./");
+ }
+ break;
+ }
+ }
+ }
+ }
+ // Add extra options
+ cmAppend(cmd, MocConst().OptionsExtra);
+ // Add output file
+ cmd.emplace_back("-o");
+ cmd.push_back(outputFile);
+ // Add source file
+ cmd.push_back(sourceFile);
}
- cmd.emplace_back("-o");
- cmd.push_back(outputFile);
- cmd.push_back(sourceFile);
// Execute moc command
cmWorkerPool::ProcessResultT result;
@@ -1358,19 +1441,19 @@ void cmQtAutoMocUic::JobMocT::Process()
if (!Mapping->IncluderFiles.empty()) {
includers = "included by\n";
for (auto const& item : Mapping->IncluderFiles) {
- includers += cmStrCat(" ", Quoted(item->FileName), '\n');
+ includers += cmStrCat(" ", MessagePath(item->FileName), '\n');
}
}
LogCommandError(GenT::MOC,
cmStrCat("The moc process failed to compile\n ",
- Quoted(sourceFile), "\ninto\n ",
- Quoted(outputFile), '\n', includers,
+ MessagePath(sourceFile), "\ninto\n ",
+ MessagePath(outputFile), '\n', includers,
result.ErrorMessage),
cmd, result.StdOut);
}
}
-void cmQtAutoMocUic::JobUicT::Process()
+void cmQtAutoMocUic::JobCompileUicT::Process()
{
std::string const& sourceFile = Mapping->SourceFile->FileName;
std::string const& outputFile = Mapping->OutputFile;
@@ -1402,13 +1485,13 @@ void cmQtAutoMocUic::JobUicT::Process()
// Uic command failed
std::string includers;
for (auto const& item : Mapping->IncluderFiles) {
- includers += cmStrCat(" ", Quoted(item->FileName), '\n');
+ includers += cmStrCat(" ", MessagePath(item->FileName), '\n');
}
LogCommandError(GenT::UIC,
cmStrCat("The uic process failed to compile\n ",
- Quoted(sourceFile), "\ninto\n ",
- Quoted(outputFile), "\nincluded by\n", includers,
- result.ErrorMessage),
+ MessagePath(sourceFile), "\ninto\n ",
+ MessagePath(outputFile), "\nincluded by\n",
+ includers, result.ErrorMessage),
cmd, result.StdOut);
}
}
@@ -1436,20 +1519,24 @@ void cmQtAutoMocUic::JobMocsCompilationT::Process()
if (cmQtAutoGenerator::FileDiffers(compAbs, content)) {
// Actually write mocs compilation file
if (Log().Verbose()) {
- Log().Info(GenT::MOC, "Generating MOC compilation " + compAbs);
+ Log().Info(GenT::MOC,
+ "Generating MOC compilation " + MessagePath(compAbs));
}
if (!FileWrite(compAbs, content)) {
- LogFileError(GenT::MOC, compAbs,
- "mocs compilation file writing failed.");
+ LogError(GenT::MOC,
+ cmStrCat("Writing MOC compilation ", MessagePath(compAbs),
+ " failed."));
}
} else if (MocEval().CompUpdated) {
// Only touch mocs compilation file
if (Log().Verbose()) {
- Log().Info(GenT::MOC, "Touching mocs compilation " + compAbs);
+ Log().Info(GenT::MOC,
+ "Touching MOC compilation " + MessagePath(compAbs));
}
if (!cmSystemTools::Touch(compAbs, false)) {
- LogFileError(GenT::MOC, compAbs,
- "mocs compilation file touching failed.");
+ LogError(GenT::MOC,
+ cmStrCat("Touching MOC compilation ", MessagePath(compAbs),
+ " failed."));
}
}
}
@@ -1543,12 +1630,10 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
makefile->GetCMakeInstance()->GetHeaderExtensions();
// - Files and directories
- BaseConst_.IncludeProjectDirsBefore =
- InfoGetBool("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE");
- BaseConst_.ProjectSourceDir = InfoGet("AM_CMAKE_SOURCE_DIR");
- BaseConst_.ProjectBinaryDir = InfoGet("AM_CMAKE_BINARY_DIR");
- BaseConst_.CurrentSourceDir = InfoGet("AM_CMAKE_CURRENT_SOURCE_DIR");
- BaseConst_.CurrentBinaryDir = InfoGet("AM_CMAKE_CURRENT_BINARY_DIR");
+ ProjectDirsRef().Source = InfoGet("AM_CMAKE_SOURCE_DIR");
+ ProjectDirsRef().Binary = InfoGet("AM_CMAKE_BINARY_DIR");
+ ProjectDirsRef().CurrentSource = InfoGet("AM_CMAKE_CURRENT_SOURCE_DIR");
+ ProjectDirsRef().CurrentBinary = InfoGet("AM_CMAKE_CURRENT_BINARY_DIR");
BaseConst_.AutogenBuildDir = InfoGet("AM_BUILD_DIR");
if (BaseConst_.AutogenBuildDir.empty()) {
return LogInfoError("Autogen build directory missing.");
@@ -1563,7 +1648,7 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
}
if (!BaseConst_.CMakeExecutableTime.Load(BaseConst_.CMakeExecutable)) {
return LogInfoError(cmStrCat("The CMake executable ",
- Quoted(BaseConst_.CMakeExecutable),
+ MessagePath(BaseConst_.CMakeExecutable),
" does not exist."));
}
BaseConst_.ParseCacheFile = InfoGetConfig("AM_PARSE_CACHE_FILE");
@@ -1592,7 +1677,7 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
// Load the executable file time
if (!MocConst_.ExecutableTime.Load(MocConst_.Executable)) {
return LogInfoError(cmStrCat("The moc executable ",
- Quoted(MocConst_.Executable),
+ MessagePath(MocConst_.Executable),
" does not exist."));
}
for (std::string& sfl : InfoGetList("AM_MOC_SKIP")) {
@@ -1600,8 +1685,11 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
}
MocConst_.Definitions = InfoGetConfigList("AM_MOC_DEFINITIONS");
MocConst_.IncludePaths = InfoGetConfigList("AM_MOC_INCLUDES");
- MocConst_.Options = InfoGetList("AM_MOC_OPTIONS");
+ MocConst_.OptionsExtra = InfoGetList("AM_MOC_OPTIONS");
+
MocConst_.RelaxedMode = InfoGetBool("AM_MOC_RELAXED_MODE");
+ MocConst_.PathPrefix = InfoGetBool("AM_MOC_PATH_PREFIX");
+
for (std::string const& item : InfoGetList("AM_MOC_MACRO_NAMES")) {
MocConst_.MacroFilters.emplace_back(
item, ("[\n][ \t]*{?[ \t]*" + item).append("[^a-zA-Z0-9_]"));
@@ -1658,7 +1746,7 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
// Load the executable file time
if (!UicConst_.ExecutableTime.Load(UicConst_.Executable)) {
return LogInfoError(cmStrCat("The uic executable ",
- Quoted(UicConst_.Executable),
+ MessagePath(UicConst_.Executable),
" does not exist."));
}
for (std::string& sfl : InfoGetList("AM_UIC_SKIP")) {
@@ -1685,83 +1773,89 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
}
}
- // - Headers and sources
+ // Headers
{
- auto makeSource =
- [&LogInfoError](std::string const& fileName,
- std::string const& fileFlags) -> SourceFileHandleT {
+ // Get file lists
+ cm::string_view const keyFiles = "AM_HEADERS";
+ cm::string_view const keyFlags = "AM_HEADERS_FLAGS";
+ std::vector<std::string> files = InfoGetList(keyFiles);
+ std::vector<std::string> flags = InfoGetList(keyFlags);
+ std::vector<std::string> builds;
+ if (!MatchSizes(keyFiles, keyFlags, files.size(), flags.size())) {
+ return false;
+ }
+ if (MocConst().Enabled) {
+ cm::string_view const keyPaths = "AM_HEADERS_BUILD_PATHS";
+ builds = InfoGetList(keyPaths);
+ if (!MatchSizes(keyFiles, keyPaths, files.size(), builds.size())) {
+ return false;
+ }
+ }
+
+ // Process file lists
+ for (std::size_t ii = 0; ii != files.size(); ++ii) {
+ std::string& fileName(files[ii]);
+ std::string const& fileFlags(flags[ii]);
if (fileFlags.size() != 2) {
- LogInfoError("Invalid file flags string size");
- return SourceFileHandleT();
+ LogInfoError(cmStrCat("Invalid flags string size ", fileFlags.size(),
+ "in ", keyFlags));
+ return false;
}
cmFileTime fileTime;
if (!fileTime.Load(fileName)) {
- LogInfoError("The source file " + cmQtAutoGen::Quoted(fileName) +
- " does not exist.");
- return SourceFileHandleT();
- }
- SourceFileHandleT sfh = std::make_shared<SourceFileT>(fileName);
- sfh->FileTime = fileTime;
- sfh->Moc = (fileFlags[0] == 'M');
- sfh->Uic = (fileFlags[1] == 'U');
- return sfh;
- };
-
- // Headers
- {
- // Get file lists
- cm::string_view const keyFiles = "AM_HEADERS";
- cm::string_view const keyFlags = "AM_HEADERS_FLAGS";
- std::vector<std::string> files = InfoGetList(keyFiles);
- std::vector<std::string> flags = InfoGetList(keyFlags);
- std::vector<std::string> builds;
- if (!MatchSizes(keyFiles, keyFlags, files.size(), flags.size())) {
+ LogInfoError(cmStrCat("The header file ", this->MessagePath(fileName),
+ " does not exist."));
return false;
}
- if (MocConst().Enabled) {
- cm::string_view const keyPaths = "AM_HEADERS_BUILD_PATHS";
- builds = InfoGetList(keyPaths);
- if (!MatchSizes(keyFiles, keyPaths, files.size(), builds.size())) {
- return false;
- }
- }
- // Process file lists
- for (std::size_t ii = 0; ii != files.size(); ++ii) {
- std::string& fileName(files[ii]);
- SourceFileHandleT sfh = makeSource(fileName, flags[ii]);
- if (!sfh) {
- return false;
- }
- if (MocConst().Enabled) {
- sfh->BuildPath = std::move(builds[ii]);
- if (sfh->BuildPath.empty()) {
- Log().ErrorFile(GenT::GEN, this->InfoFile(),
- "Header file build path is empty");
- return false;
- }
+
+ SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(fileName);
+ sourceHandle->FileTime = fileTime;
+ sourceHandle->IsHeader = true;
+ sourceHandle->Moc = (fileFlags[0] == 'M');
+ sourceHandle->Uic = (fileFlags[1] == 'U');
+
+ if (sourceHandle->Moc && MocConst().Enabled) {
+ sourceHandle->BuildPath = std::move(builds[ii]);
+ if (sourceHandle->BuildPath.empty()) {
+ return LogInfoError("Header file build path is empty");
}
- BaseEval().Headers.emplace(std::move(fileName), std::move(sfh));
}
+ BaseEval().Headers.emplace(std::move(fileName), std::move(sourceHandle));
}
+ }
- // Sources
- {
- cm::string_view const keyFiles = "AM_SOURCES";
- cm::string_view const keyFlags = "AM_SOURCES_FLAGS";
- std::vector<std::string> files = InfoGetList(keyFiles);
- std::vector<std::string> flags = InfoGetList(keyFlags);
- if (!MatchSizes(keyFiles, keyFlags, files.size(), flags.size())) {
+ // Sources
+ {
+ cm::string_view const keyFiles = "AM_SOURCES";
+ cm::string_view const keyFlags = "AM_SOURCES_FLAGS";
+ std::vector<std::string> files = InfoGetList(keyFiles);
+ std::vector<std::string> flags = InfoGetList(keyFlags);
+ if (!MatchSizes(keyFiles, keyFlags, files.size(), flags.size())) {
+ return false;
+ }
+
+ // Process file lists
+ for (std::size_t ii = 0; ii != files.size(); ++ii) {
+ std::string& fileName(files[ii]);
+ std::string const& fileFlags(flags[ii]);
+ if (fileFlags.size() != 2) {
+ LogInfoError(cmStrCat("Invalid flags string size ", fileFlags.size(),
+ "in ", keyFlags));
return false;
}
- // Process file lists
- for (std::size_t ii = 0; ii != files.size(); ++ii) {
- std::string& fileName(files[ii]);
- SourceFileHandleT sfh = makeSource(fileName, flags[ii]);
- if (!sfh) {
- return false;
- }
- BaseEval().Sources.emplace(std::move(fileName), std::move(sfh));
+ cmFileTime fileTime;
+ if (!fileTime.Load(fileName)) {
+ LogInfoError(cmStrCat("The source file ", this->MessagePath(fileName),
+ " does not exist."));
+ return false;
}
+
+ SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(fileName);
+ sourceHandle->FileTime = fileTime;
+ sourceHandle->IsHeader = false;
+ sourceHandle->Moc = (fileFlags[0] == 'M');
+ sourceHandle->Uic = (fileFlags[1] == 'U');
+ BaseEval().Sources.emplace(std::move(fileName), std::move(sourceHandle));
}
}
@@ -1775,49 +1869,20 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
// Moc predefs file
if (!MocConst_.PredefsCmd.empty()) {
+ std::string pathRel;
if (BaseConst_.MultiConfig) {
- MocConst_.PredefsFileRel =
- cmStrCat("moc_predefs_", InfoConfig(), ".h");
+ pathRel = cmStrCat("moc_predefs_", InfoConfig(), ".h");
} else {
- MocConst_.PredefsFileRel = "moc_predefs.h";
+ pathRel = "moc_predefs.h";
}
- MocConst_.PredefsFileAbs = AbsoluteBuildPath(MocConst().PredefsFileRel);
+ MocConst_.PredefsFileAbs = AbsoluteBuildPath(pathRel);
}
- // Sort include directories on demand
- if (BaseConst().IncludeProjectDirsBefore) {
- // Move strings to temporary list
- std::list<std::string> includes(MocConst().IncludePaths.begin(),
- MocConst().IncludePaths.end());
- MocConst_.IncludePaths.clear();
- MocConst_.IncludePaths.reserve(includes.size());
- // Append project directories only
- {
- std::initializer_list<cm::string_view> const movePaths = {
- BaseConst().ProjectBinaryDir, BaseConst().ProjectSourceDir
- };
- for (cm::string_view const& ppath : movePaths) {
- auto it = includes.begin();
- while (it != includes.end()) {
- std::string const& path = *it;
- if (cmHasPrefix(path, ppath)) {
- MocConst_.IncludePaths.push_back(path);
- it = includes.erase(it);
- } else {
- ++it;
- }
- }
- }
- }
- // Append remaining directories
- MocConst_.IncludePaths.insert(MocConst_.IncludePaths.end(),
- includes.begin(), includes.end());
- }
// Compose moc includes list
{
+ // Compute framework paths
std::set<std::string> frameworkPaths;
for (std::string const& path : MocConst().IncludePaths) {
- MocConst_.Includes.push_back("-I" + path);
// Extract framework path
if (cmHasLiteralSuffix(path, ".framework/Headers")) {
// Go up twice to get to the framework root
@@ -1827,26 +1892,26 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
pathComponents.begin(), pathComponents.end() - 2));
}
}
+ // Reserve options
+ MocConst_.OptionsIncludes.reserve(MocConst().IncludePaths.size() +
+ frameworkPaths.size() * 2);
+ // Append includes
+ for (std::string const& path : MocConst().IncludePaths) {
+ MocConst_.OptionsIncludes.emplace_back("-I" + path);
+ }
// Append framework includes
for (std::string const& path : frameworkPaths) {
- MocConst_.Includes.emplace_back("-F");
- MocConst_.Includes.push_back(path);
+ MocConst_.OptionsIncludes.emplace_back("-F");
+ MocConst_.OptionsIncludes.push_back(path);
}
}
- // Setup single list with all options
+
+ // Compose moc definitions list
{
- // Add includes
- MocConst_.AllOptions.insert(MocConst_.AllOptions.end(),
- MocConst().Includes.begin(),
- MocConst().Includes.end());
- // Add definitions
+ MocConst_.OptionsDefinitions.reserve(MocConst().Definitions.size());
for (std::string const& def : MocConst().Definitions) {
- MocConst_.AllOptions.push_back("-D" + def);
+ MocConst_.OptionsDefinitions.emplace_back("-D" + def);
}
- // Add options
- MocConst_.AllOptions.insert(MocConst_.AllOptions.end(),
- MocConst().Options.begin(),
- MocConst().Options.end());
}
}
@@ -1870,18 +1935,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, ProjectDirs().CurrentSource);
+}
+
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<JobEvaluateT>();
+
+ // 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()
@@ -1920,11 +2005,18 @@ void cmQtAutoMocUic::SettingsFileRead()
if (MocConst_.Enabled) {
cryptoHash.Initialize();
cha(MocConst().Executable);
- std::for_each(MocConst().AllOptions.begin(), MocConst().AllOptions.end(),
- cha);
- cha(BaseConst().IncludeProjectDirsBefore ? "TRUE" : "FALSE");
- std::for_each(MocConst().PredefsCmd.begin(), MocConst().PredefsCmd.end(),
- cha);
+ for (auto const& item : MocConst().OptionsDefinitions) {
+ cha(item);
+ }
+ for (auto const& item : MocConst().OptionsIncludes) {
+ cha(item);
+ }
+ for (auto const& item : MocConst().OptionsExtra) {
+ cha(item);
+ }
+ for (auto const& item : MocConst().PredefsCmd) {
+ cha(item);
+ }
for (auto const& filter : MocConst().DependFilters) {
cha(filter.Key);
}
@@ -1984,7 +2076,9 @@ bool cmQtAutoMocUic::SettingsFileWrite()
// Only write if any setting changed
if (MocConst().SettingsChanged || UicConst().SettingsChanged) {
if (Log().Verbose()) {
- Log().Info(GenT::GEN, "Writing settings file " + Quoted(SettingsFile_));
+ Log().Info(
+ GenT::GEN,
+ cmStrCat("Writing settings file ", MessagePath(SettingsFile_)));
}
// Compose settings file content
std::string content;
@@ -2001,8 +2095,9 @@ bool cmQtAutoMocUic::SettingsFileWrite()
// Write settings file
std::string error;
if (!cmQtAutoGenerator::FileWrite(SettingsFile_, content, &error)) {
- Log().ErrorFile(GenT::GEN, SettingsFile_,
- "Settings file writing failed. " + error);
+ Log().Error(GenT::GEN,
+ cmStrCat("Writing the settings file ",
+ MessagePath(SettingsFile_), " failed.\n", error));
// Remove old settings file to trigger a full rebuild on the next run
cmSystemTools::RemoveFile(SettingsFile_);
return false;
@@ -2042,12 +2137,14 @@ bool cmQtAutoMocUic::ParseCacheWrite()
if (BaseEval().ParseCacheChanged) {
if (Log().Verbose()) {
Log().Info(GenT::GEN,
- "Writing parse cache file " +
- Quoted(BaseConst().ParseCacheFile));
+ cmStrCat("Writing the parse cache file ",
+ MessagePath(BaseConst().ParseCacheFile)));
}
if (!BaseEval().ParseCache.WriteToFile(BaseConst().ParseCacheFile)) {
- Log().ErrorFile(GenT::GEN, BaseConst().ParseCacheFile,
- "Parse cache file writing failed.");
+ Log().Error(GenT::GEN,
+ cmStrCat("Writing the parse cache file ",
+ MessagePath(BaseConst().ParseCacheFile),
+ " failed."));
return false;
}
}
@@ -2058,8 +2155,10 @@ bool cmQtAutoMocUic::CreateDirectories()
{
// Create AUTOGEN include directory
if (!cmSystemTools::MakeDirectory(BaseConst().AutogenIncludeDir)) {
- Log().ErrorFile(GenT::GEN, BaseConst().AutogenIncludeDir,
- "Could not create directory.");
+ Log().Error(GenT::GEN,
+ cmStrCat("Creating the AUTOGEN include directory ",
+ MessagePath(BaseConst().AutogenIncludeDir),
+ " failed."));
return false;
}
return true;