summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2017-11-20 15:12:56 (GMT)
committerKitware Robot <kwrobot@kitware.com>2017-11-20 15:13:11 (GMT)
commit08ce62bee5bee6805fbb01c1821c438028e858dc (patch)
tree35dcf486f43767fae8380afd444a1bbdde749034 /Source
parent66b37132b6c7d347a0fe83ee5082a751e8e0d9aa (diff)
parent4043463179d5e238cd1505f68fe0a4e75f4feba4 (diff)
downloadCMake-08ce62bee5bee6805fbb01c1821c438028e858dc.zip
CMake-08ce62bee5bee6805fbb01c1821c438028e858dc.tar.gz
CMake-08ce62bee5bee6805fbb01c1821c438028e858dc.tar.bz2
Merge topic 'autogen-rcc-custom-command'
40434631 Autogen: Use integers instead of strings for the Qt version be11a852 Autogen: Use project relative paths in rcc custom command comment ab9d5896 Autogen: Detect rcc feature once during configuration 2a85b5ac Autogen: Make cmQtAutoGeneratorInitializer an instantiable class 75819b86 Autogen: Add and use cmQtAutoGenerator base class 27ed3b35 Autogen: Rename cmQtAutoGenerators to cmQtAutoGeneratorMocUic 1cd285fe Autogen: Remove rcc code from cmQtAutoGenerators a87f82e0 Autogen: Switch to use custom commands for RCC ... Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !1494
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt9
-rw-r--r--Source/cmGlobalGenerator.cxx36
-rw-r--r--Source/cmGlobalGenerator.h5
-rw-r--r--Source/cmQtAutoGen.cxx91
-rw-r--r--Source/cmQtAutoGen.h6
-rw-r--r--Source/cmQtAutoGenDigest.h64
-rw-r--r--Source/cmQtAutoGenerator.cxx320
-rw-r--r--Source/cmQtAutoGenerator.h76
-rw-r--r--Source/cmQtAutoGeneratorInitializer.cxx1618
-rw-r--r--Source/cmQtAutoGeneratorInitializer.h79
-rw-r--r--Source/cmQtAutoGeneratorMocUic.cxx (renamed from Source/cmQtAutoGenerators.cxx)783
-rw-r--r--Source/cmQtAutoGeneratorMocUic.h (renamed from Source/cmQtAutoGenerators.h)73
-rw-r--r--Source/cmQtAutoGeneratorRcc.cxx425
-rw-r--r--Source/cmQtAutoGeneratorRcc.h56
-rw-r--r--Source/cmcmd.cxx20
15 files changed, 2003 insertions, 1658 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 54e5063..6c60675 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -311,11 +311,14 @@ set(SRCS
cmPropertyMap.h
cmQtAutoGen.cxx
cmQtAutoGen.h
- cmQtAutoGenDigest.h
+ cmQtAutoGenerator.cxx
+ cmQtAutoGenerator.h
cmQtAutoGeneratorInitializer.cxx
cmQtAutoGeneratorInitializer.h
- cmQtAutoGenerators.cxx
- cmQtAutoGenerators.h
+ cmQtAutoGeneratorMocUic.cxx
+ cmQtAutoGeneratorMocUic.h
+ cmQtAutoGeneratorRcc.cxx
+ cmQtAutoGeneratorRcc.h
cmRST.cxx
cmRST.h
cmScriptGenerator.h
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index eba95f5..6e903fb 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1314,7 +1314,10 @@ bool cmGlobalGenerator::Compute()
#ifdef CMAKE_BUILD_WITH_CMAKE
// Iterate through all targets and set up automoc for those which have
// the AUTOMOC, AUTOUIC or AUTORCC property set
- cmQtAutoGenDigestUPV autogenDigests = this->CreateQtAutoGeneratorsTargets();
+ auto autogenInits = this->CreateQtAutoGenInitializers();
+ for (auto& autoGen : autogenInits) {
+ autoGen->InitCustomTargets();
+ }
#endif
// Add generator specific helper commands
@@ -1335,10 +1338,11 @@ bool cmGlobalGenerator::Compute()
}
#ifdef CMAKE_BUILD_WITH_CMAKE
- for (cmQtAutoGenDigestUP const& digest : autogenDigests) {
- cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(*digest);
+ for (auto& autoGen : autogenInits) {
+ autoGen->SetupCustomTargets();
+ autoGen.reset(nullptr);
}
- autogenDigests.clear();
+ autogenInits.clear();
#endif
for (cmLocalGenerator* localGen : this->LocalGenerators) {
@@ -1469,9 +1473,10 @@ bool cmGlobalGenerator::ComputeTargetDepends()
return true;
}
-cmQtAutoGenDigestUPV cmGlobalGenerator::CreateQtAutoGeneratorsTargets()
+std::vector<std::unique_ptr<cmQtAutoGeneratorInitializer>>
+cmGlobalGenerator::CreateQtAutoGenInitializers()
{
- cmQtAutoGenDigestUPV autogenDigests;
+ std::vector<std::unique_ptr<cmQtAutoGeneratorInitializer>> autogenInits;
#ifdef CMAKE_BUILD_WITH_CMAKE
for (cmLocalGenerator* localGen : this->LocalGenerators) {
@@ -1507,25 +1512,12 @@ cmQtAutoGenDigestUPV cmGlobalGenerator::CreateQtAutoGeneratorsTargets()
continue;
}
- {
- cmQtAutoGenDigestUP digest(new cmQtAutoGenDigest(target));
- digest->QtVersionMajor = std::move(qtVersionMajor);
- digest->QtVersionMinor =
- cmQtAutoGeneratorInitializer::GetQtMinorVersion(
- target, digest->QtVersionMajor);
- digest->MocEnabled = mocEnabled;
- digest->UicEnabled = uicEnabled;
- digest->RccEnabled = rccEnabled;
- autogenDigests.emplace_back(std::move(digest));
- }
+ autogenInits.emplace_back(new cmQtAutoGeneratorInitializer(
+ target, mocEnabled, uicEnabled, rccEnabled, qtVersionMajor));
}
}
- // Initialize autogen targets
- for (const cmQtAutoGenDigestUP& digest : autogenDigests) {
- cmQtAutoGeneratorInitializer::InitializeAutogenTarget(*digest);
- }
#endif
- return autogenDigests;
+ return autogenInits;
}
cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer(
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 8fcb533..99f33e5 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -15,7 +15,6 @@
#include "cmCustomCommandLines.h"
#include "cmExportSetMap.h"
-#include "cmQtAutoGenDigest.h"
#include "cmStateSnapshot.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
@@ -33,6 +32,7 @@ class cmLinkLineComputer;
class cmLocalGenerator;
class cmMakefile;
class cmOutputConverter;
+class cmQtAutoGeneratorInitializer;
class cmSourceFile;
class cmStateDirectory;
class cmake;
@@ -433,7 +433,8 @@ protected:
virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const;
// Qt auto generators
- cmQtAutoGenDigestUPV CreateQtAutoGeneratorsTargets();
+ std::vector<std::unique_ptr<cmQtAutoGeneratorInitializer>>
+ CreateQtAutoGenInitializers();
std::string SelectMakeProgram(const std::string& makeProgram,
const std::string& makeDefault = "") const;
diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
index 9dc77ac..b9dd392 100644
--- a/Source/cmQtAutoGen.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -80,16 +80,6 @@ void MergeOptions(std::vector<std::string>& baseOpts,
baseOpts.insert(baseOpts.end(), extraOpts.begin(), extraOpts.end());
}
-static std::string utilStripCR(std::string const& line)
-{
- // Strip CR characters rcc may have printed (possibly more than one!).
- std::string::size_type cr = line.find('\r');
- if (cr != std::string::npos) {
- return line.substr(0, cr);
- }
- return line;
-}
-
/// @brief Reads the resource files list from from a .qrc file - Qt4 version
/// @return True if the .qrc file was successfully parsed
static bool RccListInputsQt4(std::string const& fileName,
@@ -107,10 +97,10 @@ static bool RccListInputsQt4(std::string const& fileName,
qrcContents = osst.str();
} else {
if (errorMessage != nullptr) {
- std::ostringstream ost;
- ost << "rcc file not readable:\n"
- << " " << cmQtAutoGen::Quoted(fileName) << "\n";
- *errorMessage = ost.str();
+ std::string& err = *errorMessage;
+ err = "rcc file not readable:\n ";
+ err += cmQtAutoGen::Quoted(fileName);
+ err += "\n";
}
allGood = false;
}
@@ -146,6 +136,7 @@ static bool RccListInputsQt4(std::string const& fileName,
/// @brief Reads the resource files list from from a .qrc file - Qt5 version
/// @return True if the .qrc file was successfully parsed
static bool RccListInputsQt5(std::string const& rccCommand,
+ std::vector<std::string> const& rccListOptions,
std::string const& fileName,
std::vector<std::string>& files,
std::string* errorMessage)
@@ -155,24 +146,6 @@ static bool RccListInputsQt5(std::string const& rccCommand,
return false;
}
- // Read rcc features
- bool hasDashDashList = false;
- {
- std::vector<std::string> command;
- command.push_back(rccCommand);
- command.push_back("--help");
- std::string rccStdOut;
- std::string rccStdErr;
- int retVal = 0;
- bool result = cmSystemTools::RunSingleCommand(
- command, &rccStdOut, &rccStdErr, &retVal, nullptr,
- cmSystemTools::OUTPUT_NONE, 0.0, cmProcessOutput::Auto);
- if (result && retVal == 0 &&
- rccStdOut.find("--list") != std::string::npos) {
- hasDashDashList = true;
- }
- }
-
std::string const fileDir = cmSystemTools::GetFilenamePath(fileName);
std::string const fileNameName = cmSystemTools::GetFilenameName(fileName);
@@ -184,7 +157,8 @@ static bool RccListInputsQt5(std::string const& rccCommand,
{
std::vector<std::string> command;
command.push_back(rccCommand);
- command.push_back(hasDashDashList ? "--list" : "-list");
+ command.insert(command.end(), rccListOptions.begin(),
+ rccListOptions.end());
command.push_back(fileNameName);
result = cmSystemTools::RunSingleCommand(
command, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(),
@@ -192,22 +166,32 @@ static bool RccListInputsQt5(std::string const& rccCommand,
}
if (!result || retVal) {
if (errorMessage != nullptr) {
- std::ostringstream ost;
- ost << "rcc list process failed for\n " << cmQtAutoGen::Quoted(fileName)
- << "\n"
- << rccStdOut << "\n"
- << rccStdErr << "\n";
- *errorMessage = ost.str();
+ std::string& err = *errorMessage;
+ err = "rcc list process failed for:\n ";
+ err += cmQtAutoGen::Quoted(fileName);
+ err += "\n";
+ err += rccStdOut;
+ err += "\n";
+ err += rccStdErr;
+ err += "\n";
}
return false;
}
+ // Lambda to strip CR characters
+ auto StripCR = [](std::string& line) {
+ std::string::size_type cr = line.find('\r');
+ if (cr != std::string::npos) {
+ line = line.substr(0, cr);
+ }
+ };
+
// Parse rcc std output
{
std::istringstream ostr(rccStdOut);
std::string oline;
while (std::getline(ostr, oline)) {
- oline = utilStripCR(oline);
+ StripCR(oline);
if (!oline.empty()) {
files.push_back(oline);
}
@@ -218,17 +202,17 @@ static bool RccListInputsQt5(std::string const& rccCommand,
std::istringstream estr(rccStdErr);
std::string eline;
while (std::getline(estr, eline)) {
- eline = utilStripCR(eline);
+ StripCR(eline);
if (cmHasLiteralPrefix(eline, "RCC: Error in")) {
static std::string searchString = "Cannot find file '";
std::string::size_type pos = eline.find(searchString);
if (pos == std::string::npos) {
if (errorMessage != nullptr) {
- std::ostringstream ost;
- ost << "rcc lists unparsable output:\n"
- << cmQtAutoGen::Quoted(eline) << "\n";
- *errorMessage = ost.str();
+ std::string& err = *errorMessage;
+ err = "rcc lists unparsable output:\n";
+ err += cmQtAutoGen::Quoted(eline);
+ err += "\n";
}
return false;
}
@@ -349,25 +333,26 @@ void cmQtAutoGen::RccMergeOptions(std::vector<std::string>& baseOpts,
MergeOptions(baseOpts, newOpts, valueOpts, isQt5);
}
-bool cmQtAutoGen::RccListInputs(std::string const& qtMajorVersion,
- std::string const& rccCommand,
+bool cmQtAutoGen::RccListInputs(std::string const& rccCommand,
+ std::vector<std::string> const& rccListOptions,
std::string const& fileName,
std::vector<std::string>& files,
std::string* errorMessage)
{
bool allGood = false;
if (cmSystemTools::FileExists(fileName.c_str())) {
- if (qtMajorVersion == "4") {
+ if (rccListOptions.empty()) {
allGood = RccListInputsQt4(fileName, files, errorMessage);
} else {
- allGood = RccListInputsQt5(rccCommand, fileName, files, errorMessage);
+ allGood = RccListInputsQt5(rccCommand, rccListOptions, fileName, files,
+ errorMessage);
}
} else {
if (errorMessage != nullptr) {
- std::ostringstream ost;
- ost << "rcc file does not exist:\n"
- << " " << cmQtAutoGen::Quoted(fileName) << "\n";
- *errorMessage = ost.str();
+ std::string& err = *errorMessage;
+ err = "rcc resource file does not exist:\n ";
+ err += cmQtAutoGen::Quoted(fileName);
+ err += "\n";
}
}
return allGood;
diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h
index acc092f..e769e93 100644
--- a/Source/cmQtAutoGen.h
+++ b/Source/cmQtAutoGen.h
@@ -61,9 +61,9 @@ public:
/// @brief Reads the resource files list from from a .qrc file
/// @arg fileName Must be the absolute path of the .qrc file
- /// @return True if the rcc file was successfully parsed
- static bool RccListInputs(std::string const& qtMajorVersion,
- std::string const& rccCommand,
+ /// @return True if the rcc file was successfully read
+ static bool RccListInputs(std::string const& rccCommand,
+ std::vector<std::string> const& rccListOptions,
std::string const& fileName,
std::vector<std::string>& files,
std::string* errorMessage = nullptr);
diff --git a/Source/cmQtAutoGenDigest.h b/Source/cmQtAutoGenDigest.h
deleted file mode 100644
index 677c397..0000000
--- a/Source/cmQtAutoGenDigest.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmQtAutoGenDigest_h
-#define cmQtAutoGenDigest_h
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <memory>
-#include <string>
-#include <vector>
-
-class cmGeneratorTarget;
-
-class cmQtAutoGenDigestQrc
-{
-public:
- cmQtAutoGenDigestQrc()
- : Generated(false)
- , Unique(false)
- {
- }
-
-public:
- std::string QrcFile;
- std::string QrcName;
- std::string PathChecksum;
- std::string RccFile;
- bool Generated;
- bool Unique;
- std::vector<std::string> Options;
- std::vector<std::string> Resources;
-};
-
-/** \class cmQtAutoGenDigest
- * \brief Filtered set of QtAutogen variables for a specific target
- */
-class cmQtAutoGenDigest
-{
-public:
- cmQtAutoGenDigest(cmGeneratorTarget* target)
- : Target(target)
- , MocEnabled(false)
- , UicEnabled(false)
- , RccEnabled(false)
- {
- }
-
-public:
- cmGeneratorTarget* Target;
- std::string QtVersionMajor;
- std::string QtVersionMinor;
- bool MocEnabled;
- bool UicEnabled;
- bool RccEnabled;
- std::vector<std::string> Headers;
- std::vector<std::string> Sources;
- std::vector<cmQtAutoGenDigestQrc> Qrcs;
-};
-
-// Utility types
-typedef std::unique_ptr<cmQtAutoGenDigest> cmQtAutoGenDigestUP;
-typedef std::vector<cmQtAutoGenDigestUP> cmQtAutoGenDigestUPV;
-
-#endif
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
new file mode 100644
index 0000000..52193af
--- /dev/null
+++ b/Source/cmQtAutoGenerator.cxx
@@ -0,0 +1,320 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmQtAutoGen.h"
+#include "cmQtAutoGenerator.h"
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/Terminal.h"
+
+#include "cmAlgorithms.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+// -- Static functions
+
+static std::string HeadLine(std::string const& title)
+{
+ std::string head = title;
+ head += '\n';
+ head.append(head.size() - 1, '-');
+ head += '\n';
+ return head;
+}
+
+static std::string QuotedCommand(std::vector<std::string> const& command)
+{
+ std::string res;
+ for (std::string const& item : command) {
+ if (!res.empty()) {
+ res.push_back(' ');
+ }
+ std::string const cesc = cmQtAutoGen::Quoted(item);
+ if (item.empty() || (cesc.size() > (item.size() + 2)) ||
+ (cesc.find(' ') != std::string::npos)) {
+ res += cesc;
+ } else {
+ res += item;
+ }
+ }
+ return res;
+}
+
+// -- Class methods
+
+cmQtAutoGenerator::cmQtAutoGenerator()
+ : Verbose(cmSystemTools::HasEnv("VERBOSE"))
+ , ColorOutput(true)
+{
+ {
+ std::string colorEnv;
+ cmSystemTools::GetEnv("COLOR", colorEnv);
+ if (!colorEnv.empty()) {
+ this->ColorOutput = cmSystemTools::IsOn(colorEnv.c_str());
+ }
+ }
+}
+
+bool cmQtAutoGenerator::Run(std::string const& infoFile,
+ std::string const& config)
+{
+ // Info settings
+ this->InfoFile = infoFile;
+ cmSystemTools::ConvertToUnixSlashes(this->InfoFile);
+ this->InfoDir = cmSystemTools::GetFilenamePath(infoFile);
+ this->InfoConfig = config;
+
+ cmake cm(cmake::RoleScript);
+ cm.SetHomeOutputDirectory(this->InfoDir);
+ cm.SetHomeDirectory(this->InfoDir);
+ cm.GetCurrentSnapshot().SetDefaultDefinitions();
+ cmGlobalGenerator gg(&cm);
+
+ cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
+ snapshot.GetDirectory().SetCurrentBinary(this->InfoDir);
+ snapshot.GetDirectory().SetCurrentSource(this->InfoDir);
+
+ auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot);
+ gg.SetCurrentMakefile(makefile.get());
+
+ return this->Process(makefile.get());
+}
+
+void cmQtAutoGenerator::LogBold(std::string const& message) const
+{
+ cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
+ cmsysTerminal_Color_ForegroundBold,
+ message.c_str(), true, this->ColorOutput);
+}
+
+void cmQtAutoGenerator::LogInfo(cmQtAutoGen::Generator genType,
+ std::string const& message) const
+{
+ std::string msg = cmQtAutoGen::GeneratorName(genType);
+ msg += ": ";
+ msg += message;
+ if (msg.back() != '\n') {
+ msg.push_back('\n');
+ }
+ cmSystemTools::Stdout(msg.c_str(), msg.size());
+}
+
+void cmQtAutoGenerator::LogWarning(cmQtAutoGen::Generator genType,
+ std::string const& message) const
+{
+ std::string msg = cmQtAutoGen::GeneratorName(genType);
+ msg += " warning:";
+ if (message.find('\n') == std::string::npos) {
+ // Single line message
+ msg.push_back(' ');
+ } else {
+ // Multi line message
+ msg.push_back('\n');
+ }
+ // Message
+ msg += message;
+ if (msg.back() != '\n') {
+ msg.push_back('\n');
+ }
+ msg.push_back('\n');
+ cmSystemTools::Stdout(msg.c_str(), msg.size());
+}
+
+void cmQtAutoGenerator::LogFileWarning(cmQtAutoGen::Generator genType,
+ std::string const& filename,
+ std::string const& message) const
+{
+ std::string msg = " ";
+ msg += cmQtAutoGen::Quoted(filename);
+ msg.push_back('\n');
+ // Message
+ msg += message;
+ this->LogWarning(genType, msg);
+}
+
+void cmQtAutoGenerator::LogError(cmQtAutoGen::Generator genType,
+ std::string const& message) const
+{
+ std::string msg;
+ msg.push_back('\n');
+ msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " error");
+ // Message
+ msg += message;
+ if (msg.back() != '\n') {
+ msg.push_back('\n');
+ }
+ msg.push_back('\n');
+ cmSystemTools::Stderr(msg.c_str(), msg.size());
+}
+
+void cmQtAutoGenerator::LogFileError(cmQtAutoGen::Generator genType,
+ std::string const& filename,
+ std::string const& message) const
+{
+ std::string emsg = " ";
+ emsg += cmQtAutoGen::Quoted(filename);
+ emsg += '\n';
+ // Message
+ emsg += message;
+ this->LogError(genType, emsg);
+}
+
+void cmQtAutoGenerator::LogCommandError(
+ cmQtAutoGen::Generator genType, std::string const& message,
+ std::vector<std::string> const& command, std::string const& output) const
+{
+ std::string msg;
+ msg.push_back('\n');
+ msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " subprocess error");
+ msg += message;
+ if (msg.back() != '\n') {
+ msg.push_back('\n');
+ }
+ msg.push_back('\n');
+ msg += HeadLine("Command");
+ msg += QuotedCommand(command);
+ if (msg.back() != '\n') {
+ msg.push_back('\n');
+ }
+ msg.push_back('\n');
+ msg += HeadLine("Output");
+ msg += output;
+ if (msg.back() != '\n') {
+ msg.push_back('\n');
+ }
+ msg.push_back('\n');
+ cmSystemTools::Stderr(msg.c_str(), msg.size());
+}
+
+/**
+ * @brief Generates the parent directory of the given file on demand
+ * @return True on success
+ */
+bool cmQtAutoGenerator::MakeParentDirectory(cmQtAutoGen::Generator genType,
+ std::string const& filename) const
+{
+ bool success = true;
+ std::string const dirName = cmSystemTools::GetFilenamePath(filename);
+ if (!dirName.empty()) {
+ if (!cmSystemTools::MakeDirectory(dirName)) {
+ this->LogFileError(genType, filename,
+ "Could not create parent directory");
+ success = false;
+ }
+ }
+ return success;
+}
+
+/**
+ * @brief Tests if buildFile is older than sourceFile
+ * @return True if buildFile is older than sourceFile.
+ * False may indicate an error.
+ */
+bool cmQtAutoGenerator::FileIsOlderThan(std::string const& buildFile,
+ std::string const& sourceFile,
+ std::string* error)
+{
+ int result = 0;
+ if (cmSystemTools::FileTimeCompare(buildFile, sourceFile, &result)) {
+ return (result < 0);
+ }
+ if (error != nullptr) {
+ error->append(
+ "File modification time comparison failed for the files\n ");
+ error->append(cmQtAutoGen::Quoted(buildFile));
+ error->append("\nand\n ");
+ error->append(cmQtAutoGen::Quoted(sourceFile));
+ }
+ return false;
+}
+
+bool cmQtAutoGenerator::FileRead(std::string& content,
+ std::string const& filename,
+ std::string* error)
+{
+ bool success = false;
+ if (cmSystemTools::FileExists(filename)) {
+ std::size_t const length = cmSystemTools::FileLength(filename);
+ cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
+ if (ifs) {
+ content.resize(length);
+ ifs.read(&content.front(), content.size());
+ if (ifs) {
+ success = true;
+ } else {
+ content.clear();
+ if (error != nullptr) {
+ error->append("Reading from the file failed.");
+ }
+ }
+ } else if (error != nullptr) {
+ error->append("Opening the file for reading failed.");
+ }
+ } else if (error != nullptr) {
+ error->append("The file does not exist.");
+ }
+ return success;
+}
+
+bool cmQtAutoGenerator::FileWrite(cmQtAutoGen::Generator genType,
+ std::string const& filename,
+ std::string const& content)
+{
+ std::string error;
+ // Make sure the parent directory exists
+ if (this->MakeParentDirectory(genType, filename)) {
+ cmsys::ofstream outfile;
+ outfile.open(filename.c_str(),
+ (std::ios::out | std::ios::binary | std::ios::trunc));
+ if (outfile) {
+ outfile << content;
+ // Check for write errors
+ if (!outfile.good()) {
+ error = "File writing failed";
+ }
+ } else {
+ error = "Opening file for writing failed";
+ }
+ }
+ if (!error.empty()) {
+ this->LogFileError(genType, filename, error);
+ return false;
+ }
+ return true;
+}
+
+bool cmQtAutoGenerator::FileDiffers(std::string const& filename,
+ std::string const& content)
+{
+ bool differs = true;
+ {
+ std::string oldContents;
+ if (this->FileRead(oldContents, filename)) {
+ differs = (oldContents != content);
+ }
+ }
+ return differs;
+}
+
+/**
+ * @brief Runs a command and returns true on success
+ * @return True on success
+ */
+bool cmQtAutoGenerator::RunCommand(std::vector<std::string> const& command,
+ std::string& output) const
+{
+ // Log command
+ if (this->Verbose) {
+ std::string qcmd = QuotedCommand(command);
+ qcmd.push_back('\n');
+ cmSystemTools::Stdout(qcmd.c_str(), qcmd.size());
+ }
+ // Execute command
+ int retVal = 0;
+ bool res = cmSystemTools::RunSingleCommand(
+ command, &output, &output, &retVal, nullptr, cmSystemTools::OUTPUT_NONE);
+ return (res && (retVal == 0));
+}
diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h
new file mode 100644
index 0000000..285340d
--- /dev/null
+++ b/Source/cmQtAutoGenerator.h
@@ -0,0 +1,76 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmQtAutoGenerator_h
+#define cmQtAutoGenerator_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmQtAutoGen.h"
+
+#include <string>
+#include <vector>
+
+class cmMakefile;
+
+class cmQtAutoGenerator
+{
+ CM_DISABLE_COPY(cmQtAutoGenerator)
+public:
+ cmQtAutoGenerator();
+ virtual ~cmQtAutoGenerator() = default;
+ bool Run(std::string const& infoFile, std::string const& config);
+
+ std::string const& GetInfoFile() const { return InfoFile; }
+ std::string const& GetInfoDir() const { return InfoDir; }
+ std::string const& GetInfoConfig() const { return InfoConfig; }
+ bool GetVerbose() const { return Verbose; }
+
+protected:
+ // -- Central processing
+ virtual bool Process(cmMakefile* makefile) = 0;
+
+ // -- Log info
+ void LogBold(std::string const& message) const;
+ void LogInfo(cmQtAutoGen::Generator genType,
+ std::string const& message) const;
+ // -- Log warning
+ void LogWarning(cmQtAutoGen::Generator genType,
+ std::string const& message) const;
+ void LogFileWarning(cmQtAutoGen::Generator genType,
+ std::string const& filename,
+ std::string const& message) const;
+ // -- Log error
+ void LogError(cmQtAutoGen::Generator genType,
+ std::string const& message) const;
+ void LogFileError(cmQtAutoGen::Generator genType,
+ std::string const& filename,
+ std::string const& message) const;
+ void LogCommandError(cmQtAutoGen::Generator genType,
+ std::string const& message,
+ std::vector<std::string> const& command,
+ std::string const& output) const;
+ // -- Utility
+ bool MakeParentDirectory(cmQtAutoGen::Generator genType,
+ std::string const& filename) const;
+ bool FileIsOlderThan(std::string const& buildFile,
+ std::string const& sourceFile,
+ std::string* error = nullptr);
+ bool FileRead(std::string& content, std::string const& filename,
+ std::string* error = nullptr);
+ bool FileWrite(cmQtAutoGen::Generator genType, std::string const& filename,
+ std::string const& content);
+ bool FileDiffers(std::string const& filename, std::string const& content);
+ bool RunCommand(std::vector<std::string> const& command,
+ std::string& output) const;
+
+private:
+ // -- Info settings
+ std::string InfoFile;
+ std::string InfoDir;
+ std::string InfoConfig;
+ // -- Settings
+ bool Verbose;
+ bool ColorOutput;
+};
+
+#endif
diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
index c7550e6..d9a5a9a 100644
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ b/Source/cmQtAutoGeneratorInitializer.cxx
@@ -14,6 +14,7 @@
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
+#include "cmProcessOutput.h"
#include "cmSourceFile.h"
#include "cmSourceGroup.h"
#include "cmState.h"
@@ -51,118 +52,6 @@ inline static std::string GetSafeProperty(cmSourceFile const* sf,
return std::string(SafeString(sf->GetProperty(key)));
}
-static cmQtAutoGen::MultiConfig AutogenMultiConfig(
- cmGlobalGenerator* globalGen)
-{
- if (!globalGen->IsMultiConfig()) {
- return cmQtAutoGen::SINGLE;
- }
-
- // FIXME: Xcode does not support per-config sources, yet.
- // (EXCLUDED_SOURCE_FILE_NAMES)
- // if (globalGen->GetName().find("Xcode") != std::string::npos) {
- // return cmQtAutoGen::FULL;
- //}
-
- // FIXME: Visual Studio does not support per-config sources, yet.
- // (EXCLUDED_SOURCE_FILE_NAMES)
- // if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
- // return cmQtAutoGen::FULL;
- //}
-
- return cmQtAutoGen::WRAP;
-}
-
-static std::string GetAutogenTargetName(cmGeneratorTarget const* target)
-{
- std::string autogenTargetName = target->GetName();
- autogenTargetName += "_autogen";
- return autogenTargetName;
-}
-
-static std::string GetAutogenTargetFilesDir(cmGeneratorTarget const* target)
-{
- cmMakefile* makefile = target->Target->GetMakefile();
- std::string targetDir = makefile->GetCurrentBinaryDirectory();
- targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
- targetDir += "/";
- targetDir += GetAutogenTargetName(target);
- targetDir += ".dir";
- return targetDir;
-}
-
-static std::string GetAutogenTargetBuildDir(cmGeneratorTarget const* target)
-{
- std::string targetDir = GetSafeProperty(target, "AUTOGEN_BUILD_DIR");
- if (targetDir.empty()) {
- cmMakefile* makefile = target->Target->GetMakefile();
- targetDir = makefile->GetCurrentBinaryDirectory();
- targetDir += "/";
- targetDir += GetAutogenTargetName(target);
- }
- return targetDir;
-}
-
-std::string cmQtAutoGeneratorInitializer::GetQtMajorVersion(
- cmGeneratorTarget const* target)
-{
- cmMakefile* makefile = target->Target->GetMakefile();
- std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
- if (qtMajor.empty()) {
- qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
- }
- const char* targetQtVersion =
- target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "");
- if (targetQtVersion != nullptr) {
- qtMajor = targetQtVersion;
- }
- return qtMajor;
-}
-
-std::string cmQtAutoGeneratorInitializer::GetQtMinorVersion(
- cmGeneratorTarget const* target, std::string const& qtVersionMajor)
-{
- cmMakefile* makefile = target->Target->GetMakefile();
- std::string qtMinor;
- if (qtVersionMajor == "5") {
- qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR");
- }
- if (qtMinor.empty()) {
- qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR");
- }
-
- const char* targetQtVersion =
- target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", "");
- if (targetQtVersion != nullptr) {
- qtMinor = targetQtVersion;
- }
- return qtMinor;
-}
-
-static bool QtVersionGreaterOrEqual(std::string const& major,
- std::string const& minor,
- unsigned long requestMajor,
- unsigned long requestMinor)
-{
- unsigned long majorUL(0);
- unsigned long minorUL(0);
- if (cmSystemTools::StringToULong(major.c_str(), &majorUL) &&
- cmSystemTools::StringToULong(minor.c_str(), &minorUL)) {
- return (majorUL > requestMajor) ||
- (majorUL == requestMajor && minorUL >= requestMinor);
- }
- return false;
-}
-
-static void GetConfigs(cmMakefile* makefile, std::string& configDefault,
- std::vector<std::string>& configsList)
-{
- configDefault = makefile->GetConfigurations(configsList);
- if (configsList.empty()) {
- configsList.push_back(configDefault);
- }
-}
-
static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
std::string const& value)
{
@@ -258,48 +147,24 @@ static void AddCleanFile(cmMakefile* makefile, std::string const& fileName)
false);
}
-static std::vector<std::string> AddGeneratedSource(
- cmGeneratorTarget* target, std::string const& filename,
- cmQtAutoGen::MultiConfig multiConfig,
- const std::vector<std::string>& configsList, cmQtAutoGen::Generator genType)
+static std::string FileProjectRelativePath(cmMakefile* makefile,
+ std::string const& fileName)
{
- std::vector<std::string> genFiles;
- // Register source file in makefile and source group
- if (multiConfig != cmQtAutoGen::FULL) {
- genFiles.push_back(filename);
- } else {
- for (std::string const& cfg : configsList) {
- genFiles.push_back(
- cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg));
- }
- }
+ std::string res;
{
- cmMakefile* makefile = target->Target->GetMakefile();
- for (std::string const& genFile : genFiles) {
- {
- cmSourceFile* gFile = makefile->GetOrCreateSource(genFile, true);
- gFile->SetProperty("GENERATED", "1");
- gFile->SetProperty("SKIP_AUTOGEN", "On");
- }
- AddToSourceGroup(makefile, genFile, genType);
- }
- }
-
- // Add source file to target
- if (multiConfig != cmQtAutoGen::FULL) {
- target->AddSource(filename);
- } else {
- for (std::string const& cfg : configsList) {
- std::string src = "$<$<CONFIG:";
- src += cfg;
- src += ">:";
- src += cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg);
- src += ">";
- target->AddSource(src);
+ std::string pSource = cmSystemTools::RelativePath(
+ makefile->GetCurrentSourceDirectory(), fileName.c_str());
+ std::string pBinary = cmSystemTools::RelativePath(
+ makefile->GetCurrentBinaryDirectory(), fileName.c_str());
+ if (pSource.size() < pBinary.size()) {
+ res = std::move(pSource);
+ } else if (pBinary.size() < fileName.size()) {
+ res = std::move(pBinary);
+ } else {
+ res = fileName;
}
}
-
- return genFiles;
+ return res;
}
/* @brief Tests if targetDepend is a STATIC_LIBRARY and if any of its
@@ -346,350 +211,123 @@ static bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin,
return cycle;
}
-struct cmQtAutoGenSetup
-{
- std::set<std::string> MocSkip;
- std::set<std::string> UicSkip;
-
- std::map<std::string, std::string> ConfigMocIncludes;
- std::map<std::string, std::string> ConfigMocDefines;
- std::map<std::string, std::string> ConfigUicOptions;
-};
-
-static void SetupAcquireSkipFiles(cmQtAutoGenDigest const& digest,
- cmQtAutoGenSetup& setup)
+cmQtAutoGeneratorInitializer::cmQtAutoGeneratorInitializer(
+ cmGeneratorTarget* target, bool mocEnabled, bool uicEnabled, bool rccEnabled,
+ std::string const& qtVersionMajor)
+ : Target(target)
+ , MocEnabled(mocEnabled)
+ , UicEnabled(uicEnabled)
+ , RccEnabled(rccEnabled)
+ , QtVersionMajor(qtVersionMajor)
+ , MultiConfig(cmQtAutoGen::WRAP)
{
- // Read skip files from makefile sources
- {
- const std::vector<cmSourceFile*>& allSources =
- digest.Target->Makefile->GetSourceFiles();
- for (cmSourceFile* sf : allSources) {
- // sf->GetExtension() is only valid after sf->GetFullPath() ...
- std::string const& fPath = sf->GetFullPath();
- cmSystemTools::FileFormat const fileType =
- cmSystemTools::GetFileFormat(sf->GetExtension().c_str());
- if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) &&
- !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
- continue;
- }
- const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN");
- const bool mocSkip = digest.MocEnabled &&
- (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC"));
- const bool uicSkip = digest.UicEnabled &&
- (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC"));
- if (mocSkip || uicSkip) {
- std::string const absFile = cmSystemTools::GetRealPath(fPath);
- if (mocSkip) {
- setup.MocSkip.insert(absFile);
- }
- if (uicSkip) {
- setup.UicSkip.insert(absFile);
- }
- }
- }
- }
+ this->QtVersionMinor = cmQtAutoGeneratorInitializer::GetQtMinorVersion(
+ target, this->QtVersionMajor);
}
-static void SetupAutoTargetMoc(cmQtAutoGenDigest const& digest,
- std::string const& configDefault,
- std::vector<std::string> const& configsList,
- cmQtAutoGenSetup& setup)
+void cmQtAutoGeneratorInitializer::InitCustomTargets()
{
- cmGeneratorTarget const* target = digest.Target;
- cmLocalGenerator* localGen = target->GetLocalGenerator();
- cmMakefile* makefile = target->Target->GetMakefile();
-
- AddDefinitionEscaped(makefile, "_moc_skip", setup.MocSkip);
- AddDefinitionEscaped(makefile, "_moc_options",
- GetSafeProperty(target, "AUTOMOC_MOC_OPTIONS"));
- AddDefinitionEscaped(makefile, "_moc_relaxed_mode",
- makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE"
- : "FALSE");
- AddDefinitionEscaped(makefile, "_moc_macro_names",
- GetSafeProperty(target, "AUTOMOC_MACRO_NAMES"));
- AddDefinitionEscaped(makefile, "_moc_depend_filters",
- GetSafeProperty(target, "AUTOMOC_DEPEND_FILTERS"));
-
- // Compiler predefines
- if (target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES")) {
- if (QtVersionGreaterOrEqual(digest.QtVersionMajor, digest.QtVersionMinor,
- 5, 8)) {
- AddDefinitionEscaped(
- makefile, "_moc_predefs_cmd",
- makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"));
- }
- }
- // Moc includes and compile definitions
- {
- auto GetIncludeDirs = [target,
- localGen](std::string const& cfg) -> std::string {
- // Get the include dirs for this target, without stripping the implicit
- // include dirs off, see
- // https://gitlab.kitware.com/cmake/cmake/issues/13667
- std::vector<std::string> includeDirs;
- localGen->GetIncludeDirectories(includeDirs, target, "CXX", cfg, false);
- return cmJoin(includeDirs, ";");
- };
- auto GetCompileDefinitions =
- [target, localGen](std::string const& cfg) -> std::string {
- std::set<std::string> defines;
- localGen->AddCompileDefinitions(defines, target, cfg, "CXX");
- return cmJoin(defines, ";");
- };
+ cmMakefile* makefile = this->Target->Target->GetMakefile();
+ cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+ cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();
- // Default configuration settings
- std::string const includeDirs = GetIncludeDirs(configDefault);
- std::string const compileDefs = GetCompileDefinitions(configDefault);
- // Other configuration settings
- for (std::string const& cfg : configsList) {
- {
- std::string const configIncludeDirs = GetIncludeDirs(cfg);
- if (configIncludeDirs != includeDirs) {
- setup.ConfigMocIncludes[cfg] = configIncludeDirs;
- }
- }
- {
- std::string const configCompileDefs = GetCompileDefinitions(cfg);
- if (configCompileDefs != compileDefs) {
- setup.ConfigMocDefines[cfg] = configCompileDefs;
- }
- }
- }
- AddDefinitionEscaped(makefile, "_moc_include_dirs", includeDirs);
- AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs);
+ // Configurations
+ this->ConfigDefault = makefile->GetConfigurations(this->ConfigsList);
+ if (this->ConfigsList.empty()) {
+ this->ConfigsList.push_back(this->ConfigDefault);
}
- // Moc executable
+ // Multi configuration
{
- std::string mocExec;
- std::string err;
-
- if (digest.QtVersionMajor == "5") {
- cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::moc");
- if (tgt != nullptr) {
- mocExec = SafeString(tgt->ImportedGetLocation(""));
- } else {
- err = "AUTOMOC: Qt5::moc target not found";
- }
- } else if (digest.QtVersionMajor == "4") {
- cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::moc");
- if (tgt != nullptr) {
- mocExec = SafeString(tgt->ImportedGetLocation(""));
- } else {
- err = "AUTOMOC: Qt4::moc target not found";
- }
- } else {
- err = "The AUTOMOC feature supports only Qt 4 and Qt 5";
+ if (!globalGen->IsMultiConfig()) {
+ this->MultiConfig = cmQtAutoGen::SINGLE;
}
- if (err.empty()) {
- AddDefinitionEscaped(makefile, "_qt_moc_executable", mocExec);
- } else {
- err += " (" + target->GetName() + ")";
- cmSystemTools::Error(err.c_str());
- }
+ // FIXME: Xcode does not support per-config sources, yet.
+ // (EXCLUDED_SOURCE_FILE_NAMES)
+ // if (globalGen->GetName().find("Xcode") != std::string::npos) {
+ // return cmQtAutoGen::FULL;
+ //}
+
+ // FIXME: Visual Studio does not support per-config sources, yet.
+ // (EXCLUDED_SOURCE_FILE_NAMES)
+ // if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
+ // return cmQtAutoGen::FULL;
+ //}
}
-}
-static void SetupAutoTargetUic(cmQtAutoGenDigest const& digest,
- std::string const& config,
- std::vector<std::string> const& configs,
- cmQtAutoGenSetup& setup)
-{
- cmGeneratorTarget const* target = digest.Target;
- cmMakefile* makefile = target->Target->GetMakefile();
+ // Autogen target name
+ this->AutogenTargetName = this->Target->GetName();
+ this->AutogenTargetName += "_autogen";
- // Uic search paths
+ // Autogen directories
{
- std::vector<std::string> uicSearchPaths;
- {
- std::string const usp = GetSafeProperty(target, "AUTOUIC_SEARCH_PATHS");
- if (!usp.empty()) {
- cmSystemTools::ExpandListArgument(usp, uicSearchPaths);
- std::string const srcDir = makefile->GetCurrentSourceDirectory();
- for (std::string& path : uicSearchPaths) {
- path = cmSystemTools::CollapseFullPath(path, srcDir);
- }
- }
+ // Collapsed current binary directory
+ std::string const cbd = cmSystemTools::CollapseFullPath(
+ "", makefile->GetCurrentBinaryDirectory());
+
+ // Autogen info dir
+ this->DirInfo = cbd;
+ this->DirInfo += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
+ this->DirInfo += "/";
+ this->DirInfo += this->AutogenTargetName;
+ this->DirInfo += ".dir";
+ cmSystemTools::ConvertToUnixSlashes(this->DirInfo);
+
+ // Autogen build dir
+ this->DirBuild = GetSafeProperty(this->Target, "AUTOGEN_BUILD_DIR");
+ if (this->DirBuild.empty()) {
+ this->DirBuild = cbd;
+ this->DirBuild += "/";
+ this->DirBuild += this->AutogenTargetName;
}
- AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths);
- }
- // Uic target options
- {
- auto UicGetOpts = [target](std::string const& cfg) -> std::string {
- std::vector<std::string> opts;
- target->GetAutoUicOptions(opts, cfg);
- return cmJoin(opts, ";");
- };
+ cmSystemTools::ConvertToUnixSlashes(this->DirBuild);
- // Default settings
- std::string const uicOpts = UicGetOpts(config);
- AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts);
-
- // Configuration specific settings
- for (std::string const& cfg : configs) {
- std::string const configUicOpts = UicGetOpts(cfg);
- if (configUicOpts != uicOpts) {
- setup.ConfigUicOptions[cfg] = configUicOpts;
- }
- }
- }
- // .ui files skip and options
- {
- std::vector<std::string> uiFileFiles;
- std::vector<std::vector<std::string>> uiFileOptions;
- {
- std::string const uiExt = "ui";
- for (cmSourceFile* sf : makefile->GetSourceFiles()) {
- // sf->GetExtension() is only valid after sf->GetFullPath() ...
- std::string const& fPath = sf->GetFullPath();
- if (sf->GetExtension() == uiExt) {
- std::string const absFile = cmSystemTools::GetRealPath(fPath);
- // Check if the file should be skipped
- if (sf->GetPropertyAsBool("SKIP_AUTOUIC") ||
- sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
- setup.UicSkip.insert(absFile);
- }
- // Check if the files has uic options
- std::string const uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS");
- if (!uicOpts.empty()) {
- // Check if file isn't skipped
- if (setup.UicSkip.count(absFile) == 0) {
- uiFileFiles.push_back(absFile);
- std::vector<std::string> optsVec;
- cmSystemTools::ExpandListArgument(uicOpts, optsVec);
- uiFileOptions.push_back(std::move(optsVec));
- }
- }
- }
- }
- }
- AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles);
- AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions);
+ // Working directory
+ this->DirWork = cbd;
+ cmSystemTools::ConvertToUnixSlashes(this->DirWork);
}
- AddDefinitionEscaped(makefile, "_uic_skip", setup.UicSkip);
-
- // Uic executable
+ // Autogen files
{
- std::string err;
- std::string uicExec;
+ this->AutogenInfoFile = this->DirInfo;
+ this->AutogenInfoFile += "/AutogenInfo.cmake";
- cmLocalGenerator* localGen = target->GetLocalGenerator();
- if (digest.QtVersionMajor == "5") {
- cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::uic");
- if (tgt != nullptr) {
- uicExec = SafeString(tgt->ImportedGetLocation(""));
- } else {
- // Project does not use Qt5Widgets, but has AUTOUIC ON anyway
- }
- } else if (digest.QtVersionMajor == "4") {
- cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::uic");
- if (tgt != nullptr) {
- uicExec = SafeString(tgt->ImportedGetLocation(""));
- } else {
- err = "AUTOUIC: Qt4::uic target not found";
- }
- } else {
- err = "The AUTOUIC feature supports only Qt 4 and Qt 5";
- }
-
- if (err.empty()) {
- AddDefinitionEscaped(makefile, "_qt_uic_executable", uicExec);
- } else {
- err += " (" + target->GetName() + ")";
- cmSystemTools::Error(err.c_str());
- }
+ this->AutogenSettingsFile = this->DirInfo;
+ this->AutogenSettingsFile += "/AutogenOldSettings.cmake";
}
-}
-static std::string RccGetExecutable(cmGeneratorTarget const* target,
- std::string const& qtMajorVersion)
-{
- std::string rccExec;
- std::string err;
-
- cmLocalGenerator* localGen = target->GetLocalGenerator();
- if (qtMajorVersion == "5") {
- cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::rcc");
- if (tgt != nullptr) {
- rccExec = SafeString(tgt->ImportedGetLocation(""));
- } else {
- err = "AUTORCC: Qt5::rcc target not found";
+ // Autogen target FOLDER property
+ {
+ const char* folder =
+ makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");
+ if (folder == nullptr) {
+ folder =
+ makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");
}
- } else if (qtMajorVersion == "4") {
- cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::rcc");
- if (tgt != nullptr) {
- rccExec = SafeString(tgt->ImportedGetLocation(""));
- } else {
- err = "AUTORCC: Qt4::rcc target not found";
+ // Inherit FOLDER property from target (#13688)
+ if (folder == nullptr) {
+ folder = SafeString(this->Target->Target->GetProperty("FOLDER"));
+ }
+ if (folder != nullptr) {
+ this->AutogenFolder = folder;
}
- } else {
- err = "The AUTORCC feature supports only Qt 4 and Qt 5";
- }
-
- if (!err.empty()) {
- err += " (" + target->GetName() + ")";
- cmSystemTools::Error(err.c_str());
- }
- return rccExec;
-}
-
-static void SetupAutoTargetRcc(cmQtAutoGenDigest const& digest)
-{
- std::vector<std::string> rccFiles;
- std::vector<std::string> rccBuilds;
- std::vector<std::vector<std::string>> rccOptions;
- std::vector<std::vector<std::string>> rccInputs;
-
- for (cmQtAutoGenDigestQrc const& qrcDigest : digest.Qrcs) {
- rccFiles.push_back(qrcDigest.QrcFile);
- rccBuilds.push_back(qrcDigest.RccFile);
- rccOptions.push_back(qrcDigest.Options);
- rccInputs.push_back(qrcDigest.Resources);
}
- cmMakefile* makefile = digest.Target->Target->GetMakefile();
- AddDefinitionEscaped(makefile, "_qt_rcc_executable",
- RccGetExecutable(digest.Target, digest.QtVersionMajor));
- AddDefinitionEscaped(makefile, "_rcc_files", rccFiles);
- AddDefinitionEscaped(makefile, "_rcc_builds", rccBuilds);
- AddDefinitionEscaped(makefile, "_rcc_options", rccOptions);
- AddDefinitionEscaped(makefile, "_rcc_inputs", rccInputs);
-}
-
-void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
- cmQtAutoGenDigest& digest)
-{
- cmGeneratorTarget* target = digest.Target;
- cmMakefile* makefile = target->Target->GetMakefile();
- cmLocalGenerator* localGen = target->GetLocalGenerator();
- cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();
-
- std::string const autogenTargetName = GetAutogenTargetName(target);
- std::string const autogenInfoDir = GetAutogenTargetFilesDir(target);
- std::string const autogenBuildDir = GetAutogenTargetBuildDir(target);
- std::string const workingDirectory =
- cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory());
-
- cmQtAutoGen::MultiConfig const multiConfig = AutogenMultiConfig(globalGen);
- std::string configDefault;
- std::vector<std::string> configsList;
- GetConfigs(makefile, configDefault, configsList);
-
std::set<std::string> autogenDependFiles;
std::set<cmTarget*> autogenDependTargets;
std::vector<std::string> autogenProvides;
// Remove build directories on cleanup
- AddCleanFile(makefile, autogenBuildDir);
+ AddCleanFile(makefile, this->DirBuild);
// Remove old settings on cleanup
{
- std::string base = autogenInfoDir + "/AutogenOldSettings";
- if (multiConfig == cmQtAutoGen::SINGLE) {
+ std::string base = this->DirInfo;
+ base += "/AutogenOldSettings";
+ if (this->MultiConfig == cmQtAutoGen::SINGLE) {
AddCleanFile(makefile, base.append(".cmake"));
} else {
- for (std::string const& cfg : configsList) {
+ for (std::string const& cfg : this->ConfigsList) {
std::string filename = base;
filename += "_";
filename += cfg;
@@ -699,62 +337,72 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
}
}
- // Compose command lines
- cmCustomCommandLines commandLines;
- {
- cmCustomCommandLine currentLine;
- currentLine.push_back(cmSystemTools::GetCMakeCommand());
- currentLine.push_back("-E");
- currentLine.push_back("cmake_autogen");
- currentLine.push_back(autogenInfoDir);
- currentLine.push_back("$<CONFIGURATION>");
- commandLines.push_back(currentLine);
- }
-
- // Compose target comment
- std::string autogenComment;
- {
- std::vector<std::string> toolNames;
- if (digest.MocEnabled) {
- toolNames.emplace_back("MOC");
- }
- if (digest.UicEnabled) {
- toolNames.emplace_back("UIC");
- }
- if (digest.RccEnabled) {
- toolNames.emplace_back("RCC");
- }
-
- std::string tools = toolNames.front();
- toolNames.erase(toolNames.begin());
- if (!toolNames.empty()) {
- while (toolNames.size() > 1) {
- tools += ", ";
- tools += toolNames.front();
- toolNames.erase(toolNames.begin());
- }
- tools += " and " + toolNames.front();
- }
- autogenComment = "Automatic " + tools + " for target " + target->GetName();
- }
-
// Add moc compilation to generated files list
- if (digest.MocEnabled) {
- std::string const mocsComp = autogenBuildDir + "/mocs_compilation.cpp";
- auto files = AddGeneratedSource(target, mocsComp, multiConfig, configsList,
- cmQtAutoGen::MOC);
+ if (this->MocEnabled) {
+ std::string const mocsComp = this->DirBuild + "/mocs_compilation.cpp";
+ auto files = this->AddGeneratedSource(mocsComp, cmQtAutoGen::MOC);
for (std::string& file : files) {
autogenProvides.push_back(std::move(file));
}
}
// Add autogen includes directory to the origin target INCLUDE_DIRECTORIES
- if (digest.MocEnabled || digest.UicEnabled) {
- std::string includeDir = autogenBuildDir + "/include";
- if (multiConfig != cmQtAutoGen::SINGLE) {
+ if (this->MocEnabled || this->UicEnabled) {
+ std::string includeDir = this->DirBuild + "/include";
+ if (this->MultiConfig != cmQtAutoGen::SINGLE) {
includeDir += "_$<CONFIG>";
}
- target->AddIncludeDirectory(includeDir, true);
+ this->Target->AddIncludeDirectory(includeDir, true);
+ }
+
+ // Acquire rcc executable and features
+ if (this->RccEnabled) {
+ {
+ std::string err;
+ if (this->QtVersionMajor == "5") {
+ cmGeneratorTarget* tgt =
+ localGen->FindGeneratorTargetToUse("Qt5::rcc");
+ if (tgt != nullptr) {
+ this->RccExecutable = SafeString(tgt->ImportedGetLocation(""));
+ } else {
+ err = "AUTORCC: Qt5::rcc target not found";
+ }
+ } else if (QtVersionMajor == "4") {
+ cmGeneratorTarget* tgt =
+ localGen->FindGeneratorTargetToUse("Qt4::rcc");
+ if (tgt != nullptr) {
+ this->RccExecutable = SafeString(tgt->ImportedGetLocation(""));
+ } else {
+ err = "AUTORCC: Qt4::rcc target not found";
+ }
+ } else {
+ err = "The AUTORCC feature supports only Qt 4 and Qt 5";
+ }
+ if (!err.empty()) {
+ err += " (";
+ err += this->Target->GetName();
+ err += ")";
+ cmSystemTools::Error(err.c_str());
+ }
+ }
+ // Detect if rcc supports (-)-list
+ if (!this->RccExecutable.empty() && (this->QtVersionMajor == "5")) {
+ std::vector<std::string> command;
+ command.push_back(this->RccExecutable);
+ command.push_back("--help");
+ std::string rccStdOut;
+ std::string rccStdErr;
+ int retVal = 0;
+ bool result = cmSystemTools::RunSingleCommand(
+ command, &rccStdOut, &rccStdErr, &retVal, nullptr,
+ cmSystemTools::OUTPUT_NONE, 0.0, cmProcessOutput::Auto);
+ if (result && retVal == 0 &&
+ rccStdOut.find("--list") != std::string::npos) {
+ this->RccListOptions.push_back("--list");
+ } else {
+ this->RccListOptions.push_back("-list");
+ }
+ }
}
// Extract relevant source files
@@ -763,7 +411,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
{
std::string const qrcExt = "qrc";
std::vector<cmSourceFile*> srcFiles;
- target->GetConfigCommonSourceFiles(srcFiles);
+ this->Target->GetConfigCommonSourceFiles(srcFiles);
for (cmSourceFile* sf : srcFiles) {
if (sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
continue;
@@ -772,50 +420,50 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
std::string const& fPath = sf->GetFullPath();
std::string const& ext = sf->GetExtension();
// Register generated files that will be scanned by moc or uic
- if (digest.MocEnabled || digest.UicEnabled) {
+ if (this->MocEnabled || this->UicEnabled) {
cmSystemTools::FileFormat const fileType =
cmSystemTools::GetFileFormat(ext.c_str());
if ((fileType == cmSystemTools::CXX_FILE_FORMAT) ||
(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
std::string const absPath = cmSystemTools::GetRealPath(fPath);
- if ((digest.MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) ||
- (digest.UicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) {
+ if ((this->MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) ||
+ (this->UicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) {
// Register source
const bool generated = sf->GetPropertyAsBool("GENERATED");
if (fileType == cmSystemTools::HEADER_FILE_FORMAT) {
if (generated) {
generatedHeaders.push_back(absPath);
} else {
- digest.Headers.push_back(absPath);
+ this->Headers.push_back(absPath);
}
} else {
if (generated) {
generatedSources.push_back(absPath);
} else {
- digest.Sources.push_back(absPath);
+ this->Sources.push_back(absPath);
}
}
}
}
}
// Register rcc enabled files
- if (digest.RccEnabled && (ext == qrcExt) &&
+ if (this->RccEnabled && (ext == qrcExt) &&
!sf->GetPropertyAsBool("SKIP_AUTORCC")) {
// Register qrc file
{
- cmQtAutoGenDigestQrc qrcDigest;
- qrcDigest.QrcFile = cmSystemTools::GetRealPath(fPath);
- qrcDigest.QrcName =
- cmSystemTools::GetFilenameWithoutLastExtension(qrcDigest.QrcFile);
- qrcDigest.Generated = sf->GetPropertyAsBool("GENERATED");
+ Qrc qrc;
+ qrc.QrcFile = cmSystemTools::GetRealPath(fPath);
+ qrc.QrcName =
+ cmSystemTools::GetFilenameWithoutLastExtension(qrc.QrcFile);
+ qrc.Generated = sf->GetPropertyAsBool("GENERATED");
// RCC options
{
std::string const opts = GetSafeProperty(sf, "AUTORCC_OPTIONS");
if (!opts.empty()) {
- cmSystemTools::ExpandListArgument(opts, qrcDigest.Options);
+ cmSystemTools::ExpandListArgument(opts, qrc.Options);
}
}
- digest.Qrcs.push_back(std::move(qrcDigest));
+ this->Qrcs.push_back(std::move(qrc));
}
}
}
@@ -823,7 +471,35 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
// sources meta data cache. Clear it so that OBJECT library targets that
// are AUTOGEN initialized after this target get their added
// mocs_compilation.cpp source acknowledged by this target.
- target->ClearSourcesCache();
+ this->Target->ClearSourcesCache();
+ }
+ // Read skip files from makefile sources
+ if (this->MocEnabled || this->UicEnabled) {
+ const std::vector<cmSourceFile*>& allSources = makefile->GetSourceFiles();
+ for (cmSourceFile* sf : allSources) {
+ // sf->GetExtension() is only valid after sf->GetFullPath() ...
+ std::string const& fPath = sf->GetFullPath();
+ cmSystemTools::FileFormat const fileType =
+ cmSystemTools::GetFileFormat(sf->GetExtension().c_str());
+ if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) &&
+ !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
+ continue;
+ }
+ const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN");
+ const bool mocSkip =
+ this->MocEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC"));
+ const bool uicSkip =
+ this->UicEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC"));
+ if (mocSkip || uicSkip) {
+ std::string const absFile = cmSystemTools::GetRealPath(fPath);
+ if (mocSkip) {
+ this->MocSkip.insert(absFile);
+ }
+ if (uicSkip) {
+ this->UicSkip.insert(absFile);
+ }
+ }
+ }
}
// Process GENERATED sources and headers
@@ -832,7 +508,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
bool policyAccept = false;
bool policyWarn = false;
cmPolicies::PolicyStatus const CMP0071_status =
- target->Makefile->GetPolicyStatus(cmPolicies::CMP0071);
+ makefile->GetPolicyStatus(cmPolicies::CMP0071);
switch (CMP0071_status) {
case cmPolicies::WARN:
policyWarn = true;
@@ -851,11 +527,11 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
if (policyAccept) {
// Accept GENERATED sources
for (std::string const& absFile : generatedHeaders) {
- digest.Headers.push_back(absFile);
+ this->Headers.push_back(absFile);
autogenDependFiles.insert(absFile);
}
for (std::string const& absFile : generatedSources) {
- digest.Sources.push_back(absFile);
+ this->Sources.push_back(absFile);
autogenDependFiles.insert(absFile);
}
} else {
@@ -865,13 +541,13 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
msg += "\n";
std::string tools;
std::string property;
- if (digest.MocEnabled && digest.UicEnabled) {
+ if (this->MocEnabled && this->UicEnabled) {
tools = "AUTOMOC and AUTOUIC";
property = "SKIP_AUTOGEN";
- } else if (digest.MocEnabled) {
+ } else if (this->MocEnabled) {
tools = "AUTOMOC";
property = "SKIP_AUTOMOC";
- } else if (digest.UicEnabled) {
+ } else if (this->UicEnabled) {
tools = "AUTOUIC";
property = "SKIP_AUTOUIC";
}
@@ -896,57 +572,74 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
makefile->IssueMessage(cmake::AUTHOR_WARNING, msg);
}
}
+ // Clear lists
+ generatedSources.clear();
+ generatedHeaders.clear();
}
// Sort headers and sources
- std::sort(digest.Headers.begin(), digest.Headers.end());
- std::sort(digest.Sources.begin(), digest.Sources.end());
+ if (this->MocEnabled || this->UicEnabled) {
+ std::sort(this->Headers.begin(), this->Headers.end());
+ std::sort(this->Sources.begin(), this->Sources.end());
+ }
// Process qrc files
- if (!digest.Qrcs.empty()) {
- const bool QtV5 = (digest.QtVersionMajor == "5");
- std::string const rcc = RccGetExecutable(target, digest.QtVersionMajor);
+ if (!this->Qrcs.empty()) {
+ const bool QtV5 = (this->QtVersionMajor == "5");
// Target rcc options
std::vector<std::string> optionsTarget;
cmSystemTools::ExpandListArgument(
- GetSafeProperty(target, "AUTORCC_OPTIONS"), optionsTarget);
+ GetSafeProperty(this->Target, "AUTORCC_OPTIONS"), optionsTarget);
// Check if file name is unique
- for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
- qrcDigest.Unique = true;
- for (cmQtAutoGenDigestQrc const& qrcDig2 : digest.Qrcs) {
- if ((&qrcDigest != &qrcDig2) &&
- (qrcDigest.QrcName == qrcDig2.QrcName)) {
- qrcDigest.Unique = false;
+ for (Qrc& qrc : this->Qrcs) {
+ qrc.Unique = true;
+ for (Qrc const& qrc2 : this->Qrcs) {
+ if ((&qrc != &qrc2) && (qrc.QrcName == qrc2.QrcName)) {
+ qrc.Unique = false;
break;
}
}
}
- // Path checksum
+ // Path checksum and file names
{
cmFilePathChecksum const fpathCheckSum(makefile);
- for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
- qrcDigest.PathChecksum = fpathCheckSum.getPart(qrcDigest.QrcFile);
+ for (Qrc& qrc : this->Qrcs) {
+ qrc.PathChecksum = fpathCheckSum.getPart(qrc.QrcFile);
// RCC output file name
- std::string rccFile = autogenBuildDir + "/";
- rccFile += qrcDigest.PathChecksum;
- rccFile += "/qrc_";
- rccFile += qrcDigest.QrcName;
- rccFile += ".cpp";
- qrcDigest.RccFile = std::move(rccFile);
+ {
+ std::string rccFile = this->DirBuild + "/";
+ rccFile += qrc.PathChecksum;
+ rccFile += "/qrc_";
+ rccFile += qrc.QrcName;
+ rccFile += ".cpp";
+ qrc.RccFile = std::move(rccFile);
+ }
+ {
+ std::string base = this->DirInfo;
+ base += "/RCC";
+ base += qrc.QrcName;
+ if (!qrc.Unique) {
+ base += qrc.PathChecksum;
+ }
+ qrc.InfoFile = base;
+ qrc.InfoFile += "Info.cmake";
+ qrc.SettingsFile = base;
+ qrc.SettingsFile += "Settings.cmake";
+ }
}
}
// RCC options
- for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
+ for (Qrc& qrc : this->Qrcs) {
// Target options
std::vector<std::string> opts = optionsTarget;
// Merge computed "-name XYZ" option
{
- std::string name = qrcDigest.QrcName;
+ std::string name = qrc.QrcName;
// Replace '-' with '_'. The former is not valid for symbol names.
std::replace(name.begin(), name.end(), '-', '_');
- if (!qrcDigest.Unique) {
+ if (!qrc.Unique) {
name += "_";
- name += qrcDigest.PathChecksum;
+ name += qrc.PathChecksum;
}
std::vector<std::string> nameOpts;
nameOpts.emplace_back("-name");
@@ -954,254 +647,324 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
cmQtAutoGen::RccMergeOptions(opts, nameOpts, QtV5);
}
// Merge file option
- cmQtAutoGen::RccMergeOptions(opts, qrcDigest.Options, QtV5);
- qrcDigest.Options = std::move(opts);
+ cmQtAutoGen::RccMergeOptions(opts, qrc.Options, QtV5);
+ qrc.Options = std::move(opts);
}
- for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
+ for (Qrc& qrc : this->Qrcs) {
// Register file at target
+ std::vector<std::string> const ccOutput =
+ this->AddGeneratedSource(qrc.RccFile, cmQtAutoGen::RCC);
+
+ cmCustomCommandLines commandLines;
{
- auto files = AddGeneratedSource(target, qrcDigest.RccFile, multiConfig,
- configsList, cmQtAutoGen::RCC);
- for (std::string& file : files) {
- autogenProvides.push_back(std::move(file));
- }
+ cmCustomCommandLine currentLine;
+ currentLine.push_back(cmSystemTools::GetCMakeCommand());
+ currentLine.push_back("-E");
+ currentLine.push_back("cmake_autorcc");
+ currentLine.push_back(qrc.InfoFile);
+ currentLine.push_back("$<CONFIGURATION>");
+ commandLines.push_back(std::move(currentLine));
}
- // Dependencies
- if (qrcDigest.Generated) {
- // Add the GENERATED .qrc file to the dependencies
- autogenDependFiles.insert(qrcDigest.QrcFile);
+ std::string ccComment = "Automatic RCC for ";
+ ccComment += FileProjectRelativePath(makefile, qrc.QrcFile);
+
+ if (qrc.Generated) {
+ // Create custom rcc target
+ std::string ccName;
+ {
+ ccName = this->Target->GetName();
+ ccName += "_arcc_";
+ ccName += qrc.QrcName;
+ if (!qrc.Unique) {
+ ccName += "_";
+ ccName += qrc.PathChecksum;
+ }
+ std::vector<std::string> ccDepends;
+ // Add the .qrc file to the custom target dependencies
+ ccDepends.push_back(qrc.QrcFile);
+
+ cmTarget* autoRccTarget = makefile->AddUtilityCommand(
+ ccName, true, this->DirWork.c_str(), ccOutput, ccDepends,
+ commandLines, false, ccComment.c_str());
+ // Create autogen generator target
+ localGen->AddGeneratorTarget(
+ new cmGeneratorTarget(autoRccTarget, localGen));
+
+ // Set FOLDER property in autogen target
+ if (!this->AutogenFolder.empty()) {
+ autoRccTarget->SetProperty("FOLDER", this->AutogenFolder.c_str());
+ }
+ }
+ // Add autogen target to the origin target dependencies
+ this->Target->Target->AddUtility(ccName, makefile);
} else {
- // Add the resource files to the dependencies
+ // Create custom rcc command
{
- std::string error;
- if (cmQtAutoGen::RccListInputs(digest.QtVersionMajor, rcc,
- qrcDigest.QrcFile,
- qrcDigest.Resources, &error)) {
- for (std::string const& fileName : qrcDigest.Resources) {
- autogenDependFiles.insert(fileName);
+ std::vector<std::string> ccByproducts;
+ std::vector<std::string> ccDepends;
+ // Add the .qrc file to the custom command dependencies
+ ccDepends.push_back(qrc.QrcFile);
+
+ // Add the resource files to the dependencies
+ {
+ std::string error;
+ if (cmQtAutoGen::RccListInputs(this->RccExecutable,
+ this->RccListOptions, qrc.QrcFile,
+ qrc.Resources, &error)) {
+ for (std::string const& fileName : qrc.Resources) {
+ // Add resource file to the custom command dependencies
+ ccDepends.push_back(fileName);
+ }
+ } else {
+ cmSystemTools::Error(error.c_str());
}
- } else {
- cmSystemTools::Error(error.c_str());
}
+ makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends,
+ /*main_dependency*/ std::string(),
+ commandLines, ccComment.c_str(),
+ this->DirWork.c_str());
}
- // Run cmake again when .qrc file changes
- makefile->AddCMakeDependFile(qrcDigest.QrcFile);
+ // Reconfigure when .qrc file changes
+ makefile->AddCMakeDependFile(qrc.QrcFile);
}
}
}
- // Add user defined autogen target dependencies
- {
- std::string const deps = GetSafeProperty(target, "AUTOGEN_TARGET_DEPENDS");
- if (!deps.empty()) {
- std::vector<std::string> extraDeps;
- cmSystemTools::ExpandListArgument(deps, extraDeps);
- for (std::string const& depName : extraDeps) {
- // Allow target and file dependencies
- auto* depTarget = makefile->FindTargetToUse(depName);
- if (depTarget != nullptr) {
- autogenDependTargets.insert(depTarget);
- } else {
- autogenDependFiles.insert(depName);
+ // Create _autogen target
+ if (this->MocEnabled || this->UicEnabled) {
+ // Add user defined autogen target dependencies
+ {
+ std::string const deps =
+ GetSafeProperty(this->Target, "AUTOGEN_TARGET_DEPENDS");
+ if (!deps.empty()) {
+ std::vector<std::string> extraDeps;
+ cmSystemTools::ExpandListArgument(deps, extraDeps);
+ for (std::string const& depName : extraDeps) {
+ // Allow target and file dependencies
+ auto* depTarget = makefile->FindTargetToUse(depName);
+ if (depTarget != nullptr) {
+ autogenDependTargets.insert(depTarget);
+ } else {
+ autogenDependFiles.insert(depName);
+ }
}
}
}
- }
- // Use PRE_BUILD on demand
- bool usePRE_BUILD = false;
- if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
- // Under VS use a PRE_BUILD event instead of a separate target to
- // reduce the number of targets loaded into the IDE.
- // This also works around a VS 11 bug that may skip updating the target:
- // https://connect.microsoft.com/VisualStudio/feedback/details/769495
- usePRE_BUILD = true;
- }
- // Disable PRE_BUILD in some cases
- if (usePRE_BUILD) {
- // Cannot use PRE_BUILD with file depends
- if (!autogenDependFiles.empty()) {
- usePRE_BUILD = false;
+ // Compose target comment
+ std::string autogenComment;
+ {
+ std::string tools;
+ if (this->MocEnabled) {
+ tools += "MOC";
+ }
+ if (this->UicEnabled) {
+ if (!tools.empty()) {
+ tools += " and ";
+ }
+ tools += "UIC";
+ }
+ autogenComment = "Automatic ";
+ autogenComment += tools;
+ autogenComment += " for target ";
+ autogenComment += this->Target->GetName();
}
- }
- // Create the autogen target/command
- if (usePRE_BUILD) {
- // Add additional autogen target dependencies to origin target
- for (cmTarget* depTarget : autogenDependTargets) {
- target->Target->AddUtility(depTarget->GetName(), makefile);
+
+ // Compose command lines
+ cmCustomCommandLines commandLines;
+ {
+ cmCustomCommandLine currentLine;
+ currentLine.push_back(cmSystemTools::GetCMakeCommand());
+ currentLine.push_back("-E");
+ currentLine.push_back("cmake_autogen");
+ currentLine.push_back(this->AutogenInfoFile);
+ currentLine.push_back("$<CONFIGURATION>");
+ commandLines.push_back(std::move(currentLine));
}
- // Add the pre-build command directly to bypass the OBJECT_LIBRARY
- // rejection in cmMakefile::AddCustomCommandToTarget because we know
- // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.
- //
- // PRE_BUILD does not support file dependencies!
- const std::vector<std::string> no_output;
- const std::vector<std::string> no_deps;
- cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps,
- commandLines, autogenComment.c_str(),
- workingDirectory.c_str());
- cc.SetEscapeOldStyle(false);
- cc.SetEscapeAllowMakeVars(true);
- target->Target->AddPreBuildCommand(cc);
- } else {
+ // Use PRE_BUILD on demand
+ bool usePRE_BUILD = false;
+ if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
+ // Under VS use a PRE_BUILD event instead of a separate target to
+ // reduce the number of targets loaded into the IDE.
+ // This also works around a VS 11 bug that may skip updating the target:
+ // https://connect.microsoft.com/VisualStudio/feedback/details/769495
+ usePRE_BUILD = true;
+ }
+ // Disable PRE_BUILD in some cases
+ if (usePRE_BUILD) {
+ // Cannot use PRE_BUILD with file depends
+ if (!autogenDependFiles.empty()) {
+ usePRE_BUILD = false;
+ }
+ }
+ // Create the autogen target/command
+ if (usePRE_BUILD) {
+ // Add additional autogen target dependencies to origin target
+ for (cmTarget* depTarget : autogenDependTargets) {
+ this->Target->Target->AddUtility(depTarget->GetName(), makefile);
+ }
- // Convert file dependencies std::set to std::vector
- std::vector<std::string> autogenDepends(autogenDependFiles.begin(),
- autogenDependFiles.end());
+ // Add the pre-build command directly to bypass the OBJECT_LIBRARY
+ // rejection in cmMakefile::AddCustomCommandToTarget because we know
+ // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.
+ //
+ // PRE_BUILD does not support file dependencies!
+ const std::vector<std::string> no_output;
+ const std::vector<std::string> no_deps;
+ cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps,
+ commandLines, autogenComment.c_str(),
+ this->DirWork.c_str());
+ cc.SetEscapeOldStyle(false);
+ cc.SetEscapeAllowMakeVars(true);
+ this->Target->Target->AddPreBuildCommand(cc);
+ } else {
- // Add link library target dependencies to the autogen target dependencies
- for (std::string const& config : configsList) {
- cmLinkImplementationLibraries const* libs =
- target->GetLinkImplementationLibraries(config);
- if (libs != nullptr) {
- for (cmLinkItem const& item : libs->Libraries) {
- cmGeneratorTarget const* libTarget = item.Target;
- if ((libTarget != nullptr) &&
- !StaticLibraryCycle(target, libTarget, config)) {
- std::string util;
- if (configsList.size() > 1) {
- util += "$<$<CONFIG:";
- util += config;
- util += ">:";
- }
- util += libTarget->GetName();
- if (configsList.size() > 1) {
- util += ">";
+ // Convert file dependencies std::set to std::vector
+ std::vector<std::string> autogenDepends(autogenDependFiles.begin(),
+ autogenDependFiles.end());
+
+ // Add link library target dependencies to the autogen target
+ // dependencies
+ for (std::string const& config : this->ConfigsList) {
+ cmLinkImplementationLibraries const* libs =
+ this->Target->GetLinkImplementationLibraries(config);
+ if (libs != nullptr) {
+ for (cmLinkItem const& item : libs->Libraries) {
+ cmGeneratorTarget const* libTarget = item.Target;
+ if ((libTarget != nullptr) &&
+ !StaticLibraryCycle(this->Target, libTarget, config)) {
+ std::string util;
+ if (this->ConfigsList.size() > 1) {
+ util += "$<$<CONFIG:";
+ util += config;
+ util += ">:";
+ }
+ util += libTarget->GetName();
+ if (this->ConfigsList.size() > 1) {
+ util += ">";
+ }
+ autogenDepends.push_back(util);
}
- autogenDepends.push_back(util);
}
}
}
- }
- // Create autogen target
- cmTarget* autogenTarget = makefile->AddUtilityCommand(
- autogenTargetName, true, workingDirectory.c_str(),
- /*byproducts=*/autogenProvides, autogenDepends, commandLines, false,
- autogenComment.c_str());
- // Create autogen generator target
- localGen->AddGeneratorTarget(
- new cmGeneratorTarget(autogenTarget, localGen));
-
- // Forward origin utilities to autogen target
- for (std::string const& depName : target->Target->GetUtilities()) {
- autogenTarget->AddUtility(depName, makefile);
- }
- // Add additional autogen target dependencies to autogen target
- for (cmTarget* depTarget : autogenDependTargets) {
- autogenTarget->AddUtility(depTarget->GetName(), makefile);
- }
-
- // Set FOLDER property in autogen target
- {
- const char* autogenFolder =
- makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");
- if (autogenFolder == nullptr) {
- autogenFolder =
- makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");
+ // Create autogen target
+ cmTarget* autogenTarget = makefile->AddUtilityCommand(
+ this->AutogenTargetName, true, this->DirWork.c_str(),
+ /*byproducts=*/autogenProvides, autogenDepends, commandLines, false,
+ autogenComment.c_str());
+ // Create autogen generator target
+ localGen->AddGeneratorTarget(
+ new cmGeneratorTarget(autogenTarget, localGen));
+
+ // Forward origin utilities to autogen target
+ for (std::string const& depName : this->Target->Target->GetUtilities()) {
+ autogenTarget->AddUtility(depName, makefile);
}
- // Inherit FOLDER property from target (#13688)
- if (autogenFolder == nullptr) {
- autogenFolder = SafeString(target->Target->GetProperty("FOLDER"));
+ // Add additional autogen target dependencies to autogen target
+ for (cmTarget* depTarget : autogenDependTargets) {
+ autogenTarget->AddUtility(depTarget->GetName(), makefile);
}
- if ((autogenFolder != nullptr) && (*autogenFolder != '\0')) {
- autogenTarget->SetProperty("FOLDER", autogenFolder);
+
+ // Set FOLDER property in autogen target
+ if (!this->AutogenFolder.empty()) {
+ autogenTarget->SetProperty("FOLDER", this->AutogenFolder.c_str());
}
- }
- // Add autogen target to the origin target dependencies
- target->Target->AddUtility(autogenTargetName, makefile);
+ // Add autogen target to the origin target dependencies
+ this->Target->Target->AddUtility(this->AutogenTargetName, makefile);
+ }
}
}
-void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
- cmQtAutoGenDigest const& digest)
+void cmQtAutoGeneratorInitializer::SetupCustomTargets()
{
- cmGeneratorTarget const* target = digest.Target;
- cmMakefile* makefile = target->Target->GetMakefile();
- cmQtAutoGen::MultiConfig const multiConfig =
- AutogenMultiConfig(target->GetGlobalGenerator());
+ cmMakefile* makefile = this->Target->Target->GetMakefile();
// forget the variables added here afterwards again:
cmMakefile::ScopePushPop varScope(makefile);
static_cast<void>(varScope);
- // Configurations
- std::string configDefault;
- std::vector<std::string> configsList;
+ // Configuration suffixes
std::map<std::string, std::string> configSuffixes;
- {
- configDefault = makefile->GetConfigurations(configsList);
- if (configsList.empty()) {
- configsList.push_back("");
- }
+ for (std::string const& cfg : this->ConfigsList) {
+ std::string& suffix = configSuffixes[cfg];
+ suffix = "_";
+ suffix += cfg;
}
- for (std::string const& cfg : configsList) {
- configSuffixes[cfg] = "_" + cfg;
- }
-
- // Configurations settings buffers
- cmQtAutoGenSetup setup;
// Basic setup
AddDefinitionEscaped(makefile, "_multi_config",
- cmQtAutoGen::MultiConfigName(multiConfig));
- AddDefinitionEscaped(makefile, "_build_dir",
- GetAutogenTargetBuildDir(target));
- AddDefinitionEscaped(makefile, "_sources", digest.Sources);
- AddDefinitionEscaped(makefile, "_headers", digest.Headers);
- AddDefinitionEscaped(makefile, "_qt_version_major", digest.QtVersionMajor);
- AddDefinitionEscaped(makefile, "_qt_version_minor", digest.QtVersionMinor);
- {
- if (digest.MocEnabled || digest.UicEnabled) {
- SetupAcquireSkipFiles(digest, setup);
- if (digest.MocEnabled) {
- SetupAutoTargetMoc(digest, configDefault, configsList, setup);
- }
- if (digest.UicEnabled) {
- SetupAutoTargetUic(digest, configDefault, configsList, setup);
- }
+ cmQtAutoGen::MultiConfigName(this->MultiConfig));
+ AddDefinitionEscaped(makefile, "_build_dir", this->DirBuild);
+
+ if (this->MocEnabled || this->UicEnabled) {
+ AddDefinitionEscaped(makefile, "_qt_version_major", this->QtVersionMajor);
+ AddDefinitionEscaped(makefile, "_settings_file",
+ this->AutogenSettingsFile);
+ AddDefinitionEscaped(makefile, "_sources", this->Sources);
+ AddDefinitionEscaped(makefile, "_headers", this->Headers);
+
+ if (this->MocEnabled) {
+ this->SetupCustomTargetsMoc();
}
- if (digest.RccEnabled) {
- SetupAutoTargetRcc(digest);
+ if (this->UicEnabled) {
+ this->SetupCustomTargetsUic();
}
}
+ if (this->RccEnabled) {
+ AddDefinitionEscaped(makefile, "_qt_rcc_executable", this->RccExecutable);
+ AddDefinitionEscaped(makefile, "_qt_rcc_list_options",
+ this->RccListOptions);
+ }
- // Generate info file
- {
- std::string const infoDir = GetAutogenTargetFilesDir(target);
- if (!cmSystemTools::MakeDirectory(infoDir)) {
- std::string emsg = ("Could not create directory: ");
- emsg += cmQtAutoGen::Quoted(infoDir);
- cmSystemTools::Error(emsg.c_str());
- }
- std::string const infoFile = infoDir + "/AutogenInfo.cmake";
- {
- std::string infoFileIn = cmSystemTools::GetCMakeRoot();
- infoFileIn += "/Modules/AutogenInfo.cmake.in";
- makefile->ConfigureFile(infoFileIn.c_str(), infoFile.c_str(), false,
- true, false);
- }
-
- // Append custom definitions to info file
- // --------------------------------------
+ // Create info directory on demand
+ if (!cmSystemTools::MakeDirectory(this->DirInfo)) {
+ std::string emsg = ("Could not create directory: ");
+ emsg += cmQtAutoGen::Quoted(this->DirInfo);
+ cmSystemTools::Error(emsg.c_str());
+ }
- // Ensure we have write permission in case .in was read-only.
+ auto ReOpenInfoFile = [](cmsys::ofstream& ofs,
+ std::string const& fileName) -> bool {
+ // Ensure we have write permission
mode_t perm = 0;
#if defined(_WIN32) && !defined(__CYGWIN__)
mode_t mode_write = S_IWRITE;
#else
mode_t mode_write = S_IWUSR;
#endif
- cmSystemTools::GetPermissions(infoFile, perm);
+ cmSystemTools::GetPermissions(fileName, perm);
if (!(perm & mode_write)) {
- cmSystemTools::SetPermissions(infoFile, perm | mode_write);
+ cmSystemTools::SetPermissions(fileName, perm | mode_write);
}
- // Open and write file
- cmsys::ofstream ofs(infoFile.c_str(), std::ios::app);
- if (ofs) {
+ ofs.open(fileName.c_str(), std::ios::app);
+ if (!ofs) {
+ // File open error
+ std::string error = "Internal CMake error when trying to open file: ";
+ error += cmQtAutoGen::Quoted(fileName);
+ error += " for writing.";
+ cmSystemTools::Error(error.c_str());
+ }
+ return static_cast<bool>(ofs);
+ };
+
+ // Generate autogen target info file
+ if (this->MocEnabled || this->UicEnabled) {
+ {
+ std::string infoFileIn = cmSystemTools::GetCMakeRoot();
+ infoFileIn += "/Modules/AutogenInfo.cmake.in";
+ makefile->ConfigureFile(
+ infoFileIn.c_str(), this->AutogenInfoFile.c_str(), false, true, false);
+ }
+
+ // Append custom definitions to info file
+ // --------------------------------------
+ cmsys::ofstream ofs;
+ if (ReOpenInfoFile(ofs, this->AutogenInfoFile)) {
auto OfsWriteMap = [&ofs](
const char* key, std::map<std::string, std::string> const& map) {
for (auto const& item : map) {
@@ -1211,15 +974,372 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
};
ofs << "# Configurations options\n";
OfsWriteMap("AM_CONFIG_SUFFIX", configSuffixes);
- OfsWriteMap("AM_MOC_DEFINITIONS", setup.ConfigMocDefines);
- OfsWriteMap("AM_MOC_INCLUDES", setup.ConfigMocIncludes);
- OfsWriteMap("AM_UIC_TARGET_OPTIONS", setup.ConfigUicOptions);
+ OfsWriteMap("AM_MOC_DEFINITIONS", this->ConfigMocDefines);
+ OfsWriteMap("AM_MOC_INCLUDES", this->ConfigMocIncludes);
+ OfsWriteMap("AM_UIC_TARGET_OPTIONS", this->ConfigUicOptions);
+ // Settings files (only require for multi configuration generators)
+ if (this->MultiConfig != cmQtAutoGen::SINGLE) {
+ std::map<std::string, std::string> settingsFiles;
+ for (std::string const& cfg : this->ConfigsList) {
+ settingsFiles[cfg] = cmQtAutoGen::AppendFilenameSuffix(
+ this->AutogenSettingsFile, "_" + cfg);
+ }
+ OfsWriteMap("AM_SETTINGS_FILE", settingsFiles);
+ }
+ }
+ }
+
+ // Generate auto RCC info files
+ if (this->RccEnabled) {
+ std::string infoFileIn = cmSystemTools::GetCMakeRoot();
+ infoFileIn += "/Modules/AutoRccInfo.cmake.in";
+ for (Qrc const& qrc : this->Qrcs) {
+ // Configure info file
+ makefile->ConfigureFile(infoFileIn.c_str(), qrc.InfoFile.c_str(), false,
+ true, false);
+
+ // Append custom definitions to info file
+ // --------------------------------------
+ cmsys::ofstream ofs;
+ if (ReOpenInfoFile(ofs, qrc.InfoFile)) {
+ {
+ ofs << "# Job\n";
+ auto OfsWrite = [&ofs](const char* key, std::string const& value) {
+ ofs << "set(" << key << " "
+ << cmOutputConverter::EscapeForCMake(value) << ")\n";
+
+ };
+ OfsWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile);
+ OfsWrite("ARCC_SOURCE", qrc.QrcFile);
+ OfsWrite("ARCC_OUTPUT", qrc.RccFile);
+ OfsWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";"));
+ OfsWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";"));
+ }
+ {
+ ofs << "# Configurations options\n";
+ auto OfsWriteMap = [&ofs](
+ const char* key, std::map<std::string, std::string> const& map) {
+ for (auto const& item : map) {
+ ofs << "set(" << key << "_" << item.first << " "
+ << cmOutputConverter::EscapeForCMake(item.second) << ")\n";
+ }
+ };
+ OfsWriteMap("ARCC_CONFIG_SUFFIX", configSuffixes);
+
+ // Settings files (only require for multi configuration generators)
+ if (this->MultiConfig != cmQtAutoGen::SINGLE) {
+ std::map<std::string, std::string> settingsFiles;
+ for (std::string const& cfg : this->ConfigsList) {
+ settingsFiles[cfg] =
+ cmQtAutoGen::AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg);
+ }
+ OfsWriteMap("ARCC_SETTINGS_FILE", settingsFiles);
+ }
+ }
+ } else {
+ break;
+ }
+ }
+ }
+}
+
+void cmQtAutoGeneratorInitializer::SetupCustomTargetsMoc()
+{
+ cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+ cmMakefile* makefile = this->Target->Target->GetMakefile();
+
+ AddDefinitionEscaped(makefile, "_moc_skip", this->MocSkip);
+ AddDefinitionEscaped(makefile, "_moc_options",
+ GetSafeProperty(this->Target, "AUTOMOC_MOC_OPTIONS"));
+ AddDefinitionEscaped(makefile, "_moc_relaxed_mode",
+ makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE"
+ : "FALSE");
+ AddDefinitionEscaped(makefile, "_moc_macro_names",
+ GetSafeProperty(this->Target, "AUTOMOC_MACRO_NAMES"));
+ AddDefinitionEscaped(
+ makefile, "_moc_depend_filters",
+ GetSafeProperty(this->Target, "AUTOMOC_DEPEND_FILTERS"));
+
+ // Compiler predefines
+ if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&
+ this->QtVersionGreaterOrEqual(5, 8)) {
+ AddDefinitionEscaped(
+ makefile, "_moc_predefs_cmd",
+ makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"));
+ }
+ // Moc includes and compile definitions
+ {
+ auto GetIncludeDirs = [this,
+ localGen](std::string const& cfg) -> std::string {
+ // Get the include dirs for this target, without stripping the implicit
+ // include dirs off, see
+ // https://gitlab.kitware.com/cmake/cmake/issues/13667
+ std::vector<std::string> includeDirs;
+ localGen->GetIncludeDirectories(includeDirs, this->Target, "CXX", cfg,
+ false);
+ return cmJoin(includeDirs, ";");
+ };
+ auto GetCompileDefinitions =
+ [this, localGen](std::string const& cfg) -> std::string {
+ std::set<std::string> defines;
+ localGen->AddCompileDefinitions(defines, this->Target, cfg, "CXX");
+ return cmJoin(defines, ";");
+ };
+
+ // Default configuration settings
+ std::string const includeDirs = GetIncludeDirs(this->ConfigDefault);
+ std::string const compileDefs = GetCompileDefinitions(this->ConfigDefault);
+ // Other configuration settings
+ for (std::string const& cfg : this->ConfigsList) {
+ {
+ std::string const configIncludeDirs = GetIncludeDirs(cfg);
+ if (configIncludeDirs != includeDirs) {
+ this->ConfigMocIncludes[cfg] = configIncludeDirs;
+ }
+ }
+ {
+ std::string const configCompileDefs = GetCompileDefinitions(cfg);
+ if (configCompileDefs != compileDefs) {
+ this->ConfigMocDefines[cfg] = configCompileDefs;
+ }
+ }
+ }
+ AddDefinitionEscaped(makefile, "_moc_include_dirs", includeDirs);
+ AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs);
+ }
+
+ // Moc executable
+ {
+ std::string mocExec;
+ std::string err;
+
+ if (this->QtVersionMajor == "5") {
+ cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::moc");
+ if (tgt != nullptr) {
+ mocExec = SafeString(tgt->ImportedGetLocation(""));
+ } else {
+ err = "AUTOMOC: Qt5::moc target not found";
+ }
+ } else if (this->QtVersionMajor == "4") {
+ cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::moc");
+ if (tgt != nullptr) {
+ mocExec = SafeString(tgt->ImportedGetLocation(""));
+ } else {
+ err = "AUTOMOC: Qt4::moc target not found";
+ }
} else {
- // File open error
- std::string error = "Internal CMake error when trying to open file: ";
- error += cmQtAutoGen::Quoted(infoFile);
- error += " for writing.";
- cmSystemTools::Error(error.c_str());
+ err = "The AUTOMOC feature supports only Qt 4 and Qt 5";
+ }
+
+ if (err.empty()) {
+ AddDefinitionEscaped(makefile, "_qt_moc_executable", mocExec);
+ } else {
+ err += " (";
+ err += this->Target->GetName();
+ err += ")";
+ cmSystemTools::Error(err.c_str());
}
}
}
+
+void cmQtAutoGeneratorInitializer::SetupCustomTargetsUic()
+{
+ cmMakefile* makefile = this->Target->Target->GetMakefile();
+
+ // Uic search paths
+ {
+ std::vector<std::string> uicSearchPaths;
+ {
+ std::string const usp =
+ GetSafeProperty(this->Target, "AUTOUIC_SEARCH_PATHS");
+ if (!usp.empty()) {
+ cmSystemTools::ExpandListArgument(usp, uicSearchPaths);
+ std::string const srcDir = makefile->GetCurrentSourceDirectory();
+ for (std::string& path : uicSearchPaths) {
+ path = cmSystemTools::CollapseFullPath(path, srcDir);
+ }
+ }
+ }
+ AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths);
+ }
+ // Uic target options
+ {
+ auto UicGetOpts = [this](std::string const& cfg) -> std::string {
+ std::vector<std::string> opts;
+ this->Target->GetAutoUicOptions(opts, cfg);
+ return cmJoin(opts, ";");
+ };
+
+ // Default settings
+ std::string const uicOpts = UicGetOpts(this->ConfigDefault);
+ AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts);
+
+ // Configuration specific settings
+ for (std::string const& cfg : this->ConfigsList) {
+ std::string const configUicOpts = UicGetOpts(cfg);
+ if (configUicOpts != uicOpts) {
+ this->ConfigUicOptions[cfg] = configUicOpts;
+ }
+ }
+ }
+ // .ui files skip and options
+ {
+ std::vector<std::string> uiFileFiles;
+ std::vector<std::vector<std::string>> uiFileOptions;
+ {
+ std::string const uiExt = "ui";
+ for (cmSourceFile* sf : makefile->GetSourceFiles()) {
+ // sf->GetExtension() is only valid after sf->GetFullPath() ...
+ std::string const& fPath = sf->GetFullPath();
+ if (sf->GetExtension() == uiExt) {
+ std::string const absFile = cmSystemTools::GetRealPath(fPath);
+ // Check if the .ui file should be skipped
+ if (sf->GetPropertyAsBool("SKIP_AUTOUIC") ||
+ sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
+ this->UicSkip.insert(absFile);
+ }
+ // Check if the .ui file has uic options
+ std::string const uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS");
+ if (!uicOpts.empty()) {
+ // Check if file isn't skipped
+ if (this->UicSkip.count(absFile) == 0) {
+ uiFileFiles.push_back(absFile);
+ std::vector<std::string> optsVec;
+ cmSystemTools::ExpandListArgument(uicOpts, optsVec);
+ uiFileOptions.push_back(std::move(optsVec));
+ }
+ }
+ }
+ }
+ }
+ AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles);
+ AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions);
+ }
+
+ AddDefinitionEscaped(makefile, "_uic_skip", this->UicSkip);
+
+ // Uic executable
+ {
+ std::string err;
+ std::string uicExec;
+
+ cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+ if (this->QtVersionMajor == "5") {
+ cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::uic");
+ if (tgt != nullptr) {
+ uicExec = SafeString(tgt->ImportedGetLocation(""));
+ } else {
+ // Project does not use Qt5Widgets, but has AUTOUIC ON anyway
+ }
+ } else if (this->QtVersionMajor == "4") {
+ cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::uic");
+ if (tgt != nullptr) {
+ uicExec = SafeString(tgt->ImportedGetLocation(""));
+ } else {
+ err = "AUTOUIC: Qt4::uic target not found";
+ }
+ } else {
+ err = "The AUTOUIC feature supports only Qt 4 and Qt 5";
+ }
+
+ if (err.empty()) {
+ AddDefinitionEscaped(makefile, "_qt_uic_executable", uicExec);
+ } else {
+ err += " (";
+ err += this->Target->GetName();
+ err += ")";
+ cmSystemTools::Error(err.c_str());
+ }
+ }
+}
+
+std::vector<std::string> cmQtAutoGeneratorInitializer::AddGeneratedSource(
+ std::string const& filename, cmQtAutoGen::Generator genType)
+{
+ std::vector<std::string> genFiles;
+ // Register source file in makefile and source group
+ if (this->MultiConfig != cmQtAutoGen::FULL) {
+ genFiles.push_back(filename);
+ } else {
+ for (std::string const& cfg : this->ConfigsList) {
+ genFiles.push_back(
+ cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg));
+ }
+ }
+ {
+ cmMakefile* makefile = this->Target->Target->GetMakefile();
+ for (std::string const& genFile : genFiles) {
+ {
+ cmSourceFile* gFile = makefile->GetOrCreateSource(genFile, true);
+ gFile->SetProperty("GENERATED", "1");
+ gFile->SetProperty("SKIP_AUTOGEN", "On");
+ }
+ AddToSourceGroup(makefile, genFile, genType);
+ }
+ }
+
+ // Add source file to target
+ if (this->MultiConfig != cmQtAutoGen::FULL) {
+ this->Target->AddSource(filename);
+ } else {
+ for (std::string const& cfg : this->ConfigsList) {
+ std::string src = "$<$<CONFIG:";
+ src += cfg;
+ src += ">:";
+ src += cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg);
+ src += ">";
+ this->Target->AddSource(src);
+ }
+ }
+
+ return genFiles;
+}
+
+std::string cmQtAutoGeneratorInitializer::GetQtMajorVersion(
+ cmGeneratorTarget const* target)
+{
+ cmMakefile* makefile = target->Target->GetMakefile();
+ std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
+ if (qtMajor.empty()) {
+ qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
+ }
+ const char* targetQtVersion =
+ target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "");
+ if (targetQtVersion != nullptr) {
+ qtMajor = targetQtVersion;
+ }
+ return qtMajor;
+}
+
+std::string cmQtAutoGeneratorInitializer::GetQtMinorVersion(
+ cmGeneratorTarget const* target, std::string const& qtVersionMajor)
+{
+ cmMakefile* makefile = target->Target->GetMakefile();
+ std::string qtMinor;
+ if (qtVersionMajor == "5") {
+ qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR");
+ }
+ if (qtMinor.empty()) {
+ qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR");
+ }
+
+ const char* targetQtVersion =
+ target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", "");
+ if (targetQtVersion != nullptr) {
+ qtMinor = targetQtVersion;
+ }
+ return qtMinor;
+}
+
+bool cmQtAutoGeneratorInitializer::QtVersionGreaterOrEqual(
+ unsigned long requestMajor, unsigned long requestMinor) const
+{
+ unsigned long majorUL(0);
+ unsigned long minorUL(0);
+ if (cmSystemTools::StringToULong(this->QtVersionMajor.c_str(), &majorUL) &&
+ cmSystemTools::StringToULong(this->QtVersionMinor.c_str(), &minorUL)) {
+ return (majorUL > requestMajor) ||
+ (majorUL == requestMajor && minorUL >= requestMinor);
+ }
+ return false;
+}
diff --git a/Source/cmQtAutoGeneratorInitializer.h b/Source/cmQtAutoGeneratorInitializer.h
index b8a5ae4..e06e1c4 100644
--- a/Source/cmQtAutoGeneratorInitializer.h
+++ b/Source/cmQtAutoGeneratorInitializer.h
@@ -4,9 +4,12 @@
#define cmQtAutoGeneratorInitializer_h
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmQtAutoGenDigest.h"
+#include "cmQtAutoGen.h"
+#include <map>
+#include <set>
#include <string>
+#include <vector>
class cmGeneratorTarget;
@@ -17,8 +20,78 @@ public:
static std::string GetQtMinorVersion(cmGeneratorTarget const* target,
std::string const& qtVersionMajor);
- static void InitializeAutogenTarget(cmQtAutoGenDigest& digest);
- static void SetupAutoGenerateTarget(cmQtAutoGenDigest const& digest);
+ class Qrc
+ {
+ public:
+ Qrc()
+ : Generated(false)
+ , Unique(false)
+ {
+ }
+
+ public:
+ std::string QrcFile;
+ std::string QrcName;
+ std::string PathChecksum;
+ std::string InfoFile;
+ std::string SettingsFile;
+ std::string RccFile;
+ bool Generated;
+ bool Unique;
+ std::vector<std::string> Options;
+ std::vector<std::string> Resources;
+ };
+
+public:
+ cmQtAutoGeneratorInitializer(cmGeneratorTarget* target, bool mocEnabled,
+ bool uicEnabled, bool rccEnabled,
+ std::string const& qtVersionMajor);
+
+ void InitCustomTargets();
+ void SetupCustomTargets();
+
+private:
+ void SetupCustomTargetsMoc();
+ void SetupCustomTargetsUic();
+
+ std::vector<std::string> AddGeneratedSource(std::string const& filename,
+ cmQtAutoGen::Generator genType);
+
+ bool QtVersionGreaterOrEqual(unsigned long requestMajor,
+ unsigned long requestMinor) const;
+
+private:
+ cmGeneratorTarget* Target;
+ bool MocEnabled;
+ bool UicEnabled;
+ bool RccEnabled;
+ // Qt
+ std::string QtVersionMajor;
+ std::string QtVersionMinor;
+ std::string RccExecutable;
+ std::vector<std::string> RccListOptions;
+ // Configurations
+ std::string ConfigDefault;
+ std::vector<std::string> ConfigsList;
+ cmQtAutoGen::MultiConfig MultiConfig;
+ // Names
+ std::string AutogenTargetName;
+ std::string AutogenFolder;
+ std::string AutogenInfoFile;
+ std::string AutogenSettingsFile;
+ // Directories
+ std::string DirInfo;
+ std::string DirBuild;
+ std::string DirWork;
+ // Sources
+ std::vector<std::string> Headers;
+ std::vector<std::string> Sources;
+ std::set<std::string> MocSkip;
+ std::set<std::string> UicSkip;
+ std::map<std::string, std::string> ConfigMocIncludes;
+ std::map<std::string, std::string> ConfigMocDefines;
+ std::map<std::string, std::string> ConfigUicOptions;
+ std::vector<Qrc> Qrcs;
};
#endif
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGeneratorMocUic.cxx
index 28a8df1..0de02b5 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGeneratorMocUic.cxx
@@ -1,10 +1,8 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmQtAutoGen.h"
-#include "cmQtAutoGenerators.h"
+#include "cmQtAutoGeneratorMocUic.h"
-#include "cmsys/FStream.hxx"
-#include "cmsys/Terminal.h"
#include <algorithm>
#include <array>
#include <list>
@@ -15,12 +13,8 @@
#include "cmAlgorithms.h"
#include "cmCryptoHash.h"
-#include "cmFilePathChecksum.h"
-#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
-#include "cmStateDirectory.h"
-#include "cmStateSnapshot.h"
#include "cmSystemTools.h"
#include "cmake.h"
@@ -32,37 +26,9 @@
static const char* SettingsKeyMoc = "AM_MOC_SETTINGS_HASH";
static const char* SettingsKeyUic = "AM_UIC_SETTINGS_HASH";
-static const char* SettingsKeyRcc = "AM_RCC_SETTINGS_HASH";
// -- Static functions
-static std::string HeadLine(std::string const& title)
-{
- std::string head = title;
- head += '\n';
- head.append(head.size() - 1, '-');
- head += '\n';
- return head;
-}
-
-static std::string QuotedCommand(std::vector<std::string> const& command)
-{
- std::string res;
- for (std::string const& item : command) {
- if (!res.empty()) {
- res.push_back(' ');
- }
- std::string const cesc = cmQtAutoGen::Quoted(item);
- if (item.empty() || (cesc.size() > (item.size() + 2)) ||
- (cesc.find(' ') != std::string::npos)) {
- res += cesc;
- } else {
- res += item;
- }
- }
- return res;
-}
-
static std::string SubDirPrefix(std::string const& fileName)
{
std::string res(cmSystemTools::GetFilenamePath(fileName));
@@ -72,56 +38,6 @@ static std::string SubDirPrefix(std::string const& fileName)
return res;
}
-static bool ReadFile(std::string& content, std::string const& filename,
- std::string* error = nullptr)
-{
- bool success = false;
- if (cmSystemTools::FileExists(filename)) {
- std::size_t const length = cmSystemTools::FileLength(filename);
- cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
- if (ifs) {
- content.resize(length);
- ifs.read(&content.front(), content.size());
- if (ifs) {
- success = true;
- } else {
- content.clear();
- if (error != nullptr) {
- error->append("Reading from the file failed.");
- }
- }
- } else if (error != nullptr) {
- error->append("Opening the file for reading failed.");
- }
- } else if (error != nullptr) {
- error->append("The file does not exist.");
- }
- return success;
-}
-
-/**
- * @brief Tests if buildFile is older than sourceFile
- * @return True if buildFile is older than sourceFile.
- * False may indicate an error.
- */
-static bool FileIsOlderThan(std::string const& buildFile,
- std::string const& sourceFile,
- std::string* error = nullptr)
-{
- int result = 0;
- if (cmSystemTools::FileTimeCompare(buildFile, sourceFile, &result)) {
- return (result < 0);
- }
- if (error != nullptr) {
- error->append(
- "File modification time comparison failed for the files\n ");
- error->append(cmQtAutoGen::Quoted(buildFile));
- error->append("\nand\n ");
- error->append(cmQtAutoGen::Quoted(sourceFile));
- }
- return false;
-}
-
static bool ListContains(std::vector<std::string> const& list,
std::string const& entry)
{
@@ -130,25 +46,15 @@ static bool ListContains(std::vector<std::string> const& list,
// -- Class methods
-cmQtAutoGenerators::cmQtAutoGenerators()
+cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic()
: MultiConfig(cmQtAutoGen::WRAP)
, IncludeProjectDirsBefore(false)
- , Verbose(cmSystemTools::HasEnv("VERBOSE"))
- , ColorOutput(true)
+ , QtVersionMajor(4)
, MocSettingsChanged(false)
, MocPredefsChanged(false)
, MocRelaxedMode(false)
, UicSettingsChanged(false)
- , RccSettingsChanged(false)
{
- {
- std::string colorEnv;
- cmSystemTools::GetEnv("COLOR", colorEnv);
- if (!colorEnv.empty()) {
- this->ColorOutput = cmSystemTools::IsOn(colorEnv.c_str());
- }
- }
-
// Precompile regular expressions
this->MocRegExpInclude.compile(
"[\n][ \t]*#[ \t]*include[ \t]+"
@@ -157,39 +63,7 @@ cmQtAutoGenerators::cmQtAutoGenerators()
"[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
}
-bool cmQtAutoGenerators::Run(std::string const& targetDirectory,
- std::string const& config)
-{
- cmake cm(cmake::RoleScript);
- cm.SetHomeOutputDirectory(targetDirectory);
- cm.SetHomeDirectory(targetDirectory);
- cm.GetCurrentSnapshot().SetDefaultDefinitions();
- cmGlobalGenerator gg(&cm);
-
- cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
- snapshot.GetDirectory().SetCurrentBinary(targetDirectory);
- snapshot.GetDirectory().SetCurrentSource(targetDirectory);
-
- auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot);
- gg.SetCurrentMakefile(makefile.get());
-
- bool success = false;
- if (this->InitInfoFile(makefile.get(), targetDirectory, config)) {
- // Read latest settings
- this->SettingsFileRead(makefile.get());
- if (this->Process()) {
- // Write current settings
- if (this->SettingsFileWrite()) {
- success = true;
- }
- }
- }
- return success;
-}
-
-bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile,
- std::string const& targetDirectory,
- std::string const& config)
+bool cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile)
{
// -- Meta
this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions();
@@ -233,12 +107,12 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile,
}
return lists;
};
- auto InfoGetConfig = [makefile, &config](const char* key) -> std::string {
+ auto InfoGetConfig = [makefile, this](const char* key) -> std::string {
const char* valueConf = nullptr;
{
std::string keyConf = key;
keyConf += '_';
- keyConf += config;
+ keyConf += this->GetInfoConfig();
valueConf = makefile->GetDefinition(keyConf);
}
if (valueConf == nullptr) {
@@ -254,11 +128,8 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile,
};
// -- Read info file
- this->InfoFile = cmSystemTools::CollapseFullPath(targetDirectory);
- cmSystemTools::ConvertToUnixSlashes(this->InfoFile);
- this->InfoFile += "/AutogenInfo.cmake";
- if (!makefile->ReadListFile(this->InfoFile.c_str())) {
- this->LogFileError(cmQtAutoGen::GEN, this->InfoFile,
+ if (!makefile->ReadListFile(this->GetInfoFile().c_str())) {
+ this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(),
"File processing failed");
return false;
}
@@ -268,7 +139,14 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile,
this->ConfigSuffix = InfoGetConfig("AM_CONFIG_SUFFIX");
if (this->ConfigSuffix.empty()) {
this->ConfigSuffix = "_";
- this->ConfigSuffix += config;
+ this->ConfigSuffix += this->GetInfoConfig();
+ }
+
+ this->SettingsFile = InfoGetConfig("AM_SETTINGS_FILE");
+ if (this->SettingsFile.empty()) {
+ this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(),
+ "Settings file name missing");
+ return false;
}
// - Files and directories
@@ -280,25 +158,18 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile,
InfoGetBool("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE");
this->AutogenBuildDir = InfoGet("AM_BUILD_DIR");
if (this->AutogenBuildDir.empty()) {
- this->LogFileError(cmQtAutoGen::GEN, this->InfoFile,
+ this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(),
"Autogen build directory missing");
return false;
}
// - Qt environment
- this->QtMajorVersion = InfoGet("AM_QT_VERSION_MAJOR");
- this->QtMinorVersion = InfoGet("AM_QT_VERSION_MINOR");
+ if (!cmSystemTools::StringToULong(InfoGet("AM_QT_VERSION_MAJOR"),
+ &this->QtVersionMajor)) {
+ this->QtVersionMajor = 4;
+ }
this->MocExecutable = InfoGet("AM_QT_MOC_EXECUTABLE");
this->UicExecutable = InfoGet("AM_QT_UIC_EXECUTABLE");
- this->RccExecutable = InfoGet("AM_QT_RCC_EXECUTABLE");
-
- // Check Qt version
- if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) {
- this->LogFileError(cmQtAutoGen::GEN, this->InfoFile,
- "Unsupported Qt version: " +
- cmQtAutoGen::Quoted(this->QtMajorVersion));
- return false;
- }
// - Moc
if (this->MocEnabled()) {
@@ -327,7 +198,7 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile,
std::vector<std::string> const mocDependFilters =
InfoGetList("AM_MOC_DEPEND_FILTERS");
// Insert Q_PLUGIN_METADATA dependency filter
- if (this->QtMajorVersion != "4") {
+ if (this->QtVersionMajor != 4) {
this->MocDependFilterPush("Q_PLUGIN_METADATA",
"[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
"[^\\)]*FILE[ \t]*\"([^\"]+)\"");
@@ -344,7 +215,7 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile,
}
} else {
this->LogFileError(
- cmQtAutoGen::MOC, this->InfoFile,
+ cmQtAutoGen::MOC, this->GetInfoFile(),
"AUTOMOC_DEPEND_FILTERS list size is not a multiple of 2");
return false;
}
@@ -365,7 +236,7 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile,
std::ostringstream ost;
ost << "files/options lists sizes missmatch (" << sources.size() << "/"
<< options.size() << ")";
- this->LogFileError(cmQtAutoGen::UIC, this->InfoFile, ost.str());
+ this->LogFileError(cmQtAutoGen::UIC, this->GetInfoFile(), ost.str());
return false;
}
auto fitEnd = sources.cend();
@@ -379,53 +250,6 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile,
}
}
- // - Rcc
- if (this->RccEnabled()) {
- // File lists
- auto sources = InfoGetList("AM_RCC_SOURCES");
- auto builds = InfoGetList("AM_RCC_BUILDS");
- auto options = InfoGetLists("AM_RCC_OPTIONS");
- auto inputs = InfoGetLists("AM_RCC_INPUTS");
-
- if (sources.size() != builds.size()) {
- std::ostringstream ost;
- ost << "sources, builds lists sizes missmatch (" << sources.size() << "/"
- << builds.size() << ")";
- this->LogFileError(cmQtAutoGen::RCC, this->InfoFile, ost.str());
- return false;
- }
- if (sources.size() != options.size()) {
- std::ostringstream ost;
- ost << "sources, options lists sizes missmatch (" << sources.size()
- << "/" << options.size() << ")";
- this->LogFileError(cmQtAutoGen::RCC, this->InfoFile, ost.str());
- return false;
- }
- if (sources.size() != inputs.size()) {
- std::ostringstream ost;
- ost << "sources, inputs lists sizes missmatch (" << sources.size() << "/"
- << inputs.size() << ")";
- this->LogFileError(cmQtAutoGen::RCC, this->InfoFile, ost.str());
- return false;
- }
- {
- auto srcItEnd = sources.end();
- auto srcIt = sources.begin();
- auto bldIt = builds.begin();
- auto optIt = options.begin();
- auto inpIt = inputs.begin();
- while (srcIt != srcItEnd) {
- this->RccJobs.push_back(RccJob{ std::move(*srcIt), std::move(*bldIt),
- std::move(*optIt),
- std::move(*inpIt) });
- ++srcIt;
- ++bldIt;
- ++optIt;
- ++inpIt;
- }
- }
- }
-
// Initialize source file jobs
{
// Utility lambdas
@@ -585,21 +409,10 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile,
}
}
- // - Old settings file
- {
- this->SettingsFile = cmSystemTools::CollapseFullPath(targetDirectory);
- cmSystemTools::ConvertToUnixSlashes(this->SettingsFile);
- this->SettingsFile += "/AutogenOldSettings";
- if (this->MultiConfig != cmQtAutoGen::SINGLE) {
- this->SettingsFile += this->ConfigSuffix;
- }
- this->SettingsFile += ".cmake";
- }
-
return true;
}
-void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile)
+void cmQtAutoGeneratorMocUic::SettingsFileRead(cmMakefile* makefile)
{
// Compose current settings strings
{
@@ -631,20 +444,6 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile)
str += sep;
this->SettingsStringUic = crypt.HashString(str);
}
- if (this->RccEnabled()) {
- std::string str;
- str += this->RccExecutable;
- for (const RccJob& rccJob : this->RccJobs) {
- str += sep;
- str += rccJob.QrcFile;
- str += sep;
- str += rccJob.RccFile;
- str += sep;
- str += cmJoin(rccJob.Options, ";");
- }
- str += sep;
- this->SettingsStringRcc = crypt.HashString(str);
- }
}
// Read old settings
@@ -659,9 +458,6 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile)
if (!SMatch(SettingsKeyUic, this->SettingsStringUic)) {
this->UicSettingsChanged = true;
}
- if (!SMatch(SettingsKeyRcc, this->SettingsStringRcc)) {
- this->RccSettingsChanged = true;
- }
}
// In case any setting changed remove the old settings file.
// This triggers a full rebuild on the next run if the current
@@ -673,16 +469,15 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile)
// If the file could not be read re-generate everythiung.
this->MocSettingsChanged = true;
this->UicSettingsChanged = true;
- this->RccSettingsChanged = true;
}
}
-bool cmQtAutoGenerators::SettingsFileWrite()
+bool cmQtAutoGeneratorMocUic::SettingsFileWrite()
{
bool success = true;
// Only write if any setting changed
if (this->SettingsChanged()) {
- if (this->Verbose) {
+ if (this->GetVerbose()) {
this->LogInfo(cmQtAutoGen::GEN, "Writing settings file " +
cmQtAutoGen::Quoted(this->SettingsFile));
}
@@ -699,7 +494,6 @@ bool cmQtAutoGenerators::SettingsFileWrite()
};
SettingAppend(SettingsKeyMoc, this->SettingsStringMoc);
SettingAppend(SettingsKeyUic, this->SettingsStringUic);
- SettingAppend(SettingsKeyRcc, this->SettingsStringRcc);
}
// Write settings file
if (!this->FileWrite(cmQtAutoGen::GEN, this->SettingsFile, settings)) {
@@ -713,7 +507,7 @@ bool cmQtAutoGenerators::SettingsFileWrite()
return success;
}
-bool cmQtAutoGenerators::Process()
+bool cmQtAutoGeneratorMocUic::Process(cmMakefile* makefile)
{
// the program goes through all .cpp files to see which moc files are
// included. It is not really interesting how the moc file is named, but
@@ -723,6 +517,12 @@ bool cmQtAutoGenerators::Process()
// moc file is included anywhere a moc_<filename>.cpp file is created and
// included in the mocs_compilation.cpp file.
+ if (!this->InitInfoFile(makefile)) {
+ return false;
+ }
+ // Read latest settings
+ this->SettingsFileRead(makefile);
+
// Create AUTOGEN include directory
{
std::string const incDirAbs = cmSystemTools::CollapseCombinedPath(
@@ -758,7 +558,8 @@ bool cmQtAutoGenerators::Process()
if (!this->UicGenerateAll()) {
return false;
}
- if (!this->RccGenerateAll()) {
+
+ if (!this->SettingsFileWrite()) {
return false;
}
@@ -768,12 +569,12 @@ bool cmQtAutoGenerators::Process()
/**
* @return True on success
*/
-bool cmQtAutoGenerators::ParseSourceFile(std::string const& absFilename,
- const SourceJob& job)
+bool cmQtAutoGeneratorMocUic::ParseSourceFile(std::string const& absFilename,
+ const SourceJob& job)
{
std::string contentText;
std::string error;
- bool success = ReadFile(contentText, absFilename, &error);
+ bool success = this->FileRead(contentText, absFilename, &error);
if (success) {
if (!contentText.empty()) {
if (job.Moc) {
@@ -796,12 +597,12 @@ bool cmQtAutoGenerators::ParseSourceFile(std::string const& absFilename,
/**
* @return True on success
*/
-bool cmQtAutoGenerators::ParseHeaderFile(std::string const& absFilename,
- const SourceJob& job)
+bool cmQtAutoGeneratorMocUic::ParseHeaderFile(std::string const& absFilename,
+ const SourceJob& job)
{
std::string contentText;
std::string error;
- bool success = ReadFile(contentText, absFilename, &error);
+ bool success = this->FileRead(contentText, absFilename, &error);
if (success) {
if (!contentText.empty()) {
if (job.Moc) {
@@ -824,7 +625,7 @@ bool cmQtAutoGenerators::ParseHeaderFile(std::string const& absFilename,
/**
* @return True on success
*/
-bool cmQtAutoGenerators::ParsePostprocess()
+bool cmQtAutoGeneratorMocUic::ParsePostprocess()
{
bool success = true;
// Read missing dependencies
@@ -832,7 +633,7 @@ bool cmQtAutoGenerators::ParsePostprocess()
if (!item->DependsValid) {
std::string content;
std::string error;
- if (ReadFile(content, item->SourceFile, &error)) {
+ if (this->FileRead(content, item->SourceFile, &error)) {
this->MocFindDepends(item->SourceFile, content, item->Depends);
item->DependsValid = true;
} else {
@@ -855,7 +656,7 @@ bool cmQtAutoGenerators::ParsePostprocess()
* @brief Tests if the file should be ignored for moc scanning
* @return True if the file should be ignored
*/
-bool cmQtAutoGenerators::MocSkip(std::string const& absFilename) const
+bool cmQtAutoGeneratorMocUic::MocSkip(std::string const& absFilename) const
{
if (this->MocEnabled()) {
// Test if the file name is on the skip list
@@ -870,8 +671,8 @@ bool cmQtAutoGenerators::MocSkip(std::string const& absFilename) const
* @brief Tests if the C++ content requires moc processing
* @return True if moc is required
*/
-bool cmQtAutoGenerators::MocRequired(std::string const& contentText,
- std::string* macroName)
+bool cmQtAutoGeneratorMocUic::MocRequired(std::string const& contentText,
+ std::string* macroName)
{
for (KeyRegExp& filter : this->MocMacroFilters) {
// Run a simple find string operation before the expensive
@@ -889,7 +690,7 @@ bool cmQtAutoGenerators::MocRequired(std::string const& contentText,
return false;
}
-std::string cmQtAutoGenerators::MocStringMacros() const
+std::string cmQtAutoGeneratorMocUic::MocStringMacros() const
{
std::string res;
const auto itB = this->MocMacroFilters.cbegin();
@@ -911,7 +712,7 @@ std::string cmQtAutoGenerators::MocStringMacros() const
return res;
}
-std::string cmQtAutoGenerators::MocStringHeaders(
+std::string cmQtAutoGeneratorMocUic::MocStringHeaders(
std::string const& fileBase) const
{
std::string res = fileBase;
@@ -921,7 +722,7 @@ std::string cmQtAutoGenerators::MocStringHeaders(
return res;
}
-std::string cmQtAutoGenerators::MocFindIncludedHeader(
+std::string cmQtAutoGeneratorMocUic::MocFindIncludedHeader(
std::string const& sourcePath, std::string const& includeBase) const
{
std::string header;
@@ -944,7 +745,7 @@ std::string cmQtAutoGenerators::MocFindIncludedHeader(
return header;
}
-bool cmQtAutoGenerators::MocFindIncludedFile(
+bool cmQtAutoGeneratorMocUic::MocFindIncludedFile(
std::string& absFile, std::string const& sourcePath,
std::string const& includeString) const
{
@@ -974,8 +775,8 @@ bool cmQtAutoGenerators::MocFindIncludedFile(
return success;
}
-bool cmQtAutoGenerators::MocDependFilterPush(std::string const& key,
- std::string const& regExp)
+bool cmQtAutoGeneratorMocUic::MocDependFilterPush(std::string const& key,
+ std::string const& regExp)
{
std::string error;
if (!key.empty()) {
@@ -1009,9 +810,9 @@ bool cmQtAutoGenerators::MocDependFilterPush(std::string const& key,
return true;
}
-void cmQtAutoGenerators::MocFindDepends(std::string const& absFilename,
- std::string const& contentText,
- std::set<std::string>& depends)
+void cmQtAutoGeneratorMocUic::MocFindDepends(std::string const& absFilename,
+ std::string const& contentText,
+ std::set<std::string>& depends)
{
if (this->MocDependFilters.empty() && contentText.empty()) {
return;
@@ -1040,7 +841,7 @@ void cmQtAutoGenerators::MocFindDepends(std::string const& absFilename,
std::string incFile;
if (this->MocFindIncludedFile(incFile, sourcePath, match)) {
depends.insert(incFile);
- if (this->Verbose) {
+ if (this->GetVerbose()) {
this->LogInfo(cmQtAutoGen::MOC, "Found dependency:\n " +
cmQtAutoGen::Quoted(absFilename) + "\n " +
cmQtAutoGen::Quoted(incFile));
@@ -1057,10 +858,10 @@ void cmQtAutoGenerators::MocFindDepends(std::string const& absFilename,
/**
* @return True on success
*/
-bool cmQtAutoGenerators::MocParseSourceContent(std::string const& absFilename,
- std::string const& contentText)
+bool cmQtAutoGeneratorMocUic::MocParseSourceContent(
+ std::string const& absFilename, std::string const& contentText)
{
- if (this->Verbose) {
+ if (this->GetVerbose()) {
this->LogInfo(cmQtAutoGen::MOC, "Checking: " + absFilename);
}
@@ -1296,10 +1097,10 @@ bool cmQtAutoGenerators::MocParseSourceContent(std::string const& absFilename,
return true;
}
-void cmQtAutoGenerators::MocParseHeaderContent(std::string const& absFilename,
- std::string const& contentText)
+void cmQtAutoGeneratorMocUic::MocParseHeaderContent(
+ std::string const& absFilename, std::string const& contentText)
{
- if (this->Verbose) {
+ if (this->GetVerbose()) {
this->LogInfo(cmQtAutoGen::MOC, "Checking: " + absFilename);
}
@@ -1329,7 +1130,7 @@ void cmQtAutoGenerators::MocParseHeaderContent(std::string const& absFilename,
}
}
-bool cmQtAutoGenerators::MocGenerateAll()
+bool cmQtAutoGeneratorMocUic::MocGenerateAll()
{
if (!this->MocEnabled()) {
return true;
@@ -1384,7 +1185,7 @@ bool cmQtAutoGenerators::MocGenerateAll()
if (!this->MocPredefsCmd.empty()) {
if (this->MocSettingsChanged ||
!cmSystemTools::FileExists(this->MocPredefsFileAbs)) {
- if (this->Verbose) {
+ if (this->GetVerbose()) {
this->LogBold("Generating MOC predefs " + this->MocPredefsFileRel);
}
@@ -1419,7 +1220,7 @@ bool cmQtAutoGenerators::MocGenerateAll()
}
} else {
// Touch to update the time stamp
- if (this->Verbose) {
+ if (this->GetVerbose()) {
this->LogInfo(cmQtAutoGen::MOC,
"Touching moc_predefs " + this->MocPredefsFileRel);
}
@@ -1470,7 +1271,7 @@ bool cmQtAutoGenerators::MocGenerateAll()
if (this->FileDiffers(this->MocCompFileAbs, mocs)) {
// Actually write mocs compilation file
- if (this->Verbose) {
+ if (this->GetVerbose()) {
this->LogBold("Generating MOC compilation " + this->MocCompFileRel);
}
if (!this->FileWrite(cmQtAutoGen::MOC, this->MocCompFileAbs, mocs)) {
@@ -1480,7 +1281,7 @@ bool cmQtAutoGenerators::MocGenerateAll()
}
} else if (autoNameGenerated) {
// Only touch mocs compilation file
- if (this->Verbose) {
+ if (this->GetVerbose()) {
this->LogInfo(cmQtAutoGen::MOC,
"Touching mocs compilation " + this->MocCompFileRel);
}
@@ -1494,8 +1295,8 @@ bool cmQtAutoGenerators::MocGenerateAll()
/**
* @return True on success
*/
-bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob,
- bool* generated)
+bool cmQtAutoGeneratorMocUic::MocGenerateFile(const MocJobAuto& mocJob,
+ bool* generated)
{
bool success = true;
@@ -1505,7 +1306,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob,
bool generate = false;
std::string generateReason;
if (!generate && !cmSystemTools::FileExists(mocFileAbs.c_str())) {
- if (this->Verbose) {
+ if (this->GetVerbose()) {
generateReason = "Generating ";
generateReason += cmQtAutoGen::Quoted(mocFileAbs);
generateReason += " from its source file ";
@@ -1515,7 +1316,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob,
generate = true;
}
if (!generate && this->MocSettingsChanged) {
- if (this->Verbose) {
+ if (this->GetVerbose()) {
generateReason = "Generating ";
generateReason += cmQtAutoGen::Quoted(mocFileAbs);
generateReason += " from ";
@@ -1525,7 +1326,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob,
generate = true;
}
if (!generate && this->MocPredefsChanged) {
- if (this->Verbose) {
+ if (this->GetVerbose()) {
generateReason = "Generating ";
generateReason += cmQtAutoGen::Quoted(mocFileAbs);
generateReason += " from ";
@@ -1537,7 +1338,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob,
if (!generate) {
std::string error;
if (FileIsOlderThan(mocFileAbs, mocJob.SourceFile, &error)) {
- if (this->Verbose) {
+ if (this->GetVerbose()) {
generateReason = "Generating ";
generateReason += cmQtAutoGen::Quoted(mocFileAbs);
generateReason += " because it's older than its source file ";
@@ -1556,7 +1357,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob,
std::string error;
for (std::string const& depFile : mocJob.Depends) {
if (FileIsOlderThan(mocFileAbs, depFile, &error)) {
- if (this->Verbose) {
+ if (this->GetVerbose()) {
generateReason = "Generating ";
generateReason += cmQtAutoGen::Quoted(mocFileAbs);
generateReason += " from ";
@@ -1577,7 +1378,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob,
if (generate) {
// Log
- if (this->Verbose) {
+ if (this->GetVerbose()) {
this->LogBold("Generating MOC source " + mocJob.BuildFileRel);
this->LogInfo(cmQtAutoGen::MOC, generateReason);
}
@@ -1627,7 +1428,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob,
/**
* @brief Tests if the file name is in the skip list
*/
-bool cmQtAutoGenerators::UicSkip(std::string const& absFilename) const
+bool cmQtAutoGeneratorMocUic::UicSkip(std::string const& absFilename) const
{
if (this->UicEnabled()) {
// Test if the file name is on the skip list
@@ -1638,10 +1439,10 @@ bool cmQtAutoGenerators::UicSkip(std::string const& absFilename) const
return true;
}
-bool cmQtAutoGenerators::UicParseContent(std::string const& absFilename,
- std::string const& contentText)
+bool cmQtAutoGeneratorMocUic::UicParseContent(std::string const& absFilename,
+ std::string const& contentText)
{
- if (this->Verbose) {
+ if (this->GetVerbose()) {
this->LogInfo(cmQtAutoGen::UIC, "Checking: " + absFilename);
}
@@ -1689,9 +1490,9 @@ bool cmQtAutoGenerators::UicParseContent(std::string const& absFilename,
return true;
}
-bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile,
- std::string const& sourceFile,
- std::string const& includeString)
+bool cmQtAutoGeneratorMocUic::UicFindIncludedFile(
+ std::string& absFile, std::string const& sourceFile,
+ std::string const& includeString)
{
bool success = false;
std::string searchFile =
@@ -1753,7 +1554,7 @@ bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile,
return success;
}
-bool cmQtAutoGenerators::UicGenerateAll()
+bool cmQtAutoGeneratorMocUic::UicGenerateAll()
{
if (!this->UicEnabled()) {
return true;
@@ -1817,7 +1618,7 @@ bool cmQtAutoGenerators::UicGenerateAll()
/**
* @return True on success
*/
-bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob)
+bool cmQtAutoGeneratorMocUic::UicGenerateFile(const UicJob& uicJob)
{
bool success = true;
@@ -1827,7 +1628,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob)
bool generate = false;
std::string generateReason;
if (!generate && !cmSystemTools::FileExists(uicFileAbs.c_str())) {
- if (this->Verbose) {
+ if (this->GetVerbose()) {
generateReason = "Generating ";
generateReason += cmQtAutoGen::Quoted(uicFileAbs);
generateReason += " from its source file ";
@@ -1837,7 +1638,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob)
generate = true;
}
if (!generate && this->UicSettingsChanged) {
- if (this->Verbose) {
+ if (this->GetVerbose()) {
generateReason = "Generating ";
generateReason += cmQtAutoGen::Quoted(uicFileAbs);
generateReason += " from ";
@@ -1849,7 +1650,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob)
if (!generate) {
std::string error;
if (FileIsOlderThan(uicFileAbs, uicJob.SourceFile, &error)) {
- if (this->Verbose) {
+ if (this->GetVerbose()) {
generateReason = "Generating ";
generateReason += cmQtAutoGen::Quoted(uicFileAbs);
generateReason += " because it's older than its source file ";
@@ -1865,7 +1666,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob)
}
if (generate) {
// Log
- if (this->Verbose) {
+ if (this->GetVerbose()) {
this->LogBold("Generating UIC header " + uicJob.BuildFileRel);
this->LogInfo(cmQtAutoGen::UIC, generateReason);
}
@@ -1880,7 +1681,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob)
auto optionIt = this->UicOptions.find(uicJob.SourceFile);
if (optionIt != this->UicOptions.end()) {
cmQtAutoGen::UicMergeOptions(allOpts, optionIt->second,
- (this->QtMajorVersion == "5"));
+ (this->QtVersionMajor == 5));
}
cmd.insert(cmd.end(), allOpts.begin(), allOpts.end());
}
@@ -1911,413 +1712,13 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob)
return success;
}
-bool cmQtAutoGenerators::RccGenerateAll()
-{
- if (!this->RccEnabled()) {
- return true;
- }
-
- // Generate rcc files
- for (const RccJob& rccJob : this->RccJobs) {
- if (!this->RccGenerateFile(rccJob)) {
- return false;
- }
- }
- return true;
-}
-
-/**
- * @return True on success
- */
-bool cmQtAutoGenerators::RccGenerateFile(const RccJob& rccJob)
-{
- bool success = true;
- bool rccGenerated = false;
-
- std::string rccFileAbs;
- {
- std::string suffix;
- switch (this->MultiConfig) {
- case cmQtAutoGen::SINGLE:
- break;
- case cmQtAutoGen::WRAP:
- suffix = "_CMAKE";
- suffix += this->ConfigSuffix;
- suffix += "_";
- break;
- case cmQtAutoGen::FULL:
- suffix = this->ConfigSuffix;
- break;
- }
- rccFileAbs = cmQtAutoGen::AppendFilenameSuffix(rccJob.RccFile, suffix);
- }
- std::string const rccFileRel = cmSystemTools::RelativePath(
- this->AutogenBuildDir.c_str(), rccFileAbs.c_str());
-
- // Check if regeneration is required
- bool generate = false;
- std::string generateReason;
- if (!cmSystemTools::FileExists(rccJob.QrcFile)) {
- {
- std::string error = "Could not find the file\n ";
- error += cmQtAutoGen::Quoted(rccJob.QrcFile);
- this->LogError(cmQtAutoGen::RCC, error);
- }
- success = false;
- }
- if (success && !generate && !cmSystemTools::FileExists(rccFileAbs.c_str())) {
- if (this->Verbose) {
- generateReason = "Generating ";
- generateReason += cmQtAutoGen::Quoted(rccFileAbs);
- generateReason += " from its source file ";
- generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile);
- generateReason += " because it doesn't exist";
- }
- generate = true;
- }
- if (success && !generate && this->RccSettingsChanged) {
- if (this->Verbose) {
- generateReason = "Generating ";
- generateReason += cmQtAutoGen::Quoted(rccFileAbs);
- generateReason += " from ";
- generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile);
- generateReason += " because the RCC settings changed";
- }
- generate = true;
- }
- if (success && !generate) {
- std::string error;
- if (FileIsOlderThan(rccFileAbs, rccJob.QrcFile, &error)) {
- if (this->Verbose) {
- generateReason = "Generating ";
- generateReason += cmQtAutoGen::Quoted(rccFileAbs);
- generateReason += " because it is older than ";
- generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile);
- }
- generate = true;
- } else {
- if (!error.empty()) {
- this->LogError(cmQtAutoGen::RCC, error);
- success = false;
- }
- }
- }
- if (success && !generate) {
- // Acquire input file list
- std::vector<std::string> readFiles;
- std::vector<std::string> const* files = nullptr;
- if (!rccJob.Inputs.empty()) {
- files = &rccJob.Inputs;
- } else {
- // Read input file list from qrc file
- std::string error;
- if (cmQtAutoGen::RccListInputs(this->QtMajorVersion, this->RccExecutable,
- rccJob.QrcFile, readFiles, &error)) {
- files = &readFiles;
- } else {
- this->LogFileError(cmQtAutoGen::RCC, rccJob.QrcFile, error);
- success = false;
- }
- }
- // Test if any input file is newer than the build file
- if (files != nullptr) {
- std::string error;
- for (std::string const& resFile : *files) {
- if (!cmSystemTools::FileExists(resFile.c_str())) {
- error = "Could not find the file\n ";
- error += cmQtAutoGen::Quoted(resFile);
- error += "\nwhich is listed in\n ";
- error += cmQtAutoGen::Quoted(rccJob.QrcFile);
- break;
- }
- if (FileIsOlderThan(rccFileAbs, resFile, &error)) {
- if (this->Verbose) {
- generateReason = "Generating ";
- generateReason += cmQtAutoGen::Quoted(rccFileAbs);
- generateReason += " from ";
- generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile);
- generateReason += " because it is older than ";
- generateReason += cmQtAutoGen::Quoted(resFile);
- }
- generate = true;
- break;
- }
- if (!error.empty()) {
- break;
- }
- }
- // Print error
- if (!error.empty()) {
- this->LogError(cmQtAutoGen::RCC, error);
- success = false;
- }
- }
- }
- // Regenerate on demand
- if (generate) {
- // Log
- if (this->Verbose) {
- this->LogBold("Generating RCC source " + rccFileRel);
- this->LogInfo(cmQtAutoGen::RCC, generateReason);
- }
-
- // Make sure the parent directory exists
- if (this->MakeParentDirectory(cmQtAutoGen::RCC, rccFileAbs)) {
- // Compose rcc command
- std::vector<std::string> cmd;
- cmd.push_back(this->RccExecutable);
- cmd.insert(cmd.end(), rccJob.Options.begin(), rccJob.Options.end());
- cmd.push_back("-o");
- cmd.push_back(rccFileAbs);
- cmd.push_back(rccJob.QrcFile);
-
- std::string output;
- if (this->RunCommand(cmd, output)) {
- // Success
- rccGenerated = true;
- } else {
- {
- std::string emsg = "rcc failed for\n ";
- emsg += cmQtAutoGen::Quoted(rccJob.QrcFile);
- this->LogCommandError(cmQtAutoGen::RCC, emsg, cmd, output);
- }
- cmSystemTools::RemoveFile(rccFileAbs);
- success = false;
- }
- } else {
- // Parent directory creation failed
- success = false;
- }
- }
-
- // Generate a wrapper source file on demand
- if (success && (this->MultiConfig == cmQtAutoGen::WRAP)) {
- // Wrapper file name
- std::string const& wrapperFileAbs = rccJob.RccFile;
- std::string const wrapperFileRel = cmSystemTools::RelativePath(
- this->AutogenBuildDir.c_str(), wrapperFileAbs.c_str());
- // Wrapper file content
- std::string content = "// This is an autogenerated configuration "
- "wrapper file. Changes will be overwritten.\n"
- "#include \"";
- content += cmSystemTools::GetFilenameName(rccFileRel);
- content += "\"\n";
- // Write content to file
- if (this->FileDiffers(wrapperFileAbs, content)) {
- // Write new wrapper file
- if (this->Verbose) {
- this->LogBold("Generating RCC wrapper " + wrapperFileRel);
- }
- if (!this->FileWrite(cmQtAutoGen::RCC, wrapperFileAbs, content)) {
- this->LogFileError(cmQtAutoGen::RCC, wrapperFileAbs,
- "rcc wrapper file writing failed");
- success = false;
- }
- } else if (rccGenerated) {
- // Just touch the wrapper file
- if (this->Verbose) {
- this->LogInfo(cmQtAutoGen::RCC,
- "Touching RCC wrapper " + wrapperFileRel);
- }
- cmSystemTools::Touch(wrapperFileAbs, false);
- }
- }
-
- return success;
-}
-
-void cmQtAutoGenerators::LogBold(std::string const& message) const
-{
- cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
- cmsysTerminal_Color_ForegroundBold,
- message.c_str(), true, this->ColorOutput);
-}
-
-void cmQtAutoGenerators::LogInfo(cmQtAutoGen::Generator genType,
- std::string const& message) const
-{
- std::string msg = cmQtAutoGen::GeneratorName(genType);
- msg += ": ";
- msg += message;
- if (msg.back() != '\n') {
- msg.push_back('\n');
- }
- cmSystemTools::Stdout(msg.c_str(), msg.size());
-}
-
-void cmQtAutoGenerators::LogWarning(cmQtAutoGen::Generator genType,
- std::string const& message) const
-{
- std::string msg = cmQtAutoGen::GeneratorName(genType);
- msg += " warning:";
- if (message.find('\n') == std::string::npos) {
- // Single line message
- msg.push_back(' ');
- } else {
- // Multi line message
- msg.push_back('\n');
- }
- // Message
- msg += message;
- if (msg.back() != '\n') {
- msg.push_back('\n');
- }
- msg.push_back('\n');
- cmSystemTools::Stdout(msg.c_str(), msg.size());
-}
-
-void cmQtAutoGenerators::LogFileWarning(cmQtAutoGen::Generator genType,
- std::string const& filename,
- std::string const& message) const
-{
- std::string msg = " ";
- msg += cmQtAutoGen::Quoted(filename);
- msg.push_back('\n');
- // Message
- msg += message;
- this->LogWarning(genType, msg);
-}
-
-void cmQtAutoGenerators::LogError(cmQtAutoGen::Generator genType,
- std::string const& message) const
-{
- std::string msg;
- msg.push_back('\n');
- msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " error");
- // Message
- msg += message;
- if (msg.back() != '\n') {
- msg.push_back('\n');
- }
- msg.push_back('\n');
- cmSystemTools::Stderr(msg.c_str(), msg.size());
-}
-
-void cmQtAutoGenerators::LogFileError(cmQtAutoGen::Generator genType,
- std::string const& filename,
- std::string const& message) const
-{
- std::string emsg = " ";
- emsg += cmQtAutoGen::Quoted(filename);
- emsg += '\n';
- // Message
- emsg += message;
- this->LogError(genType, emsg);
-}
-
-void cmQtAutoGenerators::LogCommandError(
- cmQtAutoGen::Generator genType, std::string const& message,
- std::vector<std::string> const& command, std::string const& output) const
-{
- std::string msg;
- msg.push_back('\n');
- msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " subprocess error");
- msg += message;
- if (msg.back() != '\n') {
- msg.push_back('\n');
- }
- msg.push_back('\n');
- msg += HeadLine("Command");
- msg += QuotedCommand(command);
- if (msg.back() != '\n') {
- msg.push_back('\n');
- }
- msg.push_back('\n');
- msg += HeadLine("Output");
- msg += output;
- if (msg.back() != '\n') {
- msg.push_back('\n');
- }
- msg.push_back('\n');
- cmSystemTools::Stderr(msg.c_str(), msg.size());
-}
-
-/**
- * @brief Generates the parent directory of the given file on demand
- * @return True on success
- */
-bool cmQtAutoGenerators::MakeParentDirectory(cmQtAutoGen::Generator genType,
- std::string const& filename) const
-{
- bool success = true;
- std::string const dirName = cmSystemTools::GetFilenamePath(filename);
- if (!dirName.empty()) {
- if (!cmSystemTools::MakeDirectory(dirName)) {
- this->LogFileError(genType, filename,
- "Could not create parent directory");
- success = false;
- }
- }
- return success;
-}
-
-bool cmQtAutoGenerators::FileDiffers(std::string const& filename,
- std::string const& content)
-{
- bool differs = true;
- {
- std::string oldContents;
- if (ReadFile(oldContents, filename)) {
- differs = (oldContents != content);
- }
- }
- return differs;
-}
-
-bool cmQtAutoGenerators::FileWrite(cmQtAutoGen::Generator genType,
- std::string const& filename,
- std::string const& content)
-{
- std::string error;
- // Make sure the parent directory exists
- if (this->MakeParentDirectory(genType, filename)) {
- cmsys::ofstream outfile;
- outfile.open(filename.c_str(),
- (std::ios::out | std::ios::binary | std::ios::trunc));
- if (outfile) {
- outfile << content;
- // Check for write errors
- if (!outfile.good()) {
- error = "File writing failed";
- }
- } else {
- error = "Opening file for writing failed";
- }
- }
- if (!error.empty()) {
- this->LogFileError(genType, filename, error);
- return false;
- }
- return true;
-}
-
-/**
- * @brief Runs a command and returns true on success
- * @return True on success
- */
-bool cmQtAutoGenerators::RunCommand(std::vector<std::string> const& command,
- std::string& output) const
-{
- // Log command
- if (this->Verbose) {
- std::string qcmd = QuotedCommand(command);
- qcmd.push_back('\n');
- cmSystemTools::Stdout(qcmd.c_str(), qcmd.size());
- }
- // Execute command
- int retVal = 0;
- bool res = cmSystemTools::RunSingleCommand(
- command, &output, &output, &retVal, nullptr, cmSystemTools::OUTPUT_NONE);
- return (res && (retVal == 0));
-}
-
/**
* @brief Tries to find the header file to the given file base path by
* appending different header extensions
* @return True on success
*/
-bool cmQtAutoGenerators::FindHeader(std::string& header,
- std::string const& testBasePath) const
+bool cmQtAutoGeneratorMocUic::FindHeader(std::string& header,
+ std::string const& testBasePath) const
{
for (std::string const& ext : this->HeaderExtensions) {
std::string testFilePath(testBasePath);
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGeneratorMocUic.h
index a7bb538..d510939 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGeneratorMocUic.h
@@ -1,12 +1,13 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmQtAutoGenerators_h
-#define cmQtAutoGenerators_h
+#ifndef cmQtAutoGeneratorMocUic_h
+#define cmQtAutoGeneratorMocUic_h
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmFilePathChecksum.h"
#include "cmQtAutoGen.h"
+#include "cmQtAutoGenerator.h"
#include "cmsys/RegularExpression.hxx"
#include <map>
@@ -17,12 +18,11 @@
class cmMakefile;
-class cmQtAutoGenerators
+class cmQtAutoGeneratorMocUic : public cmQtAutoGenerator
{
- CM_DISABLE_COPY(cmQtAutoGenerators)
+ CM_DISABLE_COPY(cmQtAutoGeneratorMocUic)
public:
- cmQtAutoGenerators();
- bool Run(std::string const& targetDirectory, std::string const& config);
+ cmQtAutoGeneratorMocUic();
private:
// -- Types
@@ -80,30 +80,19 @@ private:
std::string IncludeString;
};
- /// @brief RCC job
- struct RccJob
- {
- std::string QrcFile;
- std::string RccFile;
- std::vector<std::string> Options;
- std::vector<std::string> Inputs;
- };
-
// -- Initialization
- bool InitInfoFile(cmMakefile* makefile, std::string const& targetDirectory,
- std::string const& config);
+ bool InitInfoFile(cmMakefile* makefile);
// -- Settings file
void SettingsFileRead(cmMakefile* makefile);
bool SettingsFileWrite();
bool SettingsChanged() const
{
- return (this->MocSettingsChanged || this->RccSettingsChanged ||
- this->UicSettingsChanged);
+ return (this->MocSettingsChanged || this->UicSettingsChanged);
}
// -- Central processing
- bool Process();
+ bool Process(cmMakefile* makefile) override;
// -- Source parsing
bool ParseSourceFile(std::string const& absFilename, const SourceJob& job);
@@ -146,54 +135,17 @@ private:
bool UicGenerateAll();
bool UicGenerateFile(const UicJob& uicJob);
- // -- Rcc
- bool RccEnabled() const { return !this->RccExecutable.empty(); }
- bool RccGenerateAll();
- bool RccGenerateFile(const RccJob& rccJob);
-
- // -- Log info
- void LogBold(std::string const& message) const;
- void LogInfo(cmQtAutoGen::Generator genType,
- std::string const& message) const;
- // -- Log warning
- void LogWarning(cmQtAutoGen::Generator genType,
- std::string const& message) const;
- void LogFileWarning(cmQtAutoGen::Generator genType,
- std::string const& filename,
- std::string const& message) const;
- // -- Log error
- void LogError(cmQtAutoGen::Generator genType,
- std::string const& message) const;
- void LogFileError(cmQtAutoGen::Generator genType,
- std::string const& filename,
- std::string const& message) const;
- void LogCommandError(cmQtAutoGen::Generator genType,
- std::string const& message,
- std::vector<std::string> const& command,
- std::string const& output) const;
-
// -- Utility
- bool MakeParentDirectory(cmQtAutoGen::Generator genType,
- std::string const& filename) const;
- bool FileDiffers(std::string const& filename, std::string const& content);
- bool FileWrite(cmQtAutoGen::Generator genType, std::string const& filename,
- std::string const& content);
bool FindHeader(std::string& header, std::string const& testBasePath) const;
- bool RunCommand(std::vector<std::string> const& command,
- std::string& output) const;
// -- Meta
- std::string InfoFile;
std::string ConfigSuffix;
cmQtAutoGen::MultiConfig MultiConfig;
// -- Settings
bool IncludeProjectDirsBefore;
- bool Verbose;
- bool ColorOutput;
std::string SettingsFile;
std::string SettingsStringMoc;
std::string SettingsStringUic;
- std::string SettingsStringRcc;
// -- Directories
std::string ProjectSourceDir;
std::string ProjectBinaryDir;
@@ -202,11 +154,9 @@ private:
std::string AutogenBuildDir;
std::string AutogenIncludeDir;
// -- Qt environment
- std::string QtMajorVersion;
- std::string QtMinorVersion;
+ unsigned long QtVersionMajor;
std::string MocExecutable;
std::string UicExecutable;
- std::string RccExecutable;
// -- File lists
std::map<std::string, SourceJob> HeaderJobs;
std::map<std::string, SourceJob> SourceJobs;
@@ -240,9 +190,6 @@ private:
std::vector<std::string> UicSearchPaths;
cmsys::RegularExpression UicRegExpInclude;
std::vector<std::unique_ptr<UicJob>> UicJobs;
- // -- Rcc
- bool RccSettingsChanged;
- std::vector<RccJob> RccJobs;
};
#endif
diff --git a/Source/cmQtAutoGeneratorRcc.cxx b/Source/cmQtAutoGeneratorRcc.cxx
new file mode 100644
index 0000000..3c9f1a8
--- /dev/null
+++ b/Source/cmQtAutoGeneratorRcc.cxx
@@ -0,0 +1,425 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmQtAutoGen.h"
+#include "cmQtAutoGeneratorRcc.h"
+
+#include "cmAlgorithms.h"
+#include "cmCryptoHash.h"
+#include "cmMakefile.h"
+#include "cmOutputConverter.h"
+#include "cmSystemTools.h"
+
+// -- Static variables
+
+static const char* SettingsKeyRcc = "ARCC_SETTINGS_HASH";
+
+// -- Class methods
+
+cmQtAutoGeneratorRcc::cmQtAutoGeneratorRcc()
+ : MultiConfig(cmQtAutoGen::WRAP)
+ , SettingsChanged(false)
+{
+}
+
+bool cmQtAutoGeneratorRcc::InfoFileRead(cmMakefile* makefile)
+{
+ // Utility lambdas
+ auto InfoGet = [makefile](const char* key) {
+ return makefile->GetSafeDefinition(key);
+ };
+ auto InfoGetList = [makefile](const char* key) -> std::vector<std::string> {
+ std::vector<std::string> list;
+ cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list);
+ return list;
+ };
+ auto InfoGetConfig = [makefile, this](const char* key) -> std::string {
+ const char* valueConf = nullptr;
+ {
+ std::string keyConf = key;
+ keyConf += '_';
+ keyConf += this->GetInfoConfig();
+ valueConf = makefile->GetDefinition(keyConf);
+ }
+ if (valueConf == nullptr) {
+ valueConf = makefile->GetSafeDefinition(key);
+ }
+ return std::string(valueConf);
+ };
+ auto InfoGetConfigList =
+ [&InfoGetConfig](const char* key) -> std::vector<std::string> {
+ std::vector<std::string> list;
+ cmSystemTools::ExpandListArgument(InfoGetConfig(key), list);
+ return list;
+ };
+
+ // -- Read info file
+ if (!makefile->ReadListFile(this->GetInfoFile().c_str())) {
+ this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
+ "File processing failed");
+ return false;
+ }
+
+ // -- Meta
+ this->MultiConfig =
+ cmQtAutoGen::MultiConfigType(InfoGet("ARCC_MULTI_CONFIG"));
+ this->ConfigSuffix = InfoGetConfig("ARCC_CONFIG_SUFFIX");
+ if (this->ConfigSuffix.empty()) {
+ this->ConfigSuffix = "_";
+ this->ConfigSuffix += this->GetInfoConfig();
+ }
+
+ this->SettingsFile = InfoGetConfig("ARCC_SETTINGS_FILE");
+
+ // - Files and directories
+ this->ProjectSourceDir = InfoGet("ARCC_CMAKE_SOURCE_DIR");
+ this->ProjectBinaryDir = InfoGet("ARCC_CMAKE_BINARY_DIR");
+ this->CurrentSourceDir = InfoGet("ARCC_CMAKE_CURRENT_SOURCE_DIR");
+ this->CurrentBinaryDir = InfoGet("ARCC_CMAKE_CURRENT_BINARY_DIR");
+ this->AutogenBuildDir = InfoGet("ARCC_BUILD_DIR");
+
+ // - Qt environment
+ this->RccExecutable = InfoGet("ARCC_RCC_EXECUTABLE");
+ this->RccListOptions = InfoGetList("ARCC_RCC_LIST_OPTIONS");
+
+ // - Job
+ this->QrcFile = InfoGet("ARCC_SOURCE");
+ this->RccFile = InfoGet("ARCC_OUTPUT");
+ this->Options = InfoGetConfigList("ARCC_OPTIONS");
+ this->Inputs = InfoGetList("ARCC_INPUTS");
+
+ // - Validity checks
+ if (this->SettingsFile.empty()) {
+ this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
+ "Settings file name missing");
+ return false;
+ }
+ if (this->AutogenBuildDir.empty()) {
+ this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
+ "Autogen build directory missing");
+ return false;
+ }
+ if (this->RccExecutable.empty()) {
+ this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
+ "rcc executable missing");
+ return false;
+ }
+ if (this->QrcFile.empty()) {
+ this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
+ "rcc input file missing");
+ return false;
+ }
+ if (this->RccFile.empty()) {
+ this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
+ "rcc output file missing");
+ return false;
+ }
+
+ // Init derived information
+ // ------------------------
+
+ // Init file path checksum generator
+ this->FilePathChecksum.setupParentDirs(
+ this->CurrentSourceDir, this->CurrentBinaryDir, this->ProjectSourceDir,
+ this->ProjectBinaryDir);
+
+ return true;
+}
+
+void cmQtAutoGeneratorRcc::SettingsFileRead(cmMakefile* makefile)
+{
+ // Compose current settings strings
+ {
+ cmCryptoHash crypt(cmCryptoHash::AlgoSHA256);
+ std::string const sep(" ~~~ ");
+ {
+ std::string str;
+ str += this->RccExecutable;
+ str += sep;
+ str += cmJoin(this->RccListOptions, ";");
+ str += sep;
+ str += this->QrcFile;
+ str += sep;
+ str += this->RccFile;
+ str += sep;
+ str += cmJoin(this->Options, ";");
+ str += sep;
+ str += cmJoin(this->Inputs, ";");
+ str += sep;
+ this->SettingsString = crypt.HashString(str);
+ }
+ }
+
+ // Read old settings
+ if (makefile->ReadListFile(this->SettingsFile.c_str())) {
+ {
+ auto SMatch = [makefile](const char* key, std::string const& value) {
+ return (value == makefile->GetSafeDefinition(key));
+ };
+ if (!SMatch(SettingsKeyRcc, this->SettingsString)) {
+ this->SettingsChanged = true;
+ }
+ }
+ // In case any setting changed remove the old settings file.
+ // This triggers a full rebuild on the next run if the current
+ // build is aborted before writing the current settings in the end.
+ if (this->SettingsChanged) {
+ cmSystemTools::RemoveFile(this->SettingsFile);
+ }
+ } else {
+ // If the file could not be read re-generate everythiung.
+ this->SettingsChanged = true;
+ }
+}
+
+bool cmQtAutoGeneratorRcc::SettingsFileWrite()
+{
+ bool success = true;
+ // Only write if any setting changed
+ if (this->SettingsChanged) {
+ if (this->GetVerbose()) {
+ this->LogInfo(cmQtAutoGen::RCC, "Writing settings file " +
+ cmQtAutoGen::Quoted(this->SettingsFile));
+ }
+ // Compose settings file content
+ std::string settings;
+ {
+ auto SettingAppend = [&settings](const char* key,
+ std::string const& value) {
+ settings += "set(";
+ settings += key;
+ settings += " ";
+ settings += cmOutputConverter::EscapeForCMake(value);
+ settings += ")\n";
+ };
+ SettingAppend(SettingsKeyRcc, this->SettingsString);
+ }
+ // Write settings file
+ if (!this->FileWrite(cmQtAutoGen::RCC, this->SettingsFile, settings)) {
+ this->LogFileError(cmQtAutoGen::RCC, this->SettingsFile,
+ "Settings file writing failed");
+ // Remove old settings file to trigger a full rebuild on the next run
+ cmSystemTools::RemoveFile(this->SettingsFile);
+ success = false;
+ }
+ }
+ return success;
+}
+
+bool cmQtAutoGeneratorRcc::Process(cmMakefile* makefile)
+{
+ // Read info file
+ if (!this->InfoFileRead(makefile)) {
+ return false;
+ }
+ // Read latest settings
+ this->SettingsFileRead(makefile);
+ // Generate rcc file
+ if (!this->RccGenerate()) {
+ return false;
+ }
+ // Write latest settings
+ if (!this->SettingsFileWrite()) {
+ return false;
+ }
+ return true;
+}
+
+/**
+ * @return True on success
+ */
+bool cmQtAutoGeneratorRcc::RccGenerate()
+{
+ bool success = true;
+ bool rccGenerated = false;
+
+ std::string rccFileAbs;
+ {
+ std::string suffix;
+ switch (this->MultiConfig) {
+ case cmQtAutoGen::SINGLE:
+ break;
+ case cmQtAutoGen::WRAP:
+ suffix = "_CMAKE";
+ suffix += this->ConfigSuffix;
+ suffix += "_";
+ break;
+ case cmQtAutoGen::FULL:
+ suffix = this->ConfigSuffix;
+ break;
+ }
+ rccFileAbs = cmQtAutoGen::AppendFilenameSuffix(this->RccFile, suffix);
+ }
+ std::string const rccFileRel = cmSystemTools::RelativePath(
+ this->AutogenBuildDir.c_str(), rccFileAbs.c_str());
+
+ // Check if regeneration is required
+ bool generate = false;
+ std::string generateReason;
+ if (!cmSystemTools::FileExists(this->QrcFile)) {
+ {
+ std::string error = "Could not find the file\n ";
+ error += cmQtAutoGen::Quoted(this->QrcFile);
+ this->LogError(cmQtAutoGen::RCC, error);
+ }
+ success = false;
+ }
+ if (success && !generate && !cmSystemTools::FileExists(rccFileAbs.c_str())) {
+ if (this->GetVerbose()) {
+ generateReason = "Generating ";
+ generateReason += cmQtAutoGen::Quoted(rccFileAbs);
+ generateReason += " from its source file ";
+ generateReason += cmQtAutoGen::Quoted(this->QrcFile);
+ generateReason += " because it doesn't exist";
+ }
+ generate = true;
+ }
+ if (success && !generate && this->SettingsChanged) {
+ if (this->GetVerbose()) {
+ generateReason = "Generating ";
+ generateReason += cmQtAutoGen::Quoted(rccFileAbs);
+ generateReason += " from ";
+ generateReason += cmQtAutoGen::Quoted(this->QrcFile);
+ generateReason += " because the RCC settings changed";
+ }
+ generate = true;
+ }
+ if (success && !generate) {
+ std::string error;
+ if (FileIsOlderThan(rccFileAbs, this->QrcFile, &error)) {
+ if (this->GetVerbose()) {
+ generateReason = "Generating ";
+ generateReason += cmQtAutoGen::Quoted(rccFileAbs);
+ generateReason += " because it is older than ";
+ generateReason += cmQtAutoGen::Quoted(this->QrcFile);
+ }
+ generate = true;
+ } else {
+ if (!error.empty()) {
+ this->LogError(cmQtAutoGen::RCC, error);
+ success = false;
+ }
+ }
+ }
+ if (success && !generate) {
+ // Acquire input file list
+ std::vector<std::string> readFiles;
+ std::vector<std::string> const* files = nullptr;
+ if (!this->Inputs.empty()) {
+ files = &this->Inputs;
+ } else {
+ // Read input file list from qrc file
+ std::string error;
+ if (cmQtAutoGen::RccListInputs(this->RccExecutable, this->RccListOptions,
+ this->QrcFile, readFiles, &error)) {
+ files = &readFiles;
+ } else {
+ this->LogFileError(cmQtAutoGen::RCC, this->QrcFile, error);
+ success = false;
+ }
+ }
+ // Test if any input file is newer than the build file
+ if (files != nullptr) {
+ std::string error;
+ for (std::string const& resFile : *files) {
+ if (!cmSystemTools::FileExists(resFile.c_str())) {
+ error = "Could not find the file\n ";
+ error += cmQtAutoGen::Quoted(resFile);
+ error += "\nwhich is listed in\n ";
+ error += cmQtAutoGen::Quoted(this->QrcFile);
+ break;
+ }
+ if (FileIsOlderThan(rccFileAbs, resFile, &error)) {
+ if (this->GetVerbose()) {
+ generateReason = "Generating ";
+ generateReason += cmQtAutoGen::Quoted(rccFileAbs);
+ generateReason += " from ";
+ generateReason += cmQtAutoGen::Quoted(this->QrcFile);
+ generateReason += " because it is older than ";
+ generateReason += cmQtAutoGen::Quoted(resFile);
+ }
+ generate = true;
+ break;
+ }
+ if (!error.empty()) {
+ break;
+ }
+ }
+ // Print error
+ if (!error.empty()) {
+ this->LogError(cmQtAutoGen::RCC, error);
+ success = false;
+ }
+ }
+ }
+ // Regenerate on demand
+ if (generate) {
+ // Log
+ if (this->GetVerbose()) {
+ this->LogBold("Generating RCC source " + rccFileRel);
+ this->LogInfo(cmQtAutoGen::RCC, generateReason);
+ }
+
+ // Make sure the parent directory exists
+ if (this->MakeParentDirectory(cmQtAutoGen::RCC, rccFileAbs)) {
+ // Compose rcc command
+ std::vector<std::string> cmd;
+ cmd.push_back(this->RccExecutable);
+ cmd.insert(cmd.end(), this->Options.begin(), this->Options.end());
+ cmd.push_back("-o");
+ cmd.push_back(rccFileAbs);
+ cmd.push_back(this->QrcFile);
+
+ std::string output;
+ if (this->RunCommand(cmd, output)) {
+ // Success
+ rccGenerated = true;
+ } else {
+ {
+ std::string emsg = "rcc failed for\n ";
+ emsg += cmQtAutoGen::Quoted(this->QrcFile);
+ this->LogCommandError(cmQtAutoGen::RCC, emsg, cmd, output);
+ }
+ cmSystemTools::RemoveFile(rccFileAbs);
+ success = false;
+ }
+ } else {
+ // Parent directory creation failed
+ success = false;
+ }
+ }
+
+ // Generate a wrapper source file on demand
+ if (success && (this->MultiConfig == cmQtAutoGen::WRAP)) {
+ // Wrapper file name
+ std::string const& wrapperFileAbs = this->RccFile;
+ std::string const wrapperFileRel = cmSystemTools::RelativePath(
+ this->AutogenBuildDir.c_str(), wrapperFileAbs.c_str());
+ // Wrapper file content
+ std::string content = "// This is an autogenerated configuration "
+ "wrapper file. Changes will be overwritten.\n"
+ "#include \"";
+ content += cmSystemTools::GetFilenameName(rccFileRel);
+ content += "\"\n";
+ // Write content to file
+ if (this->FileDiffers(wrapperFileAbs, content)) {
+ // Write new wrapper file
+ if (this->GetVerbose()) {
+ this->LogBold("Generating RCC wrapper " + wrapperFileRel);
+ }
+ if (!this->FileWrite(cmQtAutoGen::RCC, wrapperFileAbs, content)) {
+ this->LogFileError(cmQtAutoGen::RCC, wrapperFileAbs,
+ "rcc wrapper file writing failed");
+ success = false;
+ }
+ } else if (rccGenerated) {
+ // Just touch the wrapper file
+ if (this->GetVerbose()) {
+ this->LogInfo(cmQtAutoGen::RCC,
+ "Touching RCC wrapper " + wrapperFileRel);
+ }
+ cmSystemTools::Touch(wrapperFileAbs, false);
+ }
+ }
+
+ return success;
+}
diff --git a/Source/cmQtAutoGeneratorRcc.h b/Source/cmQtAutoGeneratorRcc.h
new file mode 100644
index 0000000..0e3f690
--- /dev/null
+++ b/Source/cmQtAutoGeneratorRcc.h
@@ -0,0 +1,56 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmQtAutoGeneratorRcc_h
+#define cmQtAutoGeneratorRcc_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmFilePathChecksum.h"
+#include "cmQtAutoGen.h"
+#include "cmQtAutoGenerator.h"
+
+#include <string>
+#include <vector>
+
+class cmMakefile;
+
+class cmQtAutoGeneratorRcc : public cmQtAutoGenerator
+{
+ CM_DISABLE_COPY(cmQtAutoGeneratorRcc)
+public:
+ cmQtAutoGeneratorRcc();
+
+private:
+ // -- Initialization & settings
+ bool InfoFileRead(cmMakefile* makefile);
+ void SettingsFileRead(cmMakefile* makefile);
+ bool SettingsFileWrite();
+ // -- Central processing
+ bool Process(cmMakefile* makefile) override;
+ bool RccGenerate();
+
+ // -- Config settings
+ std::string ConfigSuffix;
+ cmQtAutoGen::MultiConfig MultiConfig;
+ // -- Settings
+ bool SettingsChanged;
+ std::string SettingsFile;
+ std::string SettingsString;
+ // -- Directories
+ std::string ProjectSourceDir;
+ std::string ProjectBinaryDir;
+ std::string CurrentSourceDir;
+ std::string CurrentBinaryDir;
+ std::string AutogenBuildDir;
+ cmFilePathChecksum FilePathChecksum;
+ // -- Qt environment
+ std::string RccExecutable;
+ std::vector<std::string> RccListOptions;
+ // -- Job
+ std::string QrcFile;
+ std::string RccFile;
+ std::vector<std::string> Options;
+ std::vector<std::string> Inputs;
+};
+
+#endif
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 449db9d..3d9f65a 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -6,7 +6,8 @@
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmQtAutoGenerators.h"
+#include "cmQtAutoGeneratorMocUic.h"
+#include "cmQtAutoGeneratorRcc.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmSystemTools.h"
@@ -992,11 +993,20 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
}
#ifdef CMAKE_BUILD_WITH_CMAKE
- if (args[1] == "cmake_autogen" && args.size() >= 4) {
- cmQtAutoGenerators autogen;
+ if ((args[1] == "cmake_autogen") && (args.size() >= 4)) {
+ cmQtAutoGeneratorMocUic autoGen;
+ std::string const& infoDir = args[2];
std::string const& config = args[3];
- bool autogenSuccess = autogen.Run(args[2], config);
- return autogenSuccess ? 0 : 1;
+ return autoGen.Run(infoDir, config) ? 0 : 1;
+ }
+ if ((args[1] == "cmake_autorcc") && (args.size() >= 3)) {
+ cmQtAutoGeneratorRcc autoGen;
+ std::string const& infoFile = args[2];
+ std::string config;
+ if (args.size() > 3) {
+ config = args[3];
+ };
+ return autoGen.Run(infoFile, config) ? 0 : 1;
}
#endif