summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorAlexey Edelev <semlanik@gmail.com>2021-07-22 10:13:48 (GMT)
committerAlexey Edelev <semlanik@gmail.com>2021-07-23 13:37:31 (GMT)
commite5ec0e52f4f15f78bb973cdb03a61ef9c707c2fa (patch)
tree070f0eb729d32d5be2209a4752784adc9878afe8 /Source
parent41e9953143c37dfa50be30ff4e34c826e2f55c0b (diff)
downloadCMake-e5ec0e52f4f15f78bb973cdb03a61ef9c707c2fa.zip
CMake-e5ec0e52f4f15f78bb973cdb03a61ef9c707c2fa.tar.gz
CMake-e5ec0e52f4f15f78bb973cdb03a61ef9c707c2fa.tar.bz2
AUTOUIC: Fix generating of dependency rules for UI header files
We could not rely on .ui files when generating the ninja rules for the generated UI header files. .ui files might be added to the target sources but never processed by AUTOUIC afterward, since UI header files are never included in a source code. Instead of adding dependency rules based on the .ui files, this approach scans non-generated source files for includes of the UI header files, as AUTOUIC does. This gives the consistent set of UI header files at configure time, that could be used to generate byproducts rules for the AUTOUIC. Also, the path to the generated UI header file depends not on the .ui file location but on the include line is used in source files. Fixes: #16776
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/cmQtAutoGen.cxx36
-rw-r--r--Source/cmQtAutoGen.h3
-rw-r--r--Source/cmQtAutoGenInitializer.cxx53
-rw-r--r--Source/cmQtAutoGenInitializer.h2
-rw-r--r--Source/cmQtAutoGenerator.cxx37
-rw-r--r--Source/cmQtAutoGenerator.h2
-rw-r--r--Source/cmQtAutoMocUic.cxx20
-rw-r--r--Source/cmQtAutoUicHelpers.cxx25
-rw-r--r--Source/cmQtAutoUicHelpers.h20
10 files changed, 119 insertions, 81 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 9a18184..0142c07 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -432,6 +432,8 @@ set(SRCS
cmQtAutoMocUic.h
cmQtAutoRcc.cxx
cmQtAutoRcc.h
+ cmQtAutoUicHelpers.cxx
+ cmQtAutoUicHelpers.h
cmRST.cxx
cmRST.h
cmRuntimeDependencyArchive.cxx
diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
index 57fcd2d..898d862 100644
--- a/Source/cmQtAutoGen.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -384,3 +384,39 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile,
}
return true;
}
+
+bool cmQtAutoGen::FileRead(std::string& content, std::string const& filename,
+ std::string* error)
+{
+ content.clear();
+ if (!cmSystemTools::FileExists(filename, true)) {
+ if (error != nullptr) {
+ *error = "Not a file.";
+ }
+ return false;
+ }
+
+ unsigned long const length = cmSystemTools::FileLength(filename);
+ cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
+
+ // Use lambda to save destructor calls of ifs
+ return [&ifs, length, &content, error]() -> bool {
+ if (!ifs) {
+ if (error != nullptr) {
+ *error = "Opening the file for reading failed.";
+ }
+ return false;
+ }
+ content.reserve(length);
+ using IsIt = std::istreambuf_iterator<char>;
+ content.assign(IsIt{ ifs }, IsIt{});
+ if (!ifs) {
+ content.clear();
+ if (error != nullptr) {
+ *error = "Reading from the file failed.";
+ }
+ return false;
+ }
+ return true;
+ }();
+}
diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h
index 466a954..b9ae360 100644
--- a/Source/cmQtAutoGen.h
+++ b/Source/cmQtAutoGen.h
@@ -100,6 +100,9 @@ public:
std::vector<std::string> const& newOpts,
bool isQt5);
+ static bool FileRead(std::string& content, std::string const& filename,
+ std::string* error = nullptr);
+
/** @class RccLister
* @brief Lists files in qrc resource files
*/
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 2894201..9d80863 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -902,6 +902,13 @@ bool cmQtAutoGenInitializer::InitScanFiles()
// The reason is that their file names might be discovered from source files
// at generation time.
if (this->MocOrUicEnabled()) {
+ std::set<std::string> uicIncludes;
+ auto collectUicIncludes = [&](std::unique_ptr<cmSourceFile> const& sf) {
+ std::string content;
+ FileRead(content, sf->GetFullPath());
+ this->AutoUicHelpers.CollectUicIncludes(uicIncludes, content);
+ };
+
for (const auto& sf : this->Makefile->GetSourceFiles()) {
// sf->GetExtension() is only valid after sf->ResolveFullPath() ...
// Since we're iterating over source files that might be not in the
@@ -914,6 +921,10 @@ bool cmQtAutoGenInitializer::InitScanFiles()
std::string const& extLower =
cmSystemTools::LowerCase(sf->GetExtension());
+ bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN);
+ bool const skipUic =
+ (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOUIC) ||
+ !this->Uic.Enabled);
if (cm->IsAHeaderExtension(extLower)) {
if (!cm::contains(this->AutogenTarget.Headers, sf.get())) {
auto muf = makeMUFile(sf.get(), fullPath, {}, false);
@@ -921,6 +932,9 @@ bool cmQtAutoGenInitializer::InitScanFiles()
addMUHeader(std::move(muf), extLower);
}
}
+ if (!skipUic && !sf->GetIsGenerated()) {
+ collectUicIncludes(sf);
+ }
} else if (cm->IsACLikeSourceExtension(extLower)) {
if (!cm::contains(this->AutogenTarget.Sources, sf.get())) {
auto muf = makeMUFile(sf.get(), fullPath, {}, false);
@@ -928,11 +942,11 @@ bool cmQtAutoGenInitializer::InitScanFiles()
addMUSource(std::move(muf));
}
}
+ if (!skipUic && !sf->GetIsGenerated()) {
+ collectUicIncludes(sf);
+ }
} else if (this->Uic.Enabled && (extLower == kw.ui)) {
// .ui file
- bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN);
- bool const skipUic =
- (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOUIC));
if (!skipUic) {
// Check if the .ui file has uic options
std::string const uicOpts = sf->GetSafeProperty(kw.AUTOUIC_OPTIONS);
@@ -942,35 +956,22 @@ bool cmQtAutoGenInitializer::InitScanFiles()
this->Uic.UiFilesWithOptions.emplace_back(fullPath,
cmExpandedList(uicOpts));
}
-
- auto uiHeaderRelativePath = cmSystemTools::RelativePath(
- this->LocalGen->GetCurrentSourceDirectory(),
- cmSystemTools::GetFilenamePath(fullPath));
-
- // Avoid creating a path containing adjacent slashes
- if (!uiHeaderRelativePath.empty() &&
- uiHeaderRelativePath.back() != '/') {
- uiHeaderRelativePath += '/';
- }
-
- auto uiHeaderFilePath = cmStrCat(
- '/', uiHeaderRelativePath, "ui_"_s,
- cmSystemTools::GetFilenameWithoutLastExtension(fullPath), ".h"_s);
-
- ConfigString uiHeader;
- std::string uiHeaderGenex;
- this->ConfigFileNamesAndGenex(
- uiHeader, uiHeaderGenex, cmStrCat(this->Dir.Build, "/include"_s),
- uiHeaderFilePath);
-
- this->Uic.UiHeaders.emplace_back(
- std::make_pair(uiHeader, uiHeaderGenex));
} else {
// Register skipped .ui file
this->Uic.SkipUi.insert(fullPath);
}
}
}
+
+ for (const auto& include : uicIncludes) {
+ ConfigString uiHeader;
+ std::string uiHeaderGenex;
+ this->ConfigFileNamesAndGenex(uiHeader, uiHeaderGenex,
+ cmStrCat(this->Dir.Build, "/include"_s),
+ cmStrCat("/"_s, include));
+ this->Uic.UiHeaders.emplace_back(
+ std::make_pair(uiHeader, uiHeaderGenex));
+ }
}
// Process GENERATED sources and headers
diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h
index e76817b..3ec87d2 100644
--- a/Source/cmQtAutoGenInitializer.h
+++ b/Source/cmQtAutoGenInitializer.h
@@ -17,6 +17,7 @@
#include "cmFilePathChecksum.h"
#include "cmQtAutoGen.h"
+#include "cmQtAutoUicHelpers.h"
class cmGeneratorTarget;
class cmGlobalGenerator;
@@ -170,6 +171,7 @@ private:
std::string ConfigDefault;
std::vector<std::string> ConfigsList;
std::string TargetsFolder;
+ cmQtAutoUicHelpers AutoUicHelpers;
/** Common directories. */
struct
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index 568926e..0c6b5e6 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -121,43 +121,6 @@ bool cmQtAutoGenerator::MakeParentDirectory(std::string const& filename)
return success;
}
-bool cmQtAutoGenerator::FileRead(std::string& content,
- std::string const& filename,
- std::string* error)
-{
- content.clear();
- if (!cmSystemTools::FileExists(filename, true)) {
- if (error != nullptr) {
- *error = "Not a file.";
- }
- return false;
- }
-
- unsigned long const length = cmSystemTools::FileLength(filename);
- cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
-
- // Use lambda to save destructor calls of ifs
- return [&ifs, length, &content, error]() -> bool {
- if (!ifs) {
- if (error != nullptr) {
- *error = "Opening the file for reading failed.";
- }
- return false;
- }
- content.reserve(length);
- using IsIt = std::istreambuf_iterator<char>;
- content.assign(IsIt{ ifs }, IsIt{});
- if (!ifs) {
- content.clear();
- if (error != nullptr) {
- *error = "Reading from the file failed.";
- }
- return false;
- }
- return true;
- }();
-}
-
bool cmQtAutoGenerator::FileWrite(std::string const& filename,
std::string const& content,
std::string* error)
diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h
index 5c3a8ad..66399d7 100644
--- a/Source/cmQtAutoGenerator.h
+++ b/Source/cmQtAutoGenerator.h
@@ -70,8 +70,6 @@ public:
// -- File system methods
static bool MakeParentDirectory(std::string const& filename);
- static bool FileRead(std::string& content, std::string const& filename,
- std::string* error = nullptr);
static bool FileWrite(std::string const& filename,
std::string const& content,
std::string* error = nullptr);
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 2753fd5..86d54f9 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -30,6 +30,7 @@
#include "cmGeneratedFileStream.h"
#include "cmQtAutoGen.h"
#include "cmQtAutoGenerator.h"
+#include "cmQtAutoUicHelpers.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmWorkerPool.h"
@@ -281,7 +282,7 @@ public:
std::vector<std::string> Options;
std::unordered_map<std::string, UiFile> UiFiles;
std::vector<std::string> SearchPaths;
- cmsys::RegularExpression RegExpInclude;
+ cmQtAutoUicHelpers AutoUicHelpers;
};
/** Uic shared variables. */
@@ -761,11 +762,7 @@ std::string cmQtAutoMocUicT::MocSettingsT::MacrosString() const
return res;
}
-cmQtAutoMocUicT::UicSettingsT::UicSettingsT()
-{
- this->RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+"
- "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
-}
+cmQtAutoMocUicT::UicSettingsT::UicSettingsT() = default;
cmQtAutoMocUicT::UicSettingsT::~UicSettingsT() = default;
@@ -1056,16 +1053,7 @@ void cmQtAutoMocUicT::JobParseT::UicIncludes()
}
std::set<std::string> includes;
- {
- const char* contentChars = this->Content.c_str();
- cmsys::RegularExpression const& regExp = this->UicConst().RegExpInclude;
- cmsys::RegularExpressionMatch match;
- while (regExp.find(contentChars, match)) {
- includes.emplace(match.match(2));
- // Forward content pointer
- contentChars += match.end();
- }
- }
+ this->UicConst().AutoUicHelpers.CollectUicIncludes(includes, this->Content);
this->CreateKeys(this->FileHandle->ParseData->Uic.Include, includes,
UiUnderscoreLength);
}
diff --git a/Source/cmQtAutoUicHelpers.cxx b/Source/cmQtAutoUicHelpers.cxx
new file mode 100644
index 0000000..751ae08
--- /dev/null
+++ b/Source/cmQtAutoUicHelpers.cxx
@@ -0,0 +1,25 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmQtAutoUicHelpers.h"
+
+cmQtAutoUicHelpers::cmQtAutoUicHelpers()
+{
+ RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+"
+ "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
+}
+
+void cmQtAutoUicHelpers::CollectUicIncludes(std::set<std::string>& includes,
+ const std::string& content) const
+{
+ if (content.find("ui_") == std::string::npos) {
+ return;
+ }
+
+ const char* contentChars = content.c_str();
+ cmsys::RegularExpressionMatch match;
+ while (this->RegExpInclude.find(contentChars, match)) {
+ includes.emplace(match.match(2));
+ // Forward content pointer
+ contentChars += match.end();
+ }
+}
diff --git a/Source/cmQtAutoUicHelpers.h b/Source/cmQtAutoUicHelpers.h
new file mode 100644
index 0000000..6b09a31
--- /dev/null
+++ b/Source/cmQtAutoUicHelpers.h
@@ -0,0 +1,20 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <set>
+#include <string>
+
+#include "cmsys/RegularExpression.hxx"
+
+class cmQtAutoUicHelpers
+{
+public:
+ cmQtAutoUicHelpers();
+ virtual ~cmQtAutoUicHelpers() = default;
+ void CollectUicIncludes(std::set<std::string>& includes,
+ const std::string& content) const;
+
+private:
+ cmsys::RegularExpression RegExpInclude;
+};