From d1e5eb849704f73d646f64105d44807f3de50e48 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Sat, 26 Aug 2017 13:59:57 +0200 Subject: Autogen: Iterate source files only once This is a large commit that serves multiple purposes - Iterate source files only once and store all extracted information in a cmQtAutogenDigest class that can be reused. This is brings speed improvements because several properties are only evaluated once. More that that it helps to avoid duplication of code with non trivial files property checks. - Fix the Visual Studio generator to use PRE_BUILD when possible. - Convert `for( ... )` loops to C++11 range base loops where possible (cmQtAutogen*.cxx only). - String concatenation optimizations. --- Modules/AutogenInfo.cmake.in | 3 +- Source/CMakeLists.txt | 5 +- Source/cmGlobalGenerator.cxx | 74 +-- Source/cmGlobalGenerator.h | 4 +- Source/cmQtAutoGen.cxx | 243 ++++++++++ Source/cmQtAutoGen.h | 47 ++ Source/cmQtAutoGenDigest.h | 62 +++ Source/cmQtAutoGeneratorCommon.cxx | 216 --------- Source/cmQtAutoGeneratorCommon.h | 39 -- Source/cmQtAutoGeneratorInitializer.cxx | 784 +++++++++++++++----------------- Source/cmQtAutoGeneratorInitializer.h | 13 +- Source/cmQtAutoGenerators.cxx | 300 +++++------- Source/cmQtAutoGenerators.h | 7 +- 13 files changed, 899 insertions(+), 898 deletions(-) create mode 100644 Source/cmQtAutoGen.cxx create mode 100644 Source/cmQtAutoGen.h create mode 100644 Source/cmQtAutoGenDigest.h delete mode 100644 Source/cmQtAutoGeneratorCommon.cxx delete mode 100644 Source/cmQtAutoGeneratorCommon.h diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in index 60ceebc..80522ab 100644 --- a/Modules/AutogenInfo.cmake.in +++ b/Modules/AutogenInfo.cmake.in @@ -9,6 +9,7 @@ set(AM_SOURCES @_sources@) set(AM_HEADERS @_headers@) # Qt environment set(AM_QT_VERSION_MAJOR @_qt_version_major@) +set(AM_QT_VERSION_MINOR @_qt_version_minor@) set(AM_QT_MOC_EXECUTABLE @_qt_moc_executable@) set(AM_QT_UIC_EXECUTABLE @_qt_uic_executable@) set(AM_QT_RCC_EXECUTABLE @_qt_rcc_executable@) @@ -28,7 +29,7 @@ set(AM_UIC_OPTIONS_FILES @_qt_uic_options_files@) set(AM_UIC_OPTIONS_OPTIONS @_qt_uic_options_options@) set(AM_UIC_SEARCH_PATHS @_uic_search_paths@) # RCC settings -set(AM_RCC_SOURCES @_rcc_files@ ) +set(AM_RCC_SOURCES @_rcc_files@) set(AM_RCC_INPUTS @_rcc_inputs@) set(AM_RCC_OPTIONS_FILES @_rcc_options_files@) set(AM_RCC_OPTIONS_OPTIONS @_rcc_options_options@) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index bcc3437..9cd7b84 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -307,8 +307,9 @@ set(SRCS cmPropertyDefinitionMap.h cmPropertyMap.cxx cmPropertyMap.h - cmQtAutoGeneratorCommon.cxx - cmQtAutoGeneratorCommon.h + cmQtAutoGen.cxx + cmQtAutoGen.h + cmQtAutoGenDigest.h cmQtAutoGeneratorInitializer.cxx cmQtAutoGeneratorInitializer.h cmQtAutoGenerators.cxx diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index ab35593..39c181a 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1263,8 +1263,7 @@ 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 - std::vector autogenTargets = - this->CreateQtAutoGeneratorsTargets(); + cmQtAutoGenDigestUPV autogenDigests = this->CreateQtAutoGeneratorsTargets(); #endif unsigned int i; @@ -1287,11 +1286,10 @@ bool cmGlobalGenerator::Compute() } #ifdef CMAKE_BUILD_WITH_CMAKE - for (std::vector::iterator it = - autogenTargets.begin(); - it != autogenTargets.end(); ++it) { - cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(*it); + for (const cmQtAutoGenDigestUP& digest : autogenDigests) { + cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(*digest); } + autogenDigests.clear(); #endif for (i = 0; i < this->LocalGenerators.size(); ++i) { @@ -1427,24 +1425,16 @@ bool cmGlobalGenerator::ComputeTargetDepends() return true; } -std::vector -cmGlobalGenerator::CreateQtAutoGeneratorsTargets() +cmQtAutoGenDigestUPV cmGlobalGenerator::CreateQtAutoGeneratorsTargets() { - std::vector autogenTargets; + cmQtAutoGenDigestUPV autogenDigests; #ifdef CMAKE_BUILD_WITH_CMAKE - for (std::vector::const_iterator lgit = - this->LocalGenerators.begin(); - lgit != this->LocalGenerators.end(); ++lgit) { - cmLocalGenerator* localGen = *lgit; + for (cmLocalGenerator* localGen : this->LocalGenerators) { const std::vector& targets = localGen->GetGeneratorTargets(); // Find targets that require AUTOGEN processing - std::vector filteredTargets; - filteredTargets.reserve(targets.size()); - for (std::vector::const_iterator ti = targets.begin(); - ti != targets.end(); ++ti) { - cmGeneratorTarget* target = *ti; + for (cmGeneratorTarget* target : targets) { if (target->GetType() == cmStateEnums::GLOBAL_TARGET) { continue; } @@ -1455,33 +1445,43 @@ cmGlobalGenerator::CreateQtAutoGeneratorsTargets() target->GetType() != cmStateEnums::OBJECT_LIBRARY) { continue; } - if ((!target->GetPropertyAsBool("AUTOMOC") && - !target->GetPropertyAsBool("AUTOUIC") && - !target->GetPropertyAsBool("AUTORCC")) || - target->IsImported()) { + if (target->IsImported()) { continue; } - // don't do anything if there is no Qt4 or Qt5Core (which contains moc) - cmMakefile* mf = target->Target->GetMakefile(); - std::string qtMajorVersion = mf->GetSafeDefinition("QT_VERSION_MAJOR"); - if (qtMajorVersion == "") { - qtMajorVersion = mf->GetSafeDefinition("Qt5Core_VERSION_MAJOR"); + + const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC"); + const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC"); + const bool rccEnabled = target->GetPropertyAsBool("AUTORCC"); + if (!mocEnabled && !uicEnabled && !rccEnabled) { + continue; } - if (qtMajorVersion != "4" && qtMajorVersion != "5") { + + std::string qtVersionMajor = + cmQtAutoGeneratorInitializer::GetQtMajorVersion(target); + // don't do anything if there is no Qt4 or Qt5Core (which contains moc) + if (qtVersionMajor != "4" && qtVersionMajor != "5") { continue; } - filteredTargets.push_back(target); - } - // Initialize AUTOGEN targets - for (std::vector::iterator ti = - filteredTargets.begin(); - ti != filteredTargets.end(); ++ti) { - cmQtAutoGeneratorInitializer::InitializeAutogenTarget(localGen, *ti); - autogenTargets.push_back(*ti); + + { + 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)); + } } } + // Initialize autogen targets + for (const cmQtAutoGenDigestUP& digest : autogenDigests) { + cmQtAutoGeneratorInitializer::InitializeAutogenTarget(*digest); + } #endif - return autogenTargets; + return autogenDigests; } cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer( diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 3931ab8..18ca682 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -15,6 +15,7 @@ #include "cmCustomCommandLines.h" #include "cmExportSetMap.h" +#include "cmQtAutoGenDigest.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -422,7 +423,8 @@ protected: virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const; - std::vector CreateQtAutoGeneratorsTargets(); + // Qt auto generators + cmQtAutoGenDigestUPV CreateQtAutoGeneratorsTargets(); std::string SelectMakeProgram(const std::string& makeProgram, const std::string& makeDefault = "") const; diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx new file mode 100644 index 0000000..f1453b4 --- /dev/null +++ b/Source/cmQtAutoGen.cxx @@ -0,0 +1,243 @@ +/* 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 "cmAlgorithms.h" +#include "cmSystemTools.h" + +#include "cmsys/FStream.hxx" +#include "cmsys/RegularExpression.hxx" + +#include +#include + +// - Static variables + +const std::string genNameGen = "AutoGen"; +const std::string genNameMoc = "AutoMoc"; +const std::string genNameUic = "AutoUic"; +const std::string genNameRcc = "AutoRcc"; + +// - Static functions + +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(const std::string& fileName, + std::vector& files, + std::string* errorMessage) +{ + bool allGood = true; + // Read qrc file content into string + std::string qrcContents; + { + cmsys::ifstream ifs(fileName.c_str()); + if (ifs) { + std::ostringstream osst; + osst << ifs.rdbuf(); + qrcContents = osst.str(); + } else { + if (errorMessage != nullptr) { + std::ostringstream ost; + ost << "AutoRcc: Error: Rcc file not readable:\n" + << cmQtAutoGen::Quoted(fileName) << "\n"; + *errorMessage = ost.str(); + } + allGood = false; + } + } + if (allGood) { + // qrc file directory + std::string qrcDir(cmsys::SystemTools::GetFilenamePath(fileName)); + if (!qrcDir.empty()) { + qrcDir += '/'; + } + + cmsys::RegularExpression fileMatchRegex("(]*>)"); + + size_t offset = 0; + while (fileMatchRegex.find(qrcContents.c_str() + offset)) { + std::string qrcEntry = fileMatchRegex.match(1); + offset += qrcEntry.size(); + { + fileReplaceRegex.find(qrcEntry); + std::string tag = fileReplaceRegex.match(1); + qrcEntry = qrcEntry.substr(tag.size()); + } + if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) { + qrcEntry = qrcDir + qrcEntry; + } + files.push_back(qrcEntry); + } + } + return allGood; +} + +/// @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(const std::string& rccCommand, + const std::string& fileName, + std::vector& files, + std::string* errorMessage) +{ + if (rccCommand.empty()) { + cmSystemTools::Error("AutoRcc: Error: rcc executable not available\n"); + return false; + } + + // Read rcc features + bool hasDashDashList = false; + { + std::vector 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); + if (result && retVal == 0 && + rccStdOut.find("--list") != std::string::npos) { + hasDashDashList = true; + } + } + + // Run rcc list command + bool result = false; + int retVal = 0; + std::string rccStdOut; + std::string rccStdErr; + { + std::vector command; + command.push_back(rccCommand); + command.push_back(hasDashDashList ? "--list" : "-list"); + command.push_back(fileName); + result = + cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal, + nullptr, cmSystemTools::OUTPUT_NONE); + } + if (!result || retVal) { + if (errorMessage != nullptr) { + std::ostringstream ost; + ost << "AutoRcc: Error: Rcc list process for " << fileName + << " failed:\n" + << rccStdOut << "\n" + << rccStdErr << "\n"; + *errorMessage = ost.str(); + } + return false; + } + + // Parse rcc std output + { + std::istringstream ostr(rccStdOut); + std::string oline; + while (std::getline(ostr, oline)) { + oline = utilStripCR(oline); + if (!oline.empty()) { + files.push_back(oline); + } + } + } + // Parse rcc error output + { + std::istringstream estr(rccStdErr); + std::string eline; + while (std::getline(estr, eline)) { + eline = utilStripCR(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 << "AutoRcc: Error: Rcc lists unparsable output:\n" + << cmQtAutoGen::Quoted(eline) << "\n"; + *errorMessage = ost.str(); + } + return false; + } + pos += searchString.length(); + std::string::size_type sz = eline.size() - pos - 1; + files.push_back(eline.substr(pos, sz)); + } + } + } + + return true; +} + +// - Class definitions + +const std::string cmQtAutoGen::listSep = "@LSEP@"; + +const std::string& cmQtAutoGen::GeneratorName(GeneratorType type) +{ + switch (type) { + case GeneratorType::GEN: + return genNameGen; + case GeneratorType::MOC: + return genNameMoc; + case GeneratorType::UIC: + return genNameUic; + case GeneratorType::RCC: + return genNameRcc; + } + return genNameGen; +} + +std::string cmQtAutoGen::GeneratorNameUpper(GeneratorType genType) +{ + return cmSystemTools::UpperCase(cmQtAutoGen::GeneratorName(genType)); +} + +std::string cmQtAutoGen::Quoted(const std::string& text) +{ + static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a", + "\b", "\\b", "\f", "\\f", "\n", "\\n", + "\r", "\\r", "\t", "\\t", "\v", "\\v" }; + + std::string res = text; + for (const char* const* it = cmArrayBegin(rep); it != cmArrayEnd(rep); + it += 2) { + cmSystemTools::ReplaceString(res, *it, *(it + 1)); + } + res = '"' + res; + res += '"'; + return res; +} + +bool cmQtAutoGen::RccListInputs(const std::string& qtMajorVersion, + const std::string& rccCommand, + const std::string& fileName, + std::vector& files, + std::string* errorMessage) +{ + bool allGood = false; + if (cmsys::SystemTools::FileExists(fileName.c_str())) { + if (qtMajorVersion == "4") { + allGood = RccListInputsQt4(fileName, files, errorMessage); + } else { + allGood = RccListInputsQt5(rccCommand, fileName, files, errorMessage); + } + } else { + if (errorMessage != nullptr) { + std::ostringstream ost; + ost << "AutoRcc: Error: Rcc file does not exist:\n" + << cmQtAutoGen::Quoted(fileName) << "\n"; + *errorMessage = ost.str(); + } + } + return allGood; +} diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h new file mode 100644 index 0000000..88fd0fc --- /dev/null +++ b/Source/cmQtAutoGen.h @@ -0,0 +1,47 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmQtAutoGen_h +#define cmQtAutoGen_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include +#include + +/** \class cmQtAutoGen + * \brief Class used as namespace for QtAutogen related types and functions + */ +class cmQtAutoGen +{ +public: + static const std::string listSep; + + enum GeneratorType + { + GEN, // General + MOC, + UIC, + RCC + }; + +public: + /// @brief Returns the generator name + static const std::string& GeneratorName(GeneratorType genType); + /// @brief Returns the generator name in upper case + static std::string GeneratorNameUpper(GeneratorType genType); + + /// @brief Returns a the string escaped and enclosed in quotes + /// + static std::string Quoted(const std::string& text); + + /// @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(const std::string& qtMajorVersion, + const std::string& rccCommand, + const std::string& fileName, + std::vector& files, + std::string* errorMessage = nullptr); +}; + +#endif diff --git a/Source/cmQtAutoGenDigest.h b/Source/cmQtAutoGenDigest.h new file mode 100644 index 0000000..2bd9f04 --- /dev/null +++ b/Source/cmQtAutoGenDigest.h @@ -0,0 +1,62 @@ +/* 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 +#include +#include + +class cmGeneratorTarget; + +class cmQtAutoGenDigestQrc +{ +public: + cmQtAutoGenDigestQrc() + : Generated(false) + { + } + +public: + std::string QrcFile; + std::string RccFile; + bool Generated; + std::vector Options; + std::vector 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 Headers; + std::vector HeadersGenerated; + std::vector Sources; + std::vector SourcesGenerated; + std::vector Qrcs; +}; + +// Utility types +typedef std::unique_ptr cmQtAutoGenDigestUP; +typedef std::vector cmQtAutoGenDigestUPV; + +#endif diff --git a/Source/cmQtAutoGeneratorCommon.cxx b/Source/cmQtAutoGeneratorCommon.cxx deleted file mode 100644 index a8e6b96..0000000 --- a/Source/cmQtAutoGeneratorCommon.cxx +++ /dev/null @@ -1,216 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmQtAutoGeneratorCommon.h" -#include "cmAlgorithms.h" -#include "cmSystemTools.h" - -#include "cmsys/FStream.hxx" -#include "cmsys/RegularExpression.hxx" - -#include -#include - -// - Static functions - -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(const std::string& fileName, - std::vector& files, - std::string* errorMessage) -{ - bool allGood = true; - // Read qrc file content into string - std::string qrcContents; - { - cmsys::ifstream ifs(fileName.c_str()); - if (ifs) { - std::ostringstream osst; - osst << ifs.rdbuf(); - qrcContents = osst.str(); - } else { - if (errorMessage != nullptr) { - std::ostringstream ost; - ost << "AutoRcc: Error: Rcc file not readable:\n" - << cmQtAutoGeneratorCommon::Quoted(fileName) << "\n"; - *errorMessage = ost.str(); - } - allGood = false; - } - } - if (allGood) { - // qrc file directory - std::string qrcDir(cmsys::SystemTools::GetFilenamePath(fileName)); - if (!qrcDir.empty()) { - qrcDir += '/'; - } - - cmsys::RegularExpression fileMatchRegex("(]*>)"); - - size_t offset = 0; - while (fileMatchRegex.find(qrcContents.c_str() + offset)) { - std::string qrcEntry = fileMatchRegex.match(1); - offset += qrcEntry.size(); - { - fileReplaceRegex.find(qrcEntry); - std::string tag = fileReplaceRegex.match(1); - qrcEntry = qrcEntry.substr(tag.size()); - } - if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) { - qrcEntry = qrcDir + qrcEntry; - } - files.push_back(qrcEntry); - } - } - return allGood; -} - -/// @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(const std::string& rccCommand, - const std::string& fileName, - std::vector& files, - std::string* errorMessage) -{ - if (rccCommand.empty()) { - cmSystemTools::Error("AutoRcc: Error: rcc executable not available\n"); - return false; - } - - // Read rcc features - bool hasDashDashList = false; - { - std::vector 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); - if (result && retVal == 0 && - rccStdOut.find("--list") != std::string::npos) { - hasDashDashList = true; - } - } - - // Run rcc list command - bool result = false; - int retVal = 0; - std::string rccStdOut; - std::string rccStdErr; - { - std::vector command; - command.push_back(rccCommand); - command.push_back(hasDashDashList ? "--list" : "-list"); - command.push_back(fileName); - result = - cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal, - nullptr, cmSystemTools::OUTPUT_NONE); - } - if (!result || retVal) { - if (errorMessage != nullptr) { - std::ostringstream ost; - ost << "AutoRcc: Error: Rcc list process for " << fileName - << " failed:\n" - << rccStdOut << "\n" - << rccStdErr << "\n"; - *errorMessage = ost.str(); - } - return false; - } - - // Parse rcc std output - { - std::istringstream ostr(rccStdOut); - std::string oline; - while (std::getline(ostr, oline)) { - oline = utilStripCR(oline); - if (!oline.empty()) { - files.push_back(oline); - } - } - } - // Parse rcc error output - { - std::istringstream estr(rccStdErr); - std::string eline; - while (std::getline(estr, eline)) { - eline = utilStripCR(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 << "AutoRcc: Error: Rcc lists unparsable output:\n" - << cmQtAutoGeneratorCommon::Quoted(eline) << "\n"; - *errorMessage = ost.str(); - } - return false; - } - pos += searchString.length(); - std::string::size_type sz = eline.size() - pos - 1; - files.push_back(eline.substr(pos, sz)); - } - } - } - - return true; -} - -// - Class definitions - -const char* cmQtAutoGeneratorCommon::listSep = "@LSEP@"; - -std::string cmQtAutoGeneratorCommon::Quoted(const std::string& text) -{ - static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a", - "\b", "\\b", "\f", "\\f", "\n", "\\n", - "\r", "\\r", "\t", "\\t", "\v", "\\v" }; - - std::string res = text; - for (const char* const* it = cmArrayBegin(rep); it != cmArrayEnd(rep); - it += 2) { - cmSystemTools::ReplaceString(res, *it, *(it + 1)); - } - res = '"' + res; - res += '"'; - return res; -} - -bool cmQtAutoGeneratorCommon::RccListInputs(const std::string& qtMajorVersion, - const std::string& rccCommand, - const std::string& fileName, - std::vector& files, - std::string* errorMessage) -{ - bool allGood = false; - if (cmsys::SystemTools::FileExists(fileName.c_str())) { - if (qtMajorVersion == "4") { - allGood = RccListInputsQt4(fileName, files, errorMessage); - } else { - allGood = RccListInputsQt5(rccCommand, fileName, files, errorMessage); - } - } else { - if (errorMessage != nullptr) { - std::ostringstream ost; - ost << "AutoRcc: Error: Rcc file does not exist:\n" - << cmQtAutoGeneratorCommon::Quoted(fileName) << "\n"; - *errorMessage = ost.str(); - } - } - return allGood; -} diff --git a/Source/cmQtAutoGeneratorCommon.h b/Source/cmQtAutoGeneratorCommon.h deleted file mode 100644 index 23a882a..0000000 --- a/Source/cmQtAutoGeneratorCommon.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmQtAutoGeneratorCommon_h -#define cmQtAutoGeneratorCommon_h - -#include "cmConfigure.h" // IWYU pragma: keep - -#include -#include - -class cmQtAutoGeneratorCommon -{ - // - Types and statics -public: - static const char* listSep; - - enum GeneratorType - { - MOC, - UIC, - RCC - }; - -public: - /// @brief Returns a the string escaped and enclosed in quotes - /// - static std::string Quoted(const std::string& text); - - /// @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(const std::string& qtMajorVersion, - const std::string& rccCommand, - const std::string& fileName, - std::vector& files, - std::string* errorMessage = nullptr); -}; - -#endif diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index ebfb6f0..3fe4028 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -1,7 +1,7 @@ /* 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 "cmQtAutoGeneratorInitializer.h" -#include "cmQtAutoGeneratorCommon.h" #include "cmAlgorithms.h" #include "cmCustomCommand.h" @@ -23,6 +23,7 @@ #include "cmsys/FStream.hxx" #include +#include #include #include #include @@ -35,12 +36,18 @@ inline static const char* SafeString(const char* value) return (value != nullptr) ? value : ""; } -static std::string GetSafeProperty(cmGeneratorTarget const* target, - const char* key) +inline static std::string GetSafeProperty(cmGeneratorTarget const* target, + const char* key) { return std::string(SafeString(target->GetProperty(key))); } +inline static std::string GetSafeProperty(cmSourceFile const* sf, + const char* key) +{ + return std::string(SafeString(sf->GetProperty(key))); +} + inline static bool AutogenMultiConfig(cmGlobalGenerator* globalGen) { return globalGen->IsMultiConfig(); @@ -76,39 +83,40 @@ static std::string GetAutogenTargetBuildDir(cmGeneratorTarget const* target) return targetDir; } -static std::string GetQtMajorVersion(cmGeneratorTarget const* target) +std::string cmQtAutoGeneratorInitializer::GetQtMajorVersion( + cmGeneratorTarget const* target) { cmMakefile* makefile = target->Target->GetMakefile(); - std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR"); - if (qtMajorVersion.empty()) { - qtMajorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR"); + 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) { - qtMajorVersion = targetQtVersion; + qtMajor = targetQtVersion; } - return qtMajorVersion; + return qtMajor; } -static std::string GetQtMinorVersion(cmGeneratorTarget const* target, - const std::string& qtMajorVersion) +std::string cmQtAutoGeneratorInitializer::GetQtMinorVersion( + cmGeneratorTarget const* target, const std::string& qtVersionMajor) { cmMakefile* makefile = target->Target->GetMakefile(); - std::string qtMinorVersion; - if (qtMajorVersion == "5") { - qtMinorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR"); + std::string qtMinor; + if (qtVersionMajor == "5") { + qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR"); } - if (qtMinorVersion.empty()) { - qtMinorVersion = makefile->GetSafeDefinition("QT_VERSION_MINOR"); + if (qtMinor.empty()) { + qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR"); } const char* targetQtVersion = target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", ""); if (targetQtVersion != nullptr) { - qtMinorVersion = targetQtVersion; + qtMinor = targetQtVersion; } - return qtMinorVersion; + return qtMinor; } static bool QtVersionGreaterOrEqual(const std::string& major, @@ -168,9 +176,8 @@ static std::vector GetConfigurationSuffixes(cmMakefile* makefile) std::vector suffixes; if (AutogenMultiConfig(makefile->GetGlobalGenerator())) { makefile->GetConfigurations(suffixes); - for (std::vector::iterator it = suffixes.begin(); - it != suffixes.end(); ++it) { - it->insert(0, "_"); + for (std::string& suffix : suffixes) { + suffix.insert(0, "_"); } } if (suffixes.empty()) { @@ -201,32 +208,39 @@ static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, } static bool AddToSourceGroup(cmMakefile* makefile, const std::string& fileName, - cmQtAutoGeneratorCommon::GeneratorType genType) + cmQtAutoGen::GeneratorType genType) { cmSourceGroup* sourceGroup = nullptr; // Acquire source group { - const char* groupName = nullptr; - // Use generator specific group name - switch (genType) { - case cmQtAutoGeneratorCommon::MOC: - groupName = - makefile->GetState()->GetGlobalProperty("AUTOMOC_SOURCE_GROUP"); - break; - case cmQtAutoGeneratorCommon::RCC: - groupName = - makefile->GetState()->GetGlobalProperty("AUTORCC_SOURCE_GROUP"); - break; - default: - break; - } - // Use default group name on demand - if ((groupName == nullptr) || (*groupName == 0)) { - groupName = - makefile->GetState()->GetGlobalProperty("AUTOGEN_SOURCE_GROUP"); + std::string property; + std::string groupName; + { + std::array props; + // Use generator specific group name + switch (genType) { + case cmQtAutoGen::MOC: + props[0] = "AUTOMOC_SOURCE_GROUP"; + break; + case cmQtAutoGen::RCC: + props[0] = "AUTORCC_SOURCE_GROUP"; + break; + default: + props[0] = "AUTOGEN_SOURCE_GROUP"; + break; + } + props[1] = "AUTOGEN_SOURCE_GROUP"; + for (std::string& prop : props) { + const char* propName = makefile->GetState()->GetGlobalProperty(prop); + if ((propName != nullptr) && (*propName != '\0')) { + groupName = propName; + property = std::move(prop); + break; + } + } } // Generate a source group on demand - if ((groupName != nullptr) && (*groupName != 0)) { + if (!groupName.empty()) { { const char* delimiter = makefile->GetDefinition("SOURCE_GROUP_DELIMITER"); @@ -242,9 +256,12 @@ static bool AddToSourceGroup(cmMakefile* makefile, const std::string& fileName, } } if (sourceGroup == nullptr) { - cmSystemTools::Error( - "Autogen: Could not create or find source group: ", - cmQtAutoGeneratorCommon::Quoted(groupName).c_str()); + std::ostringstream ost; + ost << cmQtAutoGen::GeneratorNameUpper(genType); + ost << ": " << property; + ost << ": Could not find or create the source group "; + ost << cmQtAutoGen::Quoted(groupName); + cmSystemTools::Error(ost.str().c_str()); return false; } } @@ -263,7 +280,7 @@ static void AddCleanFile(cmMakefile* makefile, const std::string& fileName) static void AddGeneratedSource(cmGeneratorTarget* target, const std::string& filename, - cmQtAutoGeneratorCommon::GeneratorType genType) + cmQtAutoGen::GeneratorType genType) { cmMakefile* makefile = target->Target->GetMakefile(); { @@ -276,32 +293,24 @@ static void AddGeneratedSource(cmGeneratorTarget* target, AddToSourceGroup(makefile, filename, genType); } -struct AutogenSetup +struct cmQtAutoGenSetup { - std::vector sources; - std::vector headers; + std::set MocSkip; + std::set UicSkip; - std::set mocSkip; - std::set uicSkip; - - std::map configSuffix; - std::map configMocIncludes; - std::map configMocDefines; - std::map configUicOptions; + std::map ConfigMocIncludes; + std::map ConfigMocDefines; + std::map ConfigUicOptions; }; -static void SetupAcquireScanFiles(cmGeneratorTarget const* target, - bool mocEnabled, bool uicEnabled, - const std::vector& srcFiles, - AutogenSetup& setup) +static void SetupAcquireSkipFiles(cmQtAutoGenDigest const& digest, + cmQtAutoGenSetup& setup) { // Read skip files from makefile sources { const std::vector& allSources = - target->Makefile->GetSourceFiles(); - for (std::vector::const_iterator fit = allSources.begin(); - fit != allSources.end(); ++fit) { - cmSourceFile* sf = *fit; + digest.Target->Makefile->GetSourceFiles(); + for (cmSourceFile* sf : allSources) { // sf->GetExtension() is only valid after sf->GetFullPath() ... const std::string& fPath = sf->GetFullPath(); const cmSystemTools::FileFormat fileType = @@ -311,95 +320,33 @@ static void SetupAcquireScanFiles(cmGeneratorTarget const* target, continue; } const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN"); - const bool mocSkip = - mocEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC")); - const bool uicSkip = - uicEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC")); + const bool mocSkip = digest.MocEnabled && + (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC")); + const bool uicSkip = digest.UicEnabled && + (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC")); if (mocSkip || uicSkip) { const std::string absFile = cmsys::SystemTools::GetRealPath(fPath); if (mocSkip) { - setup.mocSkip.insert(absFile); + setup.MocSkip.insert(absFile); } if (uicSkip) { - setup.uicSkip.insert(absFile); + setup.UicSkip.insert(absFile); } } } } - - const cmPolicies::PolicyStatus CMP0071_status = - target->Makefile->GetPolicyStatus(cmPolicies::CMP0071); - for (std::vector::const_iterator fileIt = srcFiles.begin(); - fileIt != srcFiles.end(); ++fileIt) { - cmSourceFile* sf = *fileIt; - // sf->GetExtension() is only valid after sf->GetFullPath() ... - const std::string& fPath = sf->GetFullPath(); - const cmSystemTools::FileFormat fileType = - cmSystemTools::GetFileFormat(sf->GetExtension().c_str()); - if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) && - !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) { - continue; - } - // Real file path - const std::string absFile = cmsys::SystemTools::GetRealPath(fPath); - // Skip test - const bool mocSkip = !mocEnabled || (setup.mocSkip.count(absFile) != 0); - const bool uicSkip = !uicEnabled || (setup.uicSkip.count(absFile) != 0); - if (mocSkip && uicSkip) { - continue; - } - - // For GENERATED files check status of policy CMP0071 - if (sf->GetPropertyAsBool("GENERATED")) { - bool policyAccept = false; - switch (CMP0071_status) { - case cmPolicies::WARN: { - std::ostringstream ost; - ost << cmPolicies::GetPolicyWarning(cmPolicies::CMP0071) << "\n"; - ost << "AUTOMOC/AUTOUIC: Ignoring GENERATED source file:\n"; - ost << " " << cmQtAutoGeneratorCommon::Quoted(absFile) << "\n"; - target->Makefile->IssueMessage(cmake::AUTHOR_WARNING, ost.str()); - } - CM_FALLTHROUGH; - case cmPolicies::OLD: - // Ignore GENERATED file - break; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::NEW: - // Process GENERATED file - policyAccept = true; - break; - } - if (!policyAccept) { - continue; - } - } - - // Add file name to sources or headers list - switch (fileType) { - case cmSystemTools::CXX_FILE_FORMAT: - setup.sources.push_back(absFile); - break; - case cmSystemTools::HEADER_FILE_FORMAT: - setup.headers.push_back(absFile); - break; - default: - break; - } - } } -static void SetupAutoTargetMoc(cmGeneratorTarget const* target, - std::string const& qtMajorVersion, +static void SetupAutoTargetMoc(const cmQtAutoGenDigest& digest, std::string const& config, std::vector const& configs, - AutogenSetup& setup) + cmQtAutoGenSetup& setup) { + cmGeneratorTarget const* target = digest.Target; cmLocalGenerator* localGen = target->GetLocalGenerator(); cmMakefile* makefile = target->Target->GetMakefile(); - AddDefinitionEscaped(makefile, "_moc_skip", setup.mocSkip); + AddDefinitionEscaped(makefile, "_moc_skip", setup.MocSkip); AddDefinitionEscaped(makefile, "_moc_options", GetSafeProperty(target, "AUTOMOC_MOC_OPTIONS")); AddDefinitionEscaped(makefile, "_moc_relaxed_mode", @@ -410,8 +357,8 @@ static void SetupAutoTargetMoc(cmGeneratorTarget const* target, AddDefinitionEscaped(makefile, "_moc_depend_filters", GetSafeProperty(target, "AUTOMOC_DEPEND_FILTERS")); - if (QtVersionGreaterOrEqual( - qtMajorVersion, GetQtMinorVersion(target, qtMajorVersion), 5, 8)) { + if (QtVersionGreaterOrEqual(digest.QtVersionMajor, digest.QtVersionMinor, 5, + 8)) { AddDefinitionEscaped( makefile, "_moc_predefs_cmd", makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND")); @@ -426,17 +373,16 @@ static void SetupAutoTargetMoc(cmGeneratorTarget const* target, AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs); // Configuration specific settings - for (std::vector::const_iterator li = configs.begin(); - li != configs.end(); ++li) { + for (const std::string& cfg : configs) { std::string configIncs; std::string configCompileDefs; - GetCompileDefinitionsAndDirectories(target, *li, configIncs, + GetCompileDefinitionsAndDirectories(target, cfg, configIncs, configCompileDefs); if (configIncs != incs) { - setup.configMocIncludes[*li] = configIncs; + setup.ConfigMocIncludes[cfg] = configIncs; } if (configCompileDefs != compileDefs) { - setup.configMocDefines[*li] = configCompileDefs; + setup.ConfigMocDefines[cfg] = configCompileDefs; } } } @@ -446,14 +392,14 @@ static void SetupAutoTargetMoc(cmGeneratorTarget const* target, std::string mocExec; std::string err; - if (qtMajorVersion == "5") { + 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 (qtMajorVersion == "4") { + } else if (digest.QtVersionMajor == "4") { cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::moc"); if (tgt != nullptr) { mocExec = SafeString(tgt->ImportedGetLocation("")); @@ -481,16 +427,15 @@ static void UicGetOpts(cmGeneratorTarget const* target, optString = cmJoin(opts, ";"); } -static void SetupAutoTargetUic(cmGeneratorTarget const* target, - std::string const& qtMajorVersion, +static void SetupAutoTargetUic(const cmQtAutoGenDigest& digest, std::string const& config, std::vector const& configs, - AutogenSetup& setup) + cmQtAutoGenSetup& setup) { - cmLocalGenerator* localGen = target->GetLocalGenerator(); + cmGeneratorTarget const* target = digest.Target; cmMakefile* makefile = target->Target->GetMakefile(); - AddDefinitionEscaped(makefile, "_uic_skip", setup.uicSkip); + AddDefinitionEscaped(makefile, "_uic_skip", setup.UicSkip); // Uic search paths { @@ -500,9 +445,8 @@ static void SetupAutoTargetUic(cmGeneratorTarget const* target, if (!usp.empty()) { cmSystemTools::ExpandListArgument(usp, uicSearchPaths); const std::string srcDir = makefile->GetCurrentSourceDirectory(); - for (std::vector::iterator it = uicSearchPaths.begin(); - it != uicSearchPaths.end(); ++it) { - *it = cmSystemTools::CollapseFullPath(*it, srcDir); + for (std::string& path : uicSearchPaths) { + path = cmSystemTools::CollapseFullPath(path, srcDir); } } } @@ -516,12 +460,11 @@ static void SetupAutoTargetUic(cmGeneratorTarget const* target, AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts); // Configuration specific settings - for (std::vector::const_iterator li = configs.begin(); - li != configs.end(); ++li) { + for (const std::string& cfg : configs) { std::string configUicOpts; - UicGetOpts(target, *li, configUicOpts); + UicGetOpts(target, cfg, configUicOpts); if (configUicOpts != uicOpts) { - setup.configUicOptions[*li] = configUicOpts; + setup.ConfigUicOptions[cfg] = configUicOpts; } } } @@ -532,21 +475,18 @@ static void SetupAutoTargetUic(cmGeneratorTarget const* target, { const std::string uiExt = "ui"; const std::vector& srcFiles = makefile->GetSourceFiles(); - for (std::vector::const_iterator fit = srcFiles.begin(); - fit != srcFiles.end(); ++fit) { - cmSourceFile* sf = *fit; + for (cmSourceFile* sf : srcFiles) { // sf->GetExtension() is only valid after sf->GetFullPath() ... const std::string& fPath = sf->GetFullPath(); if (sf->GetExtension() == uiExt) { // Check if the files has uic options - std::string uicOpts = sf->GetProperty("AUTOUIC_OPTIONS"); + std::string uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS"); if (!uicOpts.empty()) { const std::string absFile = cmsys::SystemTools::GetRealPath(fPath); // Check if file isn't skipped - if (setup.uicSkip.count(absFile) == 0) { + if (setup.UicSkip.count(absFile) == 0) { uiFileFiles.push_back(absFile); - cmSystemTools::ReplaceString(uicOpts, ";", - cmQtAutoGeneratorCommon::listSep); + cmSystemTools::ReplaceString(uicOpts, ";", cmQtAutoGen::listSep); uiFileOptions.push_back(uicOpts); } } @@ -562,14 +502,15 @@ static void SetupAutoTargetUic(cmGeneratorTarget const* target, std::string err; std::string uicExec; - if (qtMajorVersion == "5") { + 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 (qtMajorVersion == "4") { + } else if (digest.QtVersionMajor == "4") { cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::uic"); if (tgt != nullptr) { uicExec = SafeString(tgt->ImportedGetLocation("")); @@ -625,14 +566,16 @@ static void RccMergeOptions(std::vector& opts, const std::vector& fileOpts, bool isQt5) { - static const char* valueOptions[] = { "name", "root", "compress", - "threshold" }; + typedef std::vector::iterator Iter; + typedef std::vector::const_iterator CIter; + static const char* valueOptions[4] = { "name", "root", "compress", + "threshold" }; + std::vector extraOpts; - for (std::vector::const_iterator fit = fileOpts.begin(); - fit != fileOpts.end(); ++fit) { - std::vector::iterator existingIt = - std::find(opts.begin(), opts.end(), *fit); - if (existingIt != opts.end()) { + for (CIter fit = fileOpts.begin(), fitEnd = fileOpts.end(); fit != fitEnd; + ++fit) { + Iter existIt = std::find(opts.begin(), opts.end(), *fit); + if (existIt != opts.end()) { const char* optName = fit->c_str(); if (*optName == '-') { ++optName; @@ -644,10 +587,10 @@ static void RccMergeOptions(std::vector& opts, if ((optName != fit->c_str()) && std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), cmStrCmp(optName)) != cmArrayEnd(valueOptions)) { - const std::vector::iterator existValueIt(existingIt + 1); - const std::vector::const_iterator fileValueIt(fit + 1); - if ((existValueIt != opts.end()) && (fileValueIt != fileOpts.end())) { - *existValueIt = *fileValueIt; + const Iter existItNext(existIt + 1); + const CIter fitNext(fit + 1); + if ((existItNext != opts.end()) && (fitNext != fitEnd)) { + *existItNext = *fitNext; ++fit; } } @@ -655,73 +598,42 @@ static void RccMergeOptions(std::vector& opts, extraOpts.push_back(*fit); } } + // Append options opts.insert(opts.end(), extraOpts.begin(), extraOpts.end()); } -static void SetupAutoTargetRcc(cmGeneratorTarget const* target, - const std::string& qtMajorVersion, - const std::vector& srcFiles) +static void SetupAutoTargetRcc(const cmQtAutoGenDigest& digest) { + cmGeneratorTarget const* target = digest.Target; cmMakefile* makefile = target->Target->GetMakefile(); - const bool qtMajorVersion5 = (qtMajorVersion == "5"); - const std::string rccCommand = RccGetExecutable(target, qtMajorVersion); std::vector rccFiles; std::vector rccInputs; std::vector rccFileFiles; std::vector rccFileOptions; - std::vector rccOptionsTarget; - - cmSystemTools::ExpandListArgument(GetSafeProperty(target, "AUTORCC_OPTIONS"), - rccOptionsTarget); - - for (std::vector::const_iterator fileIt = srcFiles.begin(); - fileIt != srcFiles.end(); ++fileIt) { - cmSourceFile* sf = *fileIt; - // sf->GetExtension() is only valid after sf->GetFullPath() ... - const std::string& fPath = sf->GetFullPath(); - if ((sf->GetExtension() == "qrc") && - !sf->GetPropertyAsBool("SKIP_AUTOGEN") && - !sf->GetPropertyAsBool("SKIP_AUTORCC")) { - const std::string absFile = cmsys::SystemTools::GetRealPath(fPath); - // qrc file - rccFiles.push_back(absFile); - // qrc file entries - { - std::string entriesList = "{"; - // Read input file list only for non generated .qrc files. - if (!sf->GetPropertyAsBool("GENERATED")) { - std::string error; - std::vector files; - if (cmQtAutoGeneratorCommon::RccListInputs( - qtMajorVersion, rccCommand, absFile, files, &error)) { - entriesList += cmJoin(files, cmQtAutoGeneratorCommon::listSep); - } else { - cmSystemTools::Error(error.c_str()); - } - } - entriesList += "}"; - rccInputs.push_back(entriesList); - } - // rcc options for this qrc file - { - // Merged target and file options - std::vector rccOptions(rccOptionsTarget); - if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) { - std::vector optsVec; - cmSystemTools::ExpandListArgument(prop, optsVec); - RccMergeOptions(rccOptions, optsVec, qtMajorVersion5); - } - // Only store non empty options lists - if (!rccOptions.empty()) { - rccFileFiles.push_back(absFile); - rccFileOptions.push_back( - cmJoin(rccOptions, cmQtAutoGeneratorCommon::listSep)); - } + + for (const cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { + const std::string absFile = qrcDigest.QrcFile; + // Register file + rccFiles.push_back(absFile); + // Register (known) resource files + { + std::string entriesList = "{"; + if (!qrcDigest.Generated) { + entriesList += cmJoin(qrcDigest.Resources, cmQtAutoGen::listSep); } + entriesList += "}"; + rccInputs.push_back(entriesList); + } + // rcc options for this qrc file + if (!qrcDigest.Options.empty()) { + rccFileFiles.push_back(absFile); + rccFileOptions.push_back( + cmJoin(qrcDigest.Options, cmQtAutoGen::listSep)); } } - AddDefinitionEscaped(makefile, "_qt_rcc_executable", rccCommand); + AddDefinitionEscaped(makefile, "_qt_rcc_executable", + RccGetExecutable(target, digest.QtVersionMajor)); AddDefinitionEscaped(makefile, "_rcc_files", rccFiles); AddDefinitionEscaped(makefile, "_rcc_inputs", rccInputs); AddDefinitionEscaped(makefile, "_rcc_options_files", rccFileFiles); @@ -729,33 +641,23 @@ static void SetupAutoTargetRcc(cmGeneratorTarget const* target, } void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( - cmLocalGenerator* localGen, cmGeneratorTarget* target) + cmQtAutoGenDigest& digest) { + cmGeneratorTarget* target = digest.Target; cmMakefile* makefile = target->Target->GetMakefile(); + cmLocalGenerator* localGen = target->GetLocalGenerator(); cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator(); // Create a custom target for running generators at buildtime - const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC"); - const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC"); - const bool rccEnabled = target->GetPropertyAsBool("AUTORCC"); const bool multiConfig = AutogenMultiConfig(globalGen); const std::string autogenTargetName = GetAutogenTargetName(target); const std::string autogenBuildDir = GetAutogenTargetBuildDir(target); const std::string workingDirectory = cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory()); const std::vector suffixes = GetConfigurationSuffixes(makefile); - std::set autogenDependsSet; + std::set autogenDepends; std::vector autogenProvides; - 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; - } - // Remove build directories on cleanup AddCleanFile(makefile, autogenBuildDir); @@ -763,9 +665,8 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( { std::string base = GetAutogenTargetFilesDir(target); base += "/AutogenOldSettings"; - for (std::vector::const_iterator it = suffixes.begin(); - it != suffixes.end(); ++it) { - AddCleanFile(makefile, base + *it + ".cmake"); + for (const std::string& suffix : suffixes) { + AddCleanFile(makefile, (base + suffix).append(".cmake")); } } @@ -785,13 +686,13 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( std::string autogenComment; { std::vector toolNames; - if (mocEnabled) { + if (digest.MocEnabled) { toolNames.push_back("MOC"); } - if (uicEnabled) { + if (digest.UicEnabled) { toolNames.push_back("UIC"); } - if (rccEnabled) { + if (digest.RccEnabled) { toolNames.push_back("RCC"); } @@ -808,14 +709,14 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( } // Add moc compilation to generated files list - if (mocEnabled) { + if (digest.MocEnabled) { const std::string mocsComp = autogenBuildDir + "/mocs_compilation.cpp"; - AddGeneratedSource(target, mocsComp, cmQtAutoGeneratorCommon::MOC); + AddGeneratedSource(target, mocsComp, cmQtAutoGen::MOC); autogenProvides.push_back(mocsComp); } // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES - if (mocEnabled || uicEnabled) { + if (digest.MocEnabled || digest.UicEnabled) { std::string includeDir = autogenBuildDir + "/include"; if (multiConfig) { includeDir += "_$"; @@ -823,49 +724,12 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( target->AddIncludeDirectory(includeDir, true); } - // Add user defined autogen target dependencies - { - const std::string deps = GetSafeProperty(target, "AUTOGEN_TARGET_DEPENDS"); - if (!deps.empty()) { - std::vector extraDepends; - cmSystemTools::ExpandListArgument(deps, extraDepends); - autogenDependsSet.insert(extraDepends.begin(), extraDepends.end()); - } - } - // Add utility target dependencies to the autogen dependencies - { - const std::set& utils = target->Target->GetUtilities(); - for (std::set::const_iterator it = utils.begin(); - it != utils.end(); ++it) { - const std::string& targetName = *it; - if (makefile->FindTargetToUse(targetName) != nullptr) { - autogenDependsSet.insert(targetName); - } - } - } - // Add link library target dependencies to the autogen dependencies - { - const cmTarget::LinkLibraryVectorType& libVec = - target->Target->GetOriginalLinkLibraries(); - for (cmTarget::LinkLibraryVectorType::const_iterator it = libVec.begin(); - it != libVec.end(); ++it) { - const std::string& libName = it->first; - if (makefile->FindTargetToUse(libName) != nullptr) { - autogenDependsSet.insert(libName); - } - } - } - // Extract relevant source files - std::vector generatedSources; - std::vector> qrcSources; { const std::string qrcExt = "qrc"; std::vector srcFiles; target->GetConfigCommonSourceFiles(srcFiles); - for (std::vector::const_iterator fileIt = srcFiles.begin(); - fileIt != srcFiles.end(); ++fileIt) { - cmSourceFile* sf = *fileIt; + for (cmSourceFile* sf : srcFiles) { if (sf->GetPropertyAsBool("SKIP_AUTOGEN")) { continue; } @@ -873,26 +737,49 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( const std::string& fPath = sf->GetFullPath(); const std::string& ext = sf->GetExtension(); // Register generated files that will be scanned by moc or uic - if (mocEnabled || uicEnabled) { + if (digest.MocEnabled || digest.UicEnabled) { const cmSystemTools::FileFormat fileType = cmSystemTools::GetFileFormat(ext.c_str()); if ((fileType == cmSystemTools::CXX_FILE_FORMAT) || (fileType == cmSystemTools::HEADER_FILE_FORMAT)) { - if (sf->GetPropertyAsBool("GENERATED")) { - if ((mocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) || - (uicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) { - generatedSources.push_back( - cmsys::SystemTools::GetRealPath(fPath)); + const std::string absPath = cmsys::SystemTools::GetRealPath(fPath); + if ((digest.MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) || + (digest.UicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) { + // Register source + const bool generated = sf->GetPropertyAsBool("GENERATED"); + if (fileType == cmSystemTools::HEADER_FILE_FORMAT) { + if (generated) { + digest.HeadersGenerated.push_back(absPath); + } else { + digest.Headers.push_back(absPath); + } + } else { + if (generated) { + digest.SourcesGenerated.push_back(absPath); + } else { + digest.Sources.push_back(absPath); + } } } } } // Register rcc enabled files - if (rccEnabled && (ext == qrcExt) && + if (digest.RccEnabled && (ext == qrcExt) && !sf->GetPropertyAsBool("SKIP_AUTORCC")) { - qrcSources.push_back( - std::pair(cmsys::SystemTools::GetRealPath(fPath), - sf->GetPropertyAsBool("GENERATED"))); + // Register qrc file + { + cmQtAutoGenDigestQrc qrcDigest; + qrcDigest.QrcFile = cmsys::SystemTools::GetRealPath(fPath); + qrcDigest.Generated = sf->GetPropertyAsBool("GENERATED"); + // RCC options + { + const std::string opts = GetSafeProperty(sf, "AUTORCC_OPTIONS"); + if (!opts.empty()) { + cmSystemTools::ExpandListArgument(opts, qrcDigest.Options); + } + } + digest.Qrcs.push_back(std::move(qrcDigest)); + } } } // cmGeneratorTarget::GetConfigCommonSourceFiles computes the target's @@ -902,89 +789,176 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( target->ClearSourcesCache(); } - if (!generatedSources.empty()) { - for (std::vector::const_iterator it = - generatedSources.begin(); - it != generatedSources.end(); ++it) { - autogenDependsSet.insert(*it); + // Process GENERATED sources and headers + if (!digest.SourcesGenerated.empty() || !digest.HeadersGenerated.empty()) { + // Check status of policy CMP0071 + bool policyAccept = false; + bool policyWarn = false; + const cmPolicies::PolicyStatus CMP0071_status = + target->Makefile->GetPolicyStatus(cmPolicies::CMP0071); + switch (CMP0071_status) { + case cmPolicies::WARN: + policyWarn = true; + CM_FALLTHROUGH; + case cmPolicies::OLD: + // Ignore GENERATED file + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + // Process GENERATED file + policyAccept = true; + break; + } + + if (policyAccept) { + // Accept GENERATED sources + for (const std::string& absFile : digest.HeadersGenerated) { + digest.Headers.push_back(absFile); + } + for (const std::string& absFile : digest.SourcesGenerated) { + digest.Sources.push_back(absFile); + } + } else if (policyWarn) { + std::ostringstream ost; + ost << cmPolicies::GetPolicyWarning(cmPolicies::CMP0071) << "\n"; + ost << "AUTOMOC,AUTOUIC: Ignoring GENERATED source file(s):\n"; + for (const std::string& absFile : digest.HeadersGenerated) { + ost << " " << cmQtAutoGen::Quoted(absFile) << "\n"; + } + for (const std::string& absFile : digest.SourcesGenerated) { + ost << " " << cmQtAutoGen::Quoted(absFile) << "\n"; + } + makefile->IssueMessage(cmake::AUTHOR_WARNING, ost.str()); + } + // Depend on GENERATED sources even when they are not processed by AUTOGEN + for (const std::string& absFile : digest.HeadersGenerated) { + autogenDepends.insert(absFile); + } + for (const std::string& absFile : digest.SourcesGenerated) { + autogenDepends.insert(absFile); } } + // Sort headers and sources + std::sort(digest.Headers.begin(), digest.Headers.end()); + std::sort(digest.Sources.begin(), digest.Sources.end()); - if (!qrcSources.empty()) { - const std::string qtMajorVersion = GetQtMajorVersion(target); - const std::string rccCommand = RccGetExecutable(target, qtMajorVersion); + // Process qrc files + if (!digest.Qrcs.empty()) { + const bool QtV5 = (digest.QtVersionMajor == "5"); const cmFilePathChecksum fpathCheckSum(makefile); - for (std::vector>::const_iterator it = - qrcSources.begin(); - it != qrcSources.end(); ++it) { - const std::string& absFile = it->first; - - // Compose rcc output file name + const std::string rcc = RccGetExecutable(target, digest.QtVersionMajor); + // Target rcc options + std::vector optionsTarget; + cmSystemTools::ExpandListArgument( + GetSafeProperty(target, "AUTORCC_OPTIONS"), optionsTarget); + + for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { + // RCC output file name { - std::string rccBuildFile = autogenBuildDir + "/"; - rccBuildFile += fpathCheckSum.getPart(absFile); - rccBuildFile += "/qrc_"; - rccBuildFile += - cmsys::SystemTools::GetFilenameWithoutLastExtension(absFile); - rccBuildFile += ".cpp"; - - // Register rcc ouput file as generated - AddGeneratedSource(target, rccBuildFile, cmQtAutoGeneratorCommon::RCC); - // Register rcc ouput file as generated by the _autogen target - autogenProvides.push_back(rccBuildFile); + std::string rccFile = autogenBuildDir + "/"; + rccFile += fpathCheckSum.getPart(qrcDigest.QrcFile); + rccFile += "/qrc_"; + rccFile += cmsys::SystemTools::GetFilenameWithoutLastExtension( + qrcDigest.QrcFile); + rccFile += ".cpp"; + + AddGeneratedSource(target, rccFile, cmQtAutoGen::RCC); + autogenProvides.push_back(rccFile); + qrcDigest.RccFile = std::move(rccFile); } - - if (it->second) { - // Add generated qrc file to the dependencies - autogenDependsSet.insert(absFile); + // RCC options + { + std::vector opts = optionsTarget; + if (!qrcDigest.Options.empty()) { + RccMergeOptions(opts, qrcDigest.Options, QtV5); + } + qrcDigest.Options = std::move(opts); + } + // GENERATED or not + if (qrcDigest.Generated) { + // Add GENERATED qrc file to the dependencies + autogenDepends.insert(qrcDigest.QrcFile); } else { - // Run cmake again when .qrc file changes - makefile->AddCMakeDependFile(absFile); - // Add the qrc input files to the dependencies + // Add the resource files to the dependencies { std::string error; - std::vector extraDepends; - if (cmQtAutoGeneratorCommon::RccListInputs( - qtMajorVersion, rccCommand, absFile, extraDepends, &error)) { - autogenDependsSet.insert(extraDepends.begin(), extraDepends.end()); + if (cmQtAutoGen::RccListInputs(digest.QtVersionMajor, rcc, + qrcDigest.QrcFile, + qrcDigest.Resources, &error)) { + autogenDepends.insert(qrcDigest.Resources.begin(), + qrcDigest.Resources.end()); } else { cmSystemTools::Error(error.c_str()); } } + // Run cmake again when .qrc file changes + makefile->AddCMakeDependFile(qrcDigest.QrcFile); + } + } + } + + // Add user defined autogen target dependencies + { + const std::string deps = GetSafeProperty(target, "AUTOGEN_TARGET_DEPENDS"); + if (!deps.empty()) { + std::vector extraDeps; + cmSystemTools::ExpandListArgument(deps, extraDeps); + autogenDepends.insert(extraDeps.begin(), extraDeps.end()); + } + } + // Add utility target dependencies to the autogen target dependencies + { + const std::set& utils = target->Target->GetUtilities(); + for (const std::string& targetName : utils) { + if (makefile->FindTargetToUse(targetName) != nullptr) { + autogenDepends.insert(targetName); + } + } + } + // Add link library target dependencies to the autogen target dependencies + { + const auto& libVec = target->Target->GetOriginalLinkLibraries(); + for (const auto& item : libVec) { + if (makefile->FindTargetToUse(item.first) != nullptr) { + autogenDepends.insert(item.first); } } } // Convert std::set to std::vector - const std::vector autogenDepends(autogenDependsSet.begin(), - autogenDependsSet.end()); - // Disable PRE_BUILD on demand + const std::vector depends(autogenDepends.begin(), + autogenDepends.end()); + autogenDepends.clear(); + + // 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) { - if (!generatedSources.empty() || !qrcSources.empty()) { - // - Cannot use PRE_BUILD with generated files - // - Cannot use PRE_BUILD because the resource files themselves - // may not be sources within the target so VS may not know the - // target needs to re-build at all. - usePRE_BUILD = false; - } - if (usePRE_BUILD) { - // If the autogen target depends on an other target don't use PRE_BUILD - for (std::vector::const_iterator it = - autogenDepends.begin(); - it != autogenDepends.end(); ++it) { - if (makefile->FindTargetToUse(*it) != nullptr) { - usePRE_BUILD = false; - break; - } + // - Cannot use PRE_BUILD with GENERATED qrc files because the + // resource files themselves may not be sources within the target + // so VS may not know the target needs to re-build at all. + for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { + if (qrcDigest.Generated) { + usePRE_BUILD = false; + break; } } } + // Create the autogen target/command if (usePRE_BUILD) { // 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. - std::vector no_output; - cmCustomCommand cc(makefile, no_output, autogenProvides, autogenDepends, + const std::vector no_output; + cmCustomCommand cc(makefile, no_output, autogenProvides, depends, commandLines, autogenComment.c_str(), workingDirectory.c_str()); cc.SetEscapeOldStyle(false); @@ -993,7 +967,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( } else { cmTarget* autogenTarget = makefile->AddUtilityCommand( autogenTargetName, true, workingDirectory.c_str(), - /*byproducts=*/autogenProvides, autogenDepends, commandLines, false, + /*byproducts=*/autogenProvides, depends, commandLines, false, autogenComment.c_str()); localGen->AddGeneratorTarget( @@ -1009,7 +983,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( } // Inherit FOLDER property from target (#13688) if (autogenFolder == nullptr) { - autogenFolder = target->Target->GetProperty("FOLDER"); + autogenFolder = SafeString(target->Target->GetProperty("FOLDER")); } if ((autogenFolder != nullptr) && (*autogenFolder != '\0')) { autogenTarget->SetProperty("FOLDER", autogenFolder); @@ -1022,8 +996,9 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( } void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( - cmGeneratorTarget const* target) + const cmQtAutoGenDigest& digest) { + cmGeneratorTarget const* target = digest.Target; cmMakefile* makefile = target->Target->GetMakefile(); // forget the variables added here afterwards again: @@ -1037,43 +1012,34 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( // Configuration suffixes std::map configSuffix; if (AutogenMultiConfig(target->GetGlobalGenerator())) { - for (std::vector::const_iterator it = configs.begin(); - it != configs.end(); ++it) { - configSuffix[*it] = "_" + *it; + for (const std::string& cfg : configs) { + configSuffix[cfg] = "_" + cfg; } } // Configurations settings buffers - AutogenSetup setup; + cmQtAutoGenSetup setup; // Basic setup + AddDefinitionEscaped(makefile, "_build_dir", + GetAutogenTargetBuildDir(target)); + AddDefinitionEscaped(makefile, "_qt_version_major", digest.QtVersionMajor); + AddDefinitionEscaped(makefile, "_qt_version_minor", digest.QtVersionMinor); + AddDefinitionEscaped(makefile, "_sources", digest.Sources); + AddDefinitionEscaped(makefile, "_headers", digest.Headers); { - const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC"); - const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC"); - const bool rccEnabled = target->GetPropertyAsBool("AUTORCC"); - const std::string qtMajorVersion = GetQtMajorVersion(target); - { - std::vector srcFiles; - target->GetConfigCommonSourceFiles(srcFiles); - if (mocEnabled || uicEnabled) { - SetupAcquireScanFiles(target, mocEnabled, uicEnabled, srcFiles, setup); - if (mocEnabled) { - SetupAutoTargetMoc(target, qtMajorVersion, config, configs, setup); - } - if (uicEnabled) { - SetupAutoTargetUic(target, qtMajorVersion, config, configs, setup); - } + if (digest.MocEnabled || digest.UicEnabled) { + SetupAcquireSkipFiles(digest, setup); + if (digest.MocEnabled) { + SetupAutoTargetMoc(digest, config, configs, setup); } - if (rccEnabled) { - SetupAutoTargetRcc(target, qtMajorVersion, srcFiles); + if (digest.UicEnabled) { + SetupAutoTargetUic(digest, config, configs, setup); } } - - AddDefinitionEscaped(makefile, "_build_dir", - GetAutogenTargetBuildDir(target)); - AddDefinitionEscaped(makefile, "_qt_version_major", qtMajorVersion); - AddDefinitionEscaped(makefile, "_sources", setup.sources); - AddDefinitionEscaped(makefile, "_headers", setup.headers); + if (digest.RccEnabled) { + SetupAutoTargetRcc(digest); + } } // Generate info file @@ -1086,8 +1052,8 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( } // Append custom definitions to info file on demand - if (!configSuffix.empty() || !setup.configMocDefines.empty() || - !setup.configMocIncludes.empty() || !setup.configUicOptions.empty()) { + if (!configSuffix.empty() || !setup.ConfigMocDefines.empty() || + !setup.ConfigMocIncludes.empty() || !setup.ConfigUicOptions.empty()) { // Ensure we have write permission in case .in was read-only. mode_t perm = 0; @@ -1105,38 +1071,26 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( cmsys::ofstream ofs(infoFile.c_str(), std::ios::app); if (ofs) { ofs << "# Configuration specific options\n"; - for (std::map::iterator - it = configSuffix.begin(), - end = configSuffix.end(); - it != end; ++it) { - ofs << "set(AM_CONFIG_SUFFIX_" << it->first << " " - << cmOutputConverter::EscapeForCMake(it->second) << ")\n"; + for (const auto& item : configSuffix) { + ofs << "set(AM_CONFIG_SUFFIX_" << item.first << " " + << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; } - for (std::map::iterator - it = setup.configMocDefines.begin(), - end = setup.configMocDefines.end(); - it != end; ++it) { - ofs << "set(AM_MOC_DEFINITIONS_" << it->first << " " - << cmOutputConverter::EscapeForCMake(it->second) << ")\n"; + for (const auto& item : setup.ConfigMocDefines) { + ofs << "set(AM_MOC_DEFINITIONS_" << item.first << " " + << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; } - for (std::map::iterator - it = setup.configMocIncludes.begin(), - end = setup.configMocIncludes.end(); - it != end; ++it) { - ofs << "set(AM_MOC_INCLUDES_" << it->first << " " - << cmOutputConverter::EscapeForCMake(it->second) << ")\n"; + for (const auto& item : setup.ConfigMocIncludes) { + ofs << "set(AM_MOC_INCLUDES_" << item.first << " " + << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; } - for (std::map::iterator - it = setup.configUicOptions.begin(), - end = setup.configUicOptions.end(); - it != end; ++it) { - ofs << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " " - << cmOutputConverter::EscapeForCMake(it->second) << ")\n"; + for (const auto& item : setup.ConfigUicOptions) { + ofs << "set(AM_UIC_TARGET_OPTIONS_" << item.first << " " + << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; } } else { // File open error std::string error = "Internal CMake error when trying to open file: "; - error += cmQtAutoGeneratorCommon::Quoted(infoFile); + error += cmQtAutoGen::Quoted(infoFile); error += " for writing."; cmSystemTools::Error(error.c_str()); } diff --git a/Source/cmQtAutoGeneratorInitializer.h b/Source/cmQtAutoGeneratorInitializer.h index 48ae70e..1264ca5 100644 --- a/Source/cmQtAutoGeneratorInitializer.h +++ b/Source/cmQtAutoGeneratorInitializer.h @@ -4,16 +4,21 @@ #define cmQtAutoGeneratorInitializer_h #include "cmConfigure.h" // IWYU pragma: keep +#include "cmQtAutoGenDigest.h" + +#include class cmGeneratorTarget; -class cmLocalGenerator; class cmQtAutoGeneratorInitializer { public: - static void InitializeAutogenTarget(cmLocalGenerator* localGen, - cmGeneratorTarget* target); - static void SetupAutoGenerateTarget(cmGeneratorTarget const* target); + static std::string GetQtMajorVersion(cmGeneratorTarget const* target); + static std::string GetQtMinorVersion(cmGeneratorTarget const* target, + const std::string& qtVersionMajor); + + static void InitializeAutogenTarget(cmQtAutoGenDigest& digest); + static void SetupAutoGenerateTarget(cmQtAutoGenDigest const& digest); }; #endif diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index d7f1ea7..e9929f4 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -1,11 +1,12 @@ /* 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 "cmQtAutoGeneratorCommon.h" #include "cmsys/FStream.hxx" #include "cmsys/Terminal.h" #include +#include #include #include #include @@ -39,23 +40,22 @@ static const char* SettingsKeyRcc = "AM_RCC_SETTINGS_HASH"; inline static std::string Quoted(const std::string& text) { - return cmQtAutoGeneratorCommon::Quoted(text); + return cmQtAutoGen::Quoted(text); } static std::string QuotedCommand(const std::vector& command) { std::string res; - for (std::vector::const_iterator cit = command.begin(); - cit != command.end(); ++cit) { + for (const std::string& item : command) { if (!res.empty()) { res.push_back(' '); } - const std::string cesc = Quoted(*cit); - if (cit->empty() || (cesc.size() > (cit->size() + 2)) || + const std::string cesc = Quoted(item); + if (item.empty() || (cesc.size() > (item.size() + 2)) || (cesc.find(' ') != std::string::npos)) { res += cesc; } else { - res += *cit; + res += item; } } return res; @@ -136,9 +136,8 @@ static bool FileNameIsUnique(const std::string& filePath, { size_t count(0); const std::string fileName = cmsys::SystemTools::GetFilenameName(filePath); - for (std::map::const_iterator si = fileMap.begin(); - si != fileMap.end(); ++si) { - if (cmsys::SystemTools::GetFilenameName(si->first) == fileName) { + for (const auto& item : fileMap) { + if (cmsys::SystemTools::GetFilenameName(item.first) == fileName) { ++count; if (count > 1) { return false; @@ -191,31 +190,13 @@ static std::string JoinOptionsMap( const std::map& opts) { std::string result; - for (std::map::const_iterator it = opts.begin(); - it != opts.end(); ++it) { - if (it != opts.begin()) { - result += cmQtAutoGeneratorCommon::listSep; + for (const auto& item : opts) { + if (!result.empty()) { + result += cmQtAutoGen::listSep; } - result += it->first; + result += item.first; result += "==="; - result += it->second; - } - return result; -} - -static std::string JoinExts(const std::vector& lst) -{ - std::string result; - if (!lst.empty()) { - const std::string separator = ","; - for (std::vector::const_iterator it = lst.begin(); - it != lst.end(); ++it) { - if (it != lst.begin()) { - result += separator; - } - result += '.'; - result += *it; - } + result += item.second; } return result; } @@ -425,11 +406,9 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( { std::vector MocMacroNames; InfoGet(makefile, "AM_MOC_MACRO_NAMES", MocMacroNames); - for (std::vector::const_iterator dit = - MocMacroNames.begin(); - dit != MocMacroNames.end(); ++dit) { - this->MocMacroFilters.push_back( - MocMacroFilter(*dit, "[^a-zA-Z0-9_]" + *dit + "[^a-zA-Z0-9_]")); + for (const std::string& item : MocMacroNames) { + this->MocMacroFilters.emplace_back( + item, ("[^a-zA-Z0-9_]" + item).append("[^a-zA-Z0-9_]")); } } { @@ -443,9 +422,10 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( } // Insert user defined dependency filters if ((mocDependFilters.size() % 2) == 0) { - for (std::vector::const_iterator dit = - mocDependFilters.begin(); - dit != mocDependFilters.end(); dit += 2) { + for (std::vector::const_iterator + dit = mocDependFilters.begin(), + ditEnd = mocDependFilters.end(); + dit != ditEnd; dit += 2) { if (!this->MocDependFilterPush(*dit, *(dit + 1))) { return false; } @@ -478,8 +458,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( fileIt = uicFilesVec.begin(), optionIt = uicOptionsVec.begin(); fileIt != uicFilesVec.end(); ++fileIt, ++optionIt) { - cmSystemTools::ReplaceString(*optionIt, - cmQtAutoGeneratorCommon::listSep, ";"); + cmSystemTools::ReplaceString(*optionIt, cmQtAutoGen::listSep, ";"); this->UicOptions[*fileIt] = *optionIt; } } else { @@ -506,8 +485,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( optionIt = rccOptionsVec.begin(); fileIt != rccFilesVec.end(); ++fileIt, ++optionIt) { // Replace item separator - cmSystemTools::ReplaceString(*optionIt, - cmQtAutoGeneratorCommon::listSep, ";"); + cmSystemTools::ReplaceString(*optionIt, cmQtAutoGen::listSep, ";"); this->RccOptions[*fileIt] = *optionIt; } } else { @@ -529,8 +507,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( // Remove braces *inputIt = inputIt->substr(1, inputIt->size() - 2); // Replace item separator - cmSystemTools::ReplaceString(*inputIt, - cmQtAutoGeneratorCommon::listSep, ";"); + cmSystemTools::ReplaceString(*inputIt, cmQtAutoGen::listSep, ";"); std::vector rccInputFiles; cmSystemTools::ExpandListArgument(*inputIt, rccInputFiles); this->RccInputs[*fileIt] = rccInputFiles; @@ -629,7 +606,7 @@ bool cmQtAutoGenerators::SettingsFileWrite() SettingAppend(settings, SettingsKeyUic, this->SettingsStringUic); SettingAppend(settings, SettingsKeyRcc, this->SettingsStringRcc); // Write settings file - if (!this->FileWrite("AutoGen", this->SettingsFile, settings)) { + if (!this->FileWrite(cmQtAutoGen::GEN, this->SettingsFile, settings)) { this->LogError("AutoGen: Error: Could not write old settings file " + Quoted(this->SettingsFile)); // Remove old settings file to trigger a full rebuild on the next run @@ -679,14 +656,14 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile) this->MocIncludePaths.reserve(includes.size()); // Append project directories only { - const char* movePaths[2] = { this->ProjectBinaryDir.c_str(), - this->ProjectSourceDir.c_str() }; - for (const char* const* mpit = cmArrayBegin(movePaths); - mpit != cmArrayEnd(movePaths); ++mpit) { + const std::array movePaths = { + { &this->ProjectBinaryDir, &this->ProjectSourceDir } + }; + for (const std::string* ppath : movePaths) { std::list::iterator it = includes.begin(); while (it != includes.end()) { const std::string& path = *it; - if (cmsys::SystemTools::StringStartsWith(path, *mpit)) { + if (cmSystemTools::StringStartsWith(path, ppath->c_str())) { this->MocIncludePaths.push_back(path); it = includes.erase(it); } else { @@ -702,10 +679,7 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile) // Compose moc includes list { std::set frameworkPaths; - for (std::vector::const_iterator it = - this->MocIncludePaths.begin(); - it != this->MocIncludePaths.end(); ++it) { - const std::string& path = *it; + for (const std::string& path : this->MocIncludePaths) { this->MocIncludes.push_back("-I" + path); // Extract framework path if (cmHasLiteralSuffix(path, ".framework/Headers")) { @@ -718,10 +692,9 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile) } } // Append framework includes - for (std::set::const_iterator it = frameworkPaths.begin(); - it != frameworkPaths.end(); ++it) { + for (const std::string& path : frameworkPaths) { this->MocIncludes.push_back("-F"); - this->MocIncludes.push_back(*it); + this->MocIncludes.push_back(path); } } } @@ -757,28 +730,23 @@ bool cmQtAutoGenerators::RunAutogen() std::set uicHeaderFiles; // Parse sources - for (std::vector::const_iterator it = this->Sources.begin(); - it != this->Sources.end(); ++it) { - const std::string& absFilename = cmsys::SystemTools::GetRealPath(*it); + for (const std::string& src : this->Sources) { // Parse source file for MOC/UIC - if (!this->ParseSourceFile(absFilename, mocsIncluded, mocDepends, - uisIncluded, this->MocRelaxedMode)) { + if (!this->ParseSourceFile(src, mocsIncluded, mocDepends, uisIncluded, + this->MocRelaxedMode)) { return false; } // Find additional headers - this->SearchHeadersForSourceFile(absFilename, mocHeaderFiles, - uicHeaderFiles); + this->SearchHeadersForSourceFile(src, mocHeaderFiles, uicHeaderFiles); } // Parse headers - for (std::vector::const_iterator it = this->Headers.begin(); - it != this->Headers.end(); ++it) { - const std::string& headerName = cmsys::SystemTools::GetRealPath(*it); - if (!this->MocSkip(headerName)) { - mocHeaderFiles.insert(headerName); + for (const std::string& hdr : this->Headers) { + if (!this->MocSkip(hdr)) { + mocHeaderFiles.insert(hdr); } - if (!this->UicSkip(headerName)) { - uicHeaderFiles.insert(headerName); + if (!this->UicSkip(hdr)) { + uicHeaderFiles.insert(hdr); } } if (!this->ParseHeaders(mocHeaderFiles, uicHeaderFiles, mocsIncluded, @@ -807,10 +775,7 @@ bool cmQtAutoGenerators::RunAutogen() bool cmQtAutoGenerators::MocRequired(const std::string& contentText, std::string* macroName) { - for (std::vector::iterator fit = - this->MocMacroFilters.begin(); - fit != this->MocMacroFilters.end(); ++fit) { - MocMacroFilter& filter = *fit; + for (MocMacroFilter& filter : this->MocMacroFilters) { // Run a simple find string operation before the expensive // regular expression check if (contentText.find(filter.first) != std::string::npos) { @@ -830,10 +795,7 @@ void cmQtAutoGenerators::MocFindDepends( const std::string& absFilename, const std::string& contentText, std::map>& mocDepends) { - for (std::vector::iterator fit = - this->MocDependFilters.begin(); - fit != this->MocDependFilters.end(); ++fit) { - MocDependFilter& filter = *fit; + for (MocDependFilter& filter : this->MocDependFilters) { // Run a simple find string operation before the expensive // regular expression check if (contentText.find(filter.key) != std::string::npos) { @@ -1008,9 +970,8 @@ bool cmQtAutoGenerators::MocParseSourceContent( ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n" << "The file includes the moc file " << Quoted(incString) << ", but could not find header " - << Quoted(incRealBasename + "{" + - JoinExts(this->HeaderExtensions) + "}"); - ; + << Quoted(incRealBasename + ".{" + + cmJoin(this->HeaderExtensions, ",") + "}"); this->LogError(ost.str()); return false; } @@ -1166,19 +1127,19 @@ void cmQtAutoGenerators::SearchHeadersForSourceFile( const std::string& absFilename, std::set& mocHeaderFiles, std::set& uicHeaderFiles) const { - std::string basepaths[2]; + std::array basepaths; { std::string bpath = SubDirPrefix(absFilename); bpath += cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); // search for default header files and private header files basepaths[0] = bpath; - basepaths[1] = bpath + "_p"; + basepaths[1] = bpath; + basepaths[1] += "_p"; } - for (const std::string* bpit = cmArrayBegin(basepaths); - bpit != cmArrayEnd(basepaths); ++bpit) { + for (const std::string& bPath : basepaths) { std::string headerName; - if (this->FindHeader(headerName, *bpit)) { + if (this->FindHeader(headerName, bPath)) { // Moc headers if (!this->MocSkip(absFilename) && !this->MocSkip(headerName)) { mocHeaderFiles.insert(headerName); @@ -1205,9 +1166,7 @@ bool cmQtAutoGenerators::ParseHeaders( headerFiles.insert(mocHeaderFiles.begin(), mocHeaderFiles.end()); headerFiles.insert(uicHeaderFiles.begin(), uicHeaderFiles.end()); - for (std::set::const_iterator hIt = headerFiles.begin(); - hIt != headerFiles.end(); ++hIt) { - const std::string& headerName = *hIt; + for (const std::string& headerName : headerFiles) { std::string contentText; if (ReadAll(contentText, headerName)) { // Parse header content for MOC @@ -1276,10 +1235,8 @@ bool cmQtAutoGenerators::MocGenerateAll( cmd.insert(cmd.end(), this->MocIncludes.begin(), this->MocIncludes.end()); // Add definitions - for (std::vector::const_iterator it = - this->MocDefinitions.begin(); - it != this->MocDefinitions.end(); ++it) { - cmd.push_back("-D" + (*it)); + for (const std::string& def : this->MocDefinitions) { + cmd.push_back("-D" + def); } // Add options cmd.insert(cmd.end(), this->MocOptions.begin(), @@ -1298,7 +1255,8 @@ bool cmQtAutoGenerators::MocGenerateAll( } // (Re)write predefs file only on demand if (this->FileDiffers(this->MocPredefsFileAbs, output)) { - if (this->FileWrite("AutoMoc", this->MocPredefsFileAbs, output)) { + if (this->FileWrite(cmQtAutoGen::MOC, this->MocPredefsFileAbs, + output)) { this->MocPredefsChanged = true; } else { return false; @@ -1356,7 +1314,8 @@ bool cmQtAutoGenerators::MocGenerateAll( if (this->Verbose) { this->LogBold("Generating MOC compilation " + this->MocCompFileRel); } - if (!this->FileWrite("AutoMoc", this->MocCompFileAbs, automocSource)) { + if (!this->FileWrite(cmQtAutoGen::MOC, this->MocCompFileAbs, + automocSource)) { return false; } } else if (mocCompFileGenerated) { @@ -1411,7 +1370,7 @@ bool cmQtAutoGenerators::MocGenerateFile( } // Make sure the parent directory exists - if (this->MakeParentDirectory("AutoMoc", mocFileAbs)) { + if (this->MakeParentDirectory(cmQtAutoGen::MOC, mocFileAbs)) { // Compose moc command std::vector cmd; cmd.push_back(this->MocExecutable); @@ -1419,10 +1378,8 @@ bool cmQtAutoGenerators::MocGenerateFile( cmd.insert(cmd.end(), this->MocIncludes.begin(), this->MocIncludes.end()); // Add definitions - for (std::vector::const_iterator it = - this->MocDefinitions.begin(); - it != this->MocDefinitions.end(); ++it) { - cmd.push_back("-D" + (*it)); + for (const std::string& def : this->MocDefinitions) { + cmd.push_back("-D" + def); } // Add options cmd.insert(cmd.end(), this->MocOptions.begin(), this->MocOptions.end()); @@ -1470,7 +1427,11 @@ bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile, std::vector testFiles; // Collect search paths list { - const std::string searchFileFull = searchPath + searchFile; + std::string searchFileFull; + if (!searchPath.empty()) { + searchFileFull = searchPath; + searchFileFull += searchFile; + } // Vicinity of the source { const std::string sourcePath = SubDirPrefix(sourceFile); @@ -1481,25 +1442,19 @@ bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile, } // AUTOUIC search paths if (!this->UicSearchPaths.empty()) { - for (std::vector::const_iterator iit = - this->UicSearchPaths.begin(); - iit != this->UicSearchPaths.end(); ++iit) { - testFiles.push_back(*iit + "/" + searchFile); + for (const std::string& sPath : this->UicSearchPaths) { + testFiles.push_back((sPath + "/").append(searchFile)); } if (!searchPath.empty()) { - for (std::vector::const_iterator iit = - this->UicSearchPaths.begin(); - iit != this->UicSearchPaths.end(); ++iit) { - testFiles.push_back(*iit + "/" + searchFileFull); + for (const std::string& sPath : this->UicSearchPaths) { + testFiles.push_back((sPath + "/").append(searchFileFull)); } } } } // Search for the .ui file! - for (std::vector::const_iterator iit = testFiles.begin(); - iit != testFiles.end(); ++iit) { - const std::string& testFile = *iit; + for (const std::string& testFile : testFiles) { if (cmsys::SystemTools::FileExists(testFile.c_str())) { absFile = cmsys::SystemTools::GetRealPath(testFile); success = true; @@ -1512,9 +1467,8 @@ bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile, std::ostringstream ost; ost << "AutoUic: Error: " << Quoted(sourceFile) << "\n"; ost << "Could not find " << Quoted(searchFile) << " in\n"; - for (std::vector::const_iterator iit = testFiles.begin(); - iit != testFiles.end(); ++iit) { - ost << " " << Quoted(*iit) << "\n"; + for (const std::string& testFile : testFiles) { + ost << " " << Quoted(testFile) << "\n"; } this->LogError(ost.str()); } @@ -1542,16 +1496,18 @@ bool cmQtAutoGenerators::UicGenerateAll( const std::vector& sourceIncs(sit->second); // insert new source/destination map std::map& uiGenMap = sourceGenMap[source]; - for (std::vector::const_iterator uit = sourceIncs.begin(); - uit != sourceIncs.end(); ++uit) { + for (const std::string& inc : sourceIncs) { // Remove ui_ from the begin filename by substr() - const std::string uiBasePath = SubDirPrefix(*uit); + const std::string uiBasePath = SubDirPrefix(inc); const std::string uiBaseName = - cmsys::SystemTools::GetFilenameWithoutLastExtension(*uit).substr(3); + cmsys::SystemTools::GetFilenameWithoutLastExtension(inc).substr(3); const std::string uiFileName = uiBaseName + ".ui"; std::string uiInputFile; if (UicFindIncludedFile(uiInputFile, source, uiBasePath, uiFileName)) { - std::string uiOutputFile = uiBasePath + "ui_" + uiBaseName + ".h"; + std::string uiOutputFile = uiBasePath; + uiOutputFile += "ui_"; + uiOutputFile += uiBaseName; + uiOutputFile += ".h"; cmSystemTools::ReplaceString(uiOutputFile, "..", "__"); uiGenMap[uiInputFile] = uiOutputFile; testMap[uiInputFile] = uiOutputFile; @@ -1575,14 +1531,9 @@ bool cmQtAutoGenerators::UicGenerateAll( } // generate ui files - for (std::map>::const_iterator it = - sourceGenMap.begin(); - it != sourceGenMap.end(); ++it) { - for (std::map::const_iterator sit = - it->second.begin(); - sit != it->second.end(); ++sit) { - if (!this->UicGenerateFile(it->first, sit->first, sit->second)) { + for (const auto& srcItem : sourceGenMap) { + for (const auto& item : srcItem.second) { + if (!this->UicGenerateFile(srcItem.first, item.first, item.second)) { if (this->UicRunFailed) { return false; } @@ -1618,7 +1569,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, } // Make sure the parent directory exists - if (this->MakeParentDirectory("AutoUic", uicFileAbs)) { + if (this->MakeParentDirectory(cmQtAutoGen::UIC, uicFileAbs)) { // Compose uic command std::vector cmd; cmd.push_back(this->UicExecutable); @@ -1674,14 +1625,8 @@ bool cmQtAutoGenerators::RccGenerateAll() { const std::string qrcPrefix = "qrc_"; const std::string qrcSuffix = this->ConfigSuffix + ".cpp"; - for (std::vector::const_iterator si = - this->RccSources.begin(); - si != this->RccSources.end(); ++si) { - const std::string ext = - cmsys::SystemTools::GetFilenameLastExtension(*si); - if (ext == ".qrc") { - qrcGenMap[*si] = this->ChecksumedPath(*si, qrcPrefix, qrcSuffix); - } + for (const std::string& src : this->RccSources) { + qrcGenMap[src] = this->ChecksumedPath(src, qrcPrefix, qrcSuffix); } } @@ -1699,11 +1644,9 @@ bool cmQtAutoGenerators::RccGenerateAll() } // generate qrc files - for (std::map::const_iterator si = - qrcGenMap.begin(); - si != qrcGenMap.end(); ++si) { - bool unique = FileNameIsUnique(si->first, qrcGenMap); - if (!this->RccGenerateFile(si->first, si->second, unique)) { + for (const auto& item : qrcGenMap) { + bool unique = FileNameIsUnique(item.first, qrcGenMap); + if (!this->RccGenerateFile(item.first, item.second, unique)) { if (this->RccRunFailed) { return false; } @@ -1735,9 +1678,9 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, if (files->empty()) { // Read input file list from qrc file std::string error; - if (cmQtAutoGeneratorCommon::RccListInputs( - this->QtMajorVersion, this->RccExecutable, rccInputFile, - readFiles, &error)) { + if (cmQtAutoGen::RccListInputs(this->QtMajorVersion, + this->RccExecutable, rccInputFile, + readFiles, &error)) { files = &readFiles; } else { files = nullptr; @@ -1747,9 +1690,8 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, } // Test if any input file is newer than the build file if (files != nullptr) { - for (std::vector::const_iterator it = files->begin(); - it != files->end(); ++it) { - if (FileAbsentOrOlder(rccBuildFile, *it)) { + for (const std::string& file : *files) { + if (FileAbsentOrOlder(rccBuildFile, file)) { generateRcc = true; break; } @@ -1765,7 +1707,7 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, } // Make sure the parent directory exists - if (this->MakeParentDirectory("AutoRcc", rccBuildFile)) { + if (this->MakeParentDirectory(cmQtAutoGen::RCC, rccBuildFile)) { // Compose symbol name std::string symbolName = cmsys::SystemTools::GetFilenameWithoutLastExtension(rccInputFile); @@ -1836,7 +1778,7 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, if (this->Verbose) { this->LogBold("Generating RCC wrapper " + wrapperFileRel); } - if (!this->FileWrite("AutoRcc", wrapperFileAbs, content)) { + if (!this->FileWrite(cmQtAutoGen::RCC, wrapperFileAbs, content)) { // Error rccGenerated = false; this->RccRunFailed = true; @@ -1857,8 +1799,6 @@ void cmQtAutoGenerators::LogErrorNameCollision( const std::string& message, const std::multimap& collisions) const { - typedef std::multimap::const_iterator Iter; - std::ostringstream ost; // Add message if (!message.empty()) { @@ -1868,8 +1808,8 @@ void cmQtAutoGenerators::LogErrorNameCollision( } } // Append collision list - for (Iter it = collisions.begin(); it != collisions.end(); ++it) { - ost << it->first << " : " << it->second << '\n'; + for (const auto& item : collisions) { + ost << " " << item.first << " : " << item.second << '\n'; } this->LogError(ost.str()); } @@ -1968,15 +1908,15 @@ std::string cmQtAutoGenerators::ChecksumedPath( * @brief Generates the parent directory of the given file on demand * @return True on success */ -bool cmQtAutoGenerators::MakeParentDirectory(const char* logPrefix, - const std::string& filename) const +bool cmQtAutoGenerators::MakeParentDirectory( + cmQtAutoGen::GeneratorType genType, const std::string& filename) const { bool success = true; const std::string dirName = cmSystemTools::GetFilenamePath(filename); if (!dirName.empty()) { success = cmsys::SystemTools::MakeDirectory(dirName); if (!success) { - std::string error = logPrefix; + std::string error = cmQtAutoGen::GeneratorName(genType); error += ": Error: Parent directory creation failed for "; error += Quoted(filename); this->LogError(error); @@ -1998,26 +1938,28 @@ bool cmQtAutoGenerators::FileDiffers(const std::string& filename, return differs; } -bool cmQtAutoGenerators::FileWrite(const char* logPrefix, +bool cmQtAutoGenerators::FileWrite(cmQtAutoGen::GeneratorType genType, const std::string& filename, const std::string& content) { std::string error; // Make sure the parent directory exists - if (this->MakeParentDirectory(logPrefix, filename)) { + if (this->MakeParentDirectory(genType, filename)) { cmsys::ofstream outfile; outfile.open(filename.c_str(), std::ios::trunc); if (outfile) { outfile << content; // Check for write errors if (!outfile.good()) { - error = logPrefix; - error += ": Error writing "; + error = cmQtAutoGen::GeneratorName(genType); + error += ": Error: File writing failed\n"; + error += " "; error += Quoted(filename); } } else { - error = logPrefix; - error = ": Error opening "; + error = cmQtAutoGen::GeneratorName(genType); + error += ": Error: Opening file for writing failed\n"; + error += " "; error += Quoted(filename); } } @@ -2055,12 +1997,10 @@ bool cmQtAutoGenerators::RunCommand(const std::vector& command, bool cmQtAutoGenerators::FindHeader(std::string& header, const std::string& testBasePath) const { - for (std::vector::const_iterator ext = - this->HeaderExtensions.begin(); - ext != this->HeaderExtensions.end(); ++ext) { + for (const std::string& ext : this->HeaderExtensions) { std::string testFilePath(testBasePath); - testFilePath += '.'; - testFilePath += (*ext); + testFilePath.push_back('.'); + testFilePath += ext; if (cmsys::SystemTools::FileExists(testFilePath.c_str())) { header = testFilePath; return true; @@ -2076,10 +2016,10 @@ std::string cmQtAutoGenerators::MocFindHeader( // Search in vicinity of the source if (!this->FindHeader(header, sourcePath + includeBase)) { // Search in include directories - for (std::vector::const_iterator iit = - this->MocIncludePaths.begin(); - iit != this->MocIncludePaths.end(); ++iit) { - const std::string fullPath = ((*iit) + '/' + includeBase); + for (const std::string& path : this->MocIncludePaths) { + std::string fullPath = path; + fullPath.push_back('/'); + fullPath += includeBase; if (FindHeader(header, fullPath)) { break; } @@ -2108,10 +2048,10 @@ bool cmQtAutoGenerators::MocFindIncludedFile( } // Search in include directories if (!success) { - for (std::vector::const_iterator iit = - this->MocIncludePaths.begin(); - iit != this->MocIncludePaths.end(); ++iit) { - const std::string fullPath = ((*iit) + '/' + includeString); + for (const std::string& path : this->MocIncludePaths) { + std::string fullPath = path; + fullPath.push_back('/'); + fullPath += includeString; if (cmsys::SystemTools::FileExists(fullPath.c_str())) { absFile = cmsys::SystemTools::GetRealPath(fullPath); success = true; diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 5cb3d9f..5421408 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmFilePathChecksum.h" +#include "cmQtAutoGen.h" #include "cmsys/RegularExpression.hxx" #include @@ -142,11 +143,11 @@ private: std::string ChecksumedPath(const std::string& sourceFile, const std::string& basePrefix, const std::string& baseSuffix) const; - bool MakeParentDirectory(const char* logPrefix, + bool MakeParentDirectory(cmQtAutoGen::GeneratorType genType, const std::string& filename) const; bool FileDiffers(const std::string& filename, const std::string& content); - bool FileWrite(const char* logPrefix, const std::string& filename, - const std::string& content); + bool FileWrite(cmQtAutoGen::GeneratorType genType, + const std::string& filename, const std::string& content); bool RunCommand(const std::vector& command, std::string& output, bool verbose = true) const; -- cgit v0.12 From 37714f884be3c37fbbcbf7bbef0ceb3b44cc5961 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Thu, 31 Aug 2017 17:05:45 +0200 Subject: Autogen: Replace cmsys::SystemTools:: with cmSystemTools:: --- Source/cmQtAutoGen.cxx | 4 +-- Source/cmQtAutoGeneratorInitializer.cxx | 12 ++++---- Source/cmQtAutoGenerators.cxx | 50 ++++++++++++++++----------------- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index f1453b4..98dbdd2 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -56,7 +56,7 @@ static bool RccListInputsQt4(const std::string& fileName, } if (allGood) { // qrc file directory - std::string qrcDir(cmsys::SystemTools::GetFilenamePath(fileName)); + std::string qrcDir(cmSystemTools::GetFilenamePath(fileName)); if (!qrcDir.empty()) { qrcDir += '/'; } @@ -225,7 +225,7 @@ bool cmQtAutoGen::RccListInputs(const std::string& qtMajorVersion, std::string* errorMessage) { bool allGood = false; - if (cmsys::SystemTools::FileExists(fileName.c_str())) { + if (cmSystemTools::FileExists(fileName.c_str())) { if (qtMajorVersion == "4") { allGood = RccListInputsQt4(fileName, files, errorMessage); } else { diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index 3fe4028..79bb99b 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -325,7 +325,7 @@ static void SetupAcquireSkipFiles(cmQtAutoGenDigest const& digest, const bool uicSkip = digest.UicEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC")); if (mocSkip || uicSkip) { - const std::string absFile = cmsys::SystemTools::GetRealPath(fPath); + const std::string absFile = cmSystemTools::GetRealPath(fPath); if (mocSkip) { setup.MocSkip.insert(absFile); } @@ -482,7 +482,7 @@ static void SetupAutoTargetUic(const cmQtAutoGenDigest& digest, // Check if the files has uic options std::string uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS"); if (!uicOpts.empty()) { - const std::string absFile = cmsys::SystemTools::GetRealPath(fPath); + const std::string absFile = cmSystemTools::GetRealPath(fPath); // Check if file isn't skipped if (setup.UicSkip.count(absFile) == 0) { uiFileFiles.push_back(absFile); @@ -742,7 +742,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( cmSystemTools::GetFileFormat(ext.c_str()); if ((fileType == cmSystemTools::CXX_FILE_FORMAT) || (fileType == cmSystemTools::HEADER_FILE_FORMAT)) { - const std::string absPath = cmsys::SystemTools::GetRealPath(fPath); + const std::string absPath = cmSystemTools::GetRealPath(fPath); if ((digest.MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) || (digest.UicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) { // Register source @@ -769,7 +769,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( // Register qrc file { cmQtAutoGenDigestQrc qrcDigest; - qrcDigest.QrcFile = cmsys::SystemTools::GetRealPath(fPath); + qrcDigest.QrcFile = cmSystemTools::GetRealPath(fPath); qrcDigest.Generated = sf->GetPropertyAsBool("GENERATED"); // RCC options { @@ -859,8 +859,8 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( std::string rccFile = autogenBuildDir + "/"; rccFile += fpathCheckSum.getPart(qrcDigest.QrcFile); rccFile += "/qrc_"; - rccFile += cmsys::SystemTools::GetFilenameWithoutLastExtension( - qrcDigest.QrcFile); + rccFile += + cmSystemTools::GetFilenameWithoutLastExtension(qrcDigest.QrcFile); rccFile += ".cpp"; AddGeneratedSource(target, rccFile, cmQtAutoGen::RCC); diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index e9929f4..7f1443e 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -124,7 +124,7 @@ static void SettingAppend(std::string& str, const char* key, static std::string SubDirPrefix(const std::string& fileName) { - std::string res(cmsys::SystemTools::GetFilenamePath(fileName)); + std::string res(cmSystemTools::GetFilenamePath(fileName)); if (!res.empty()) { res += '/'; } @@ -135,9 +135,9 @@ static bool FileNameIsUnique(const std::string& filePath, const std::map& fileMap) { size_t count(0); - const std::string fileName = cmsys::SystemTools::GetFilenameName(filePath); + const std::string fileName = cmSystemTools::GetFilenameName(filePath); for (const auto& item : fileMap) { - if (cmsys::SystemTools::GetFilenameName(item.first) == fileName) { + if (cmSystemTools::GetFilenameName(item.first) == fileName) { ++count; if (count > 1) { return false; @@ -171,7 +171,7 @@ static bool FileAbsentOrOlder(const std::string& buildFile, { int result = 0; bool success = - cmsys::SystemTools::FileTimeCompare(buildFile, sourceFile, &result); + cmSystemTools::FileTimeCompare(buildFile, sourceFile, &result); return (!success || (result <= 0)); } @@ -238,7 +238,7 @@ static void UicMergeOptions(std::vector& opts, // -- Class methods cmQtAutoGenerators::cmQtAutoGenerators() - : Verbose(cmsys::SystemTools::HasEnv("VERBOSE")) + : Verbose(cmSystemTools::HasEnv("VERBOSE")) , ColorOutput(true) , MocSettingsChanged(false) , MocPredefsChanged(false) @@ -250,7 +250,7 @@ cmQtAutoGenerators::cmQtAutoGenerators() { std::string colorEnv; - cmsys::SystemTools::GetEnv("COLOR", colorEnv); + cmSystemTools::GetEnv("COLOR", colorEnv); if (!colorEnv.empty()) { if (cmSystemTools::IsOn(colorEnv.c_str())) { this->ColorOutput = true; @@ -685,8 +685,8 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile) if (cmHasLiteralSuffix(path, ".framework/Headers")) { // Go up twice to get to the framework root std::vector pathComponents; - cmsys::SystemTools::SplitPath(path, pathComponents); - std::string frameworkPath = cmsys::SystemTools::JoinPath( + cmSystemTools::SplitPath(path, pathComponents); + std::string frameworkPath = cmSystemTools::JoinPath( pathComponents.begin(), pathComponents.end() - 2); frameworkPaths.insert(frameworkPath); } @@ -713,7 +713,7 @@ bool cmQtAutoGenerators::RunAutogen() { const std::string incDirAbs = cmSystemTools::CollapseCombinedPath( this->AutogenBuildDir, this->AutogenIncludeDir); - if (!cmsys::SystemTools::MakeDirectory(incDirAbs)) { + if (!cmSystemTools::MakeDirectory(incDirAbs)) { this->LogError("AutoGen: Error: Could not create include directory " + Quoted(incDirAbs)); return false; @@ -922,7 +922,7 @@ bool cmQtAutoGenerators::MocParseSourceContent( const std::string scannedFileAbsPath = SubDirPrefix(absFilename); const std::string scannedFileBasename = - cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); + cmSystemTools::GetFilenameWithoutLastExtension(absFilename); std::string macroName; const bool requiresMoc = this->MocRequired(contentText, ¯oName); @@ -941,7 +941,7 @@ bool cmQtAutoGenerators::MocParseSourceContent( // Basename of the moc include const std::string incSubDir(SubDirPrefix(incString)); const std::string incBasename = - cmsys::SystemTools::GetFilenameWithoutLastExtension(incString); + cmSystemTools::GetFilenameWithoutLastExtension(incString); // If the moc include is of the moc_foo.cpp style we expect // the Q_OBJECT class declaration in a header file. @@ -1130,7 +1130,7 @@ void cmQtAutoGenerators::SearchHeadersForSourceFile( std::array basepaths; { std::string bpath = SubDirPrefix(absFilename); - bpath += cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); + bpath += cmSystemTools::GetFilenameWithoutLastExtension(absFilename); // search for default header files and private header files basepaths[0] = bpath; basepaths[1] = bpath; @@ -1455,8 +1455,8 @@ bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile, // Search for the .ui file! for (const std::string& testFile : testFiles) { - if (cmsys::SystemTools::FileExists(testFile.c_str())) { - absFile = cmsys::SystemTools::GetRealPath(testFile); + if (cmSystemTools::FileExists(testFile.c_str())) { + absFile = cmSystemTools::GetRealPath(testFile); success = true; break; } @@ -1500,7 +1500,7 @@ bool cmQtAutoGenerators::UicGenerateAll( // Remove ui_ from the begin filename by substr() const std::string uiBasePath = SubDirPrefix(inc); const std::string uiBaseName = - cmsys::SystemTools::GetFilenameWithoutLastExtension(inc).substr(3); + cmSystemTools::GetFilenameWithoutLastExtension(inc).substr(3); const std::string uiFileName = uiBaseName + ".ui"; std::string uiInputFile; if (UicFindIncludedFile(uiInputFile, source, uiBasePath, uiFileName)) { @@ -1710,7 +1710,7 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, if (this->MakeParentDirectory(cmQtAutoGen::RCC, rccBuildFile)) { // Compose symbol name std::string symbolName = - cmsys::SystemTools::GetFilenameWithoutLastExtension(rccInputFile); + cmSystemTools::GetFilenameWithoutLastExtension(rccInputFile); if (!unique_n) { symbolName += "_"; symbolName += FPathChecksum.getPart(rccInputFile); @@ -1770,7 +1770,7 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, std::string content = "// This is an autogenerated configuration wrapper file. Do not edit.\n" "#include \""; - content += cmsys::SystemTools::GetFilenameName(rccBuildFile); + content += cmSystemTools::GetFilenameName(rccBuildFile); content += "\"\n"; // Write content to file if (this->FileDiffers(wrapperFileAbs, content)) { @@ -1899,7 +1899,7 @@ std::string cmQtAutoGenerators::ChecksumedPath( std::string res = FPathChecksum.getPart(sourceFile); res += "/"; res += basePrefix; - res += cmsys::SystemTools::GetFilenameWithoutLastExtension(sourceFile); + res += cmSystemTools::GetFilenameWithoutLastExtension(sourceFile); res += baseSuffix; return res; } @@ -1914,7 +1914,7 @@ bool cmQtAutoGenerators::MakeParentDirectory( bool success = true; const std::string dirName = cmSystemTools::GetFilenamePath(filename); if (!dirName.empty()) { - success = cmsys::SystemTools::MakeDirectory(dirName); + success = cmSystemTools::MakeDirectory(dirName); if (!success) { std::string error = cmQtAutoGen::GeneratorName(genType); error += ": Error: Parent directory creation failed for "; @@ -2001,7 +2001,7 @@ bool cmQtAutoGenerators::FindHeader(std::string& header, std::string testFilePath(testBasePath); testFilePath.push_back('.'); testFilePath += ext; - if (cmsys::SystemTools::FileExists(testFilePath.c_str())) { + if (cmSystemTools::FileExists(testFilePath.c_str())) { header = testFilePath; return true; } @@ -2027,7 +2027,7 @@ std::string cmQtAutoGenerators::MocFindHeader( } // Sanitize if (!header.empty()) { - header = cmsys::SystemTools::GetRealPath(header); + header = cmSystemTools::GetRealPath(header); } return header; } @@ -2041,8 +2041,8 @@ bool cmQtAutoGenerators::MocFindIncludedFile( { std::string testPath = sourcePath; testPath += includeString; - if (cmsys::SystemTools::FileExists(testPath.c_str())) { - absFile = cmsys::SystemTools::GetRealPath(testPath); + if (cmSystemTools::FileExists(testPath.c_str())) { + absFile = cmSystemTools::GetRealPath(testPath); success = true; } } @@ -2052,8 +2052,8 @@ bool cmQtAutoGenerators::MocFindIncludedFile( std::string fullPath = path; fullPath.push_back('/'); fullPath += includeString; - if (cmsys::SystemTools::FileExists(fullPath.c_str())) { - absFile = cmsys::SystemTools::GetRealPath(fullPath); + if (cmSystemTools::FileExists(fullPath.c_str())) { + absFile = cmSystemTools::GetRealPath(fullPath); success = true; break; } -- cgit v0.12 From d8d064abbc10239cf61655da31d3e6a4a46298e7 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Wed, 30 Aug 2017 23:13:10 +0200 Subject: Autogen: Use the same algorithm for RCC and UIC option merging --- Source/cmQtAutoGen.cxx | 77 +++++++++++++++++++++++++++++++++ Source/cmQtAutoGen.h | 10 +++++ Source/cmQtAutoGeneratorInitializer.cxx | 42 +----------------- Source/cmQtAutoGenerators.cxx | 39 +---------------- Source/cmQtAutoGenerators.h | 1 - 5 files changed, 90 insertions(+), 79 deletions(-) diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index 98dbdd2..cdd41ca 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -7,6 +7,7 @@ #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" +#include #include #include @@ -19,6 +20,60 @@ const std::string genNameRcc = "AutoRcc"; // - Static functions +/// @brief Merges newOpts into baseOpts +/// @arg valueOpts list of options that accept a value +void MergeOptions(std::vector& baseOpts, + const std::vector& newOpts, + const std::vector& valueOpts, bool isQt5) +{ + typedef std::vector::iterator Iter; + typedef std::vector::const_iterator CIter; + if (newOpts.empty()) { + return; + } + if (baseOpts.empty()) { + baseOpts = newOpts; + return; + } + + std::vector extraOpts; + for (CIter fit = newOpts.begin(), fitEnd = newOpts.end(); fit != fitEnd; + ++fit) { + const std::string& newOpt = *fit; + Iter existIt = std::find(baseOpts.begin(), baseOpts.end(), newOpt); + if (existIt != baseOpts.end()) { + if (newOpt.size() >= 2) { + // Acquire the option name + std::string optName; + { + auto oit = newOpt.begin(); + if (*oit == '-') { + ++oit; + if (isQt5 && (*oit == '-')) { + ++oit; + } + optName.assign(oit, newOpt.end()); + } + } + // Test if this is a value option and change the existing value + if (!optName.empty() && (std::find(valueOpts.begin(), valueOpts.end(), + optName) != valueOpts.end())) { + const Iter existItNext(existIt + 1); + const CIter fitNext(fit + 1); + if ((existItNext != baseOpts.end()) && (fitNext != fitEnd)) { + *existItNext = *fitNext; + ++fit; + } + } + } + } else { + extraOpts.push_back(newOpt); + } + } + // Append options + 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!). @@ -218,6 +273,28 @@ std::string cmQtAutoGen::Quoted(const std::string& text) return res; } +void cmQtAutoGen::UicMergeOptions(std::vector& baseOpts, + const std::vector& newOpts, + bool isQt5) +{ + static const std::vector valueOpts = { + "tr", "translate", "postfix", "generator", + "include", // Since Qt 5.3 + "g" + }; + MergeOptions(baseOpts, newOpts, valueOpts, isQt5); +} + +void cmQtAutoGen::RccMergeOptions(std::vector& baseOpts, + const std::vector& newOpts, + bool isQt5) +{ + static const std::vector valueOpts = { "name", "root", + "compress", + "threshold" }; + MergeOptions(baseOpts, newOpts, valueOpts, isQt5); +} + bool cmQtAutoGen::RccListInputs(const std::string& qtMajorVersion, const std::string& rccCommand, const std::string& fileName, diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h index 88fd0fc..4cd5e32 100644 --- a/Source/cmQtAutoGen.h +++ b/Source/cmQtAutoGen.h @@ -34,6 +34,16 @@ public: /// static std::string Quoted(const std::string& text); + /// @brief Merges newOpts into baseOpts + static void UicMergeOptions(std::vector& baseOpts, + const std::vector& newOpts, + bool isQt5); + + /// @brief Merges newOpts into baseOpts + static void RccMergeOptions(std::vector& baseOpts, + const std::vector& newOpts, + bool isQt5); + /// @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 diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index 79bb99b..d04e5b7 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -562,46 +562,6 @@ static std::string RccGetExecutable(cmGeneratorTarget const* target, return rccExec; } -static void RccMergeOptions(std::vector& opts, - const std::vector& fileOpts, - bool isQt5) -{ - typedef std::vector::iterator Iter; - typedef std::vector::const_iterator CIter; - static const char* valueOptions[4] = { "name", "root", "compress", - "threshold" }; - - std::vector extraOpts; - for (CIter fit = fileOpts.begin(), fitEnd = fileOpts.end(); fit != fitEnd; - ++fit) { - Iter existIt = std::find(opts.begin(), opts.end(), *fit); - if (existIt != opts.end()) { - const char* optName = fit->c_str(); - if (*optName == '-') { - ++optName; - if (isQt5 && *optName == '-') { - ++optName; - } - } - // Test if this is a value option and change the existing value - if ((optName != fit->c_str()) && - std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), - cmStrCmp(optName)) != cmArrayEnd(valueOptions)) { - const Iter existItNext(existIt + 1); - const CIter fitNext(fit + 1); - if ((existItNext != opts.end()) && (fitNext != fitEnd)) { - *existItNext = *fitNext; - ++fit; - } - } - } else { - extraOpts.push_back(*fit); - } - } - // Append options - opts.insert(opts.end(), extraOpts.begin(), extraOpts.end()); -} - static void SetupAutoTargetRcc(const cmQtAutoGenDigest& digest) { cmGeneratorTarget const* target = digest.Target; @@ -871,7 +831,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( { std::vector opts = optionsTarget; if (!qrcDigest.Options.empty()) { - RccMergeOptions(opts, qrcDigest.Options, QtV5); + cmQtAutoGen::RccMergeOptions(opts, qrcDigest.Options, QtV5); } qrcDigest.Options = std::move(opts); } diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 7f1443e..4e3ec96 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -7,10 +7,8 @@ #include "cmsys/Terminal.h" #include #include -#include #include #include -#include #include #include @@ -201,40 +199,6 @@ static std::string JoinOptionsMap( return result; } -static void UicMergeOptions(std::vector& opts, - const std::vector& fileOpts, - bool isQt5) -{ - static const char* valueOptions[] = { "tr", "translate", - "postfix", "generator", - "include", // Since Qt 5.3 - "g" }; - std::vector extraOpts; - for (std::vector::const_iterator it = fileOpts.begin(); - it != fileOpts.end(); ++it) { - std::vector::iterator existingIt = - std::find(opts.begin(), opts.end(), *it); - if (existingIt != opts.end()) { - const char* o = it->c_str(); - if (*o == '-') { - ++o; - } - if (isQt5 && *o == '-') { - ++o; - } - if (std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), - cmStrCmp(*it)) != cmArrayEnd(valueOptions)) { - assert(existingIt + 1 != opts.end()); - *(existingIt + 1) = *(it + 1); - ++it; - } - } else { - extraOpts.push_back(*it); - } - } - opts.insert(opts.end(), extraOpts.begin(), extraOpts.end()); -} - // -- Class methods cmQtAutoGenerators::cmQtAutoGenerators() @@ -1580,7 +1544,8 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, if (optionIt != this->UicOptions.end()) { std::vector fileOpts; cmSystemTools::ExpandListArgument(optionIt->second, fileOpts); - UicMergeOptions(allOpts, fileOpts, (this->QtMajorVersion == "5")); + cmQtAutoGen::UicMergeOptions(allOpts, fileOpts, + (this->QtMajorVersion == "5")); } cmd.insert(cmd.end(), allOpts.begin(), allOpts.end()); } diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 5421408..2084a81 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -12,7 +12,6 @@ #include #include #include -#include #include class cmMakefile; -- cgit v0.12 From 84658539bca3d0d45873872007b01a45712ba621 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Thu, 31 Aug 2017 11:47:58 +0200 Subject: Autogen: Use single KeyRegExp filter struct --- Source/cmQtAutoGenerators.cxx | 38 +++++++++++++++++++------------------- Source/cmQtAutoGenerators.h | 27 ++++++++++++++++++++------- 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 4e3ec96..7774a00 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -224,10 +224,10 @@ cmQtAutoGenerators::cmQtAutoGenerators() } // Moc macro filters - this->MocMacroFilters.push_back( - MocMacroFilter("Q_OBJECT", "[\n][ \t]*{?[ \t]*Q_OBJECT[^a-zA-Z0-9_]")); - this->MocMacroFilters.push_back( - MocMacroFilter("Q_GADGET", "[\n][ \t]*{?[ \t]*Q_GADGET[^a-zA-Z0-9_]")); + this->MocMacroFilters.emplace_back( + "Q_OBJECT", "[\n][ \t]*{?[ \t]*Q_OBJECT[^a-zA-Z0-9_]"); + this->MocMacroFilters.emplace_back( + "Q_GADGET", "[\n][ \t]*{?[ \t]*Q_GADGET[^a-zA-Z0-9_]"); // Precompile regular expressions this->MocRegExpInclude.compile( @@ -275,15 +275,15 @@ bool cmQtAutoGenerators::MocDependFilterPush(const std::string& key, bool success = false; if (!key.empty()) { if (!regExp.empty()) { - MocDependFilter filter; - filter.key = key; - if (filter.regExp.compile(regExp)) { - this->MocDependFilters.push_back(filter); + KeyRegExp filter; + filter.Key = key; + if (filter.RegExp.compile(regExp)) { + this->MocDependFilters.push_back(std::move(filter)); success = true; } else { this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Compiling " - "regular expression failed.\nKey: " + - Quoted(key) + "\nExp.: " + Quoted(regExp)); + "regular expression failed.\n Key: " + + Quoted(key) + "\n RegExp.: " + Quoted(regExp)); } } else { this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Regular " @@ -739,14 +739,14 @@ bool cmQtAutoGenerators::RunAutogen() bool cmQtAutoGenerators::MocRequired(const std::string& contentText, std::string* macroName) { - for (MocMacroFilter& filter : this->MocMacroFilters) { + for (KeyRegExp& filter : this->MocMacroFilters) { // Run a simple find string operation before the expensive // regular expression check - if (contentText.find(filter.first) != std::string::npos) { - if (filter.second.find(contentText)) { + if (contentText.find(filter.Key) != std::string::npos) { + if (filter.RegExp.find(contentText)) { // Return macro name on demand if (macroName != nullptr) { - *macroName = filter.first; + *macroName = filter.Key; } return true; } @@ -759,16 +759,16 @@ void cmQtAutoGenerators::MocFindDepends( const std::string& absFilename, const std::string& contentText, std::map>& mocDepends) { - for (MocDependFilter& filter : this->MocDependFilters) { + for (KeyRegExp& filter : this->MocDependFilters) { // Run a simple find string operation before the expensive // regular expression check - if (contentText.find(filter.key) != std::string::npos) { + if (contentText.find(filter.Key) != std::string::npos) { // Run regular expression check loop const std::string sourcePath = SubDirPrefix(absFilename); const char* contentChars = contentText.c_str(); - while (filter.regExp.find(contentChars)) { + while (filter.RegExp.find(contentChars)) { // Evaluate match - const std::string match = filter.regExp.match(1); + const std::string match = filter.RegExp.match(1); if (!match.empty()) { // Find the dependency file std::string incFile; @@ -784,7 +784,7 @@ void cmQtAutoGenerators::MocFindDepends( Quoted(match)); } } - contentChars += filter.regExp.end(); + contentChars += filter.RegExp.end(); } } } diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 2084a81..ff31884 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -25,13 +25,26 @@ public: private: // -- Types - /// @brief Used to extract additional dependencies from content text - struct MocDependFilter + /// @brief Search key plus regular expression pair + struct KeyRegExp { - std::string key; - cmsys::RegularExpression regExp; + KeyRegExp() = default; + + KeyRegExp(const char* key, const char* regExp) + : Key(key) + , RegExp(regExp) + { + } + + KeyRegExp(const std::string& key, const std::string& regExp) + : Key(key) + , RegExp(regExp) + { + } + + std::string Key; + cmsys::RegularExpression RegExp; }; - typedef std::pair MocMacroFilter; // -- Configuration bool MocDependFilterPush(const std::string& key, const std::string& regExp); @@ -200,8 +213,8 @@ private: std::vector MocDefinitions; std::vector MocOptions; std::vector MocPredefsCmd; - std::vector MocDependFilters; - std::vector MocMacroFilters; + std::vector MocDependFilters; + std::vector MocMacroFilters; cmsys::RegularExpression MocRegExpInclude; // -- Uic bool UicSettingsChanged; -- cgit v0.12 From 761b3d79746ab91219d6478a021ba3a1c56f05c8 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Thu, 31 Aug 2017 16:03:52 +0200 Subject: Autogen: Add functions to read/write a list of lists --- Source/cmQtAutoGeneratorInitializer.cxx | 16 ++++++++++++++ Source/cmQtAutoGenerators.cxx | 37 +++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index d04e5b7..0333a55 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -207,6 +207,22 @@ static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str()); } +static void AddDefinitionEscaped( + cmMakefile* makefile, const char* key, + const std::vector>& lists) +{ + std::vector seplist; + for (const std::vector& list : lists) { + std::string blist = "{"; + blist += cmJoin(list, ";"); + blist += "}"; + seplist.push_back(std::move(blist)); + } + makefile->AddDefinition(key, cmOutputConverter::EscapeForCMake( + cmJoin(seplist, cmQtAutoGen::listSep)) + .c_str()); +} + static bool AddToSourceGroup(cmMakefile* makefile, const std::string& fileName, cmQtAutoGen::GeneratorType genType) { diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 7774a00..3369f65 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -75,6 +75,43 @@ static void InfoGet(cmMakefile* makefile, const char* key, cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list); } +static std::vector InfoGetList(cmMakefile* makefile, + const char* key) +{ + std::vector list; + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list); + return list; +} + +static std::vector> InfoGetLists(cmMakefile* makefile, + const char* key) +{ + std::vector> lists; + { + const std::string value = makefile->GetSafeDefinition(key); + std::string::size_type pos = 0; + while (pos < value.size()) { + std::string::size_type next = value.find(cmQtAutoGen::listSep, pos); + std::string::size_type length = + (next != std::string::npos) ? next - pos : value.size() - pos; + // Remove enclosing braces + if (length >= 2) { + std::string::const_iterator itBeg = value.begin() + (pos + 1); + std::string::const_iterator itEnd = itBeg + (length - 2); + { + std::string subValue(itBeg, itEnd); + std::vector list; + cmSystemTools::ExpandListArgument(subValue, list); + lists.push_back(std::move(list)); + } + } + pos += length; + pos += cmQtAutoGen::listSep.size(); + } + } + return lists; +} + static void InfoGetConfig(cmMakefile* makefile, const char* key, const std::string& config, std::string& value) { -- cgit v0.12 From 37ef18a468149ba579b96a763ea3042a360652d7 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Thu, 31 Aug 2017 16:32:14 +0200 Subject: Autogen: Pass RCC build names and function names in info file - The output file name of the `rcc` command get computed once in the AUTOGEN initializer and is passed in the info file. - The function name for the `-name` option of `rcc` gets computed once in the AUTOGEN initializer and is passed along with the other `rcc` options in the info file. --- Modules/AutogenInfo.cmake.in | 4 +- Source/cmQtAutoGenDigest.h | 4 + Source/cmQtAutoGeneratorInitializer.cxx | 106 +++++++++------- Source/cmQtAutoGenerators.cxx | 219 +++++++++++++------------------- Source/cmQtAutoGenerators.h | 16 ++- 5 files changed, 164 insertions(+), 185 deletions(-) diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in index 80522ab..484dc93 100644 --- a/Modules/AutogenInfo.cmake.in +++ b/Modules/AutogenInfo.cmake.in @@ -30,6 +30,6 @@ set(AM_UIC_OPTIONS_OPTIONS @_qt_uic_options_options@) set(AM_UIC_SEARCH_PATHS @_uic_search_paths@) # RCC settings set(AM_RCC_SOURCES @_rcc_files@) +set(AM_RCC_BUILDS @_rcc_builds@) +set(AM_RCC_OPTIONS @_rcc_options@) set(AM_RCC_INPUTS @_rcc_inputs@) -set(AM_RCC_OPTIONS_FILES @_rcc_options_files@) -set(AM_RCC_OPTIONS_OPTIONS @_rcc_options_options@) diff --git a/Source/cmQtAutoGenDigest.h b/Source/cmQtAutoGenDigest.h index 2bd9f04..e756a94 100644 --- a/Source/cmQtAutoGenDigest.h +++ b/Source/cmQtAutoGenDigest.h @@ -16,13 +16,17 @@ 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 Options; std::vector Resources; }; diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index 0333a55..c7747b8 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -580,40 +580,25 @@ static std::string RccGetExecutable(cmGeneratorTarget const* target, static void SetupAutoTargetRcc(const cmQtAutoGenDigest& digest) { - cmGeneratorTarget const* target = digest.Target; - cmMakefile* makefile = target->Target->GetMakefile(); std::vector rccFiles; - std::vector rccInputs; - std::vector rccFileFiles; - std::vector rccFileOptions; + std::vector rccBuilds; + std::vector> rccOptions; + std::vector> rccInputs; for (const cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { - const std::string absFile = qrcDigest.QrcFile; - // Register file - rccFiles.push_back(absFile); - // Register (known) resource files - { - std::string entriesList = "{"; - if (!qrcDigest.Generated) { - entriesList += cmJoin(qrcDigest.Resources, cmQtAutoGen::listSep); - } - entriesList += "}"; - rccInputs.push_back(entriesList); - } - // rcc options for this qrc file - if (!qrcDigest.Options.empty()) { - rccFileFiles.push_back(absFile); - rccFileOptions.push_back( - cmJoin(qrcDigest.Options, cmQtAutoGen::listSep)); - } + 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(target, digest.QtVersionMajor)); + 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); - AddDefinitionEscaped(makefile, "_rcc_options_files", rccFileFiles); - AddDefinitionEscaped(makefile, "_rcc_options_options", rccFileOptions); } void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( @@ -746,6 +731,8 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( { cmQtAutoGenDigestQrc qrcDigest; qrcDigest.QrcFile = cmSystemTools::GetRealPath(fPath); + qrcDigest.QrcName = + cmSystemTools::GetFilenameWithoutLastExtension(qrcDigest.QrcFile); qrcDigest.Generated = sf->GetPropertyAsBool("GENERATED"); // RCC options { @@ -822,36 +809,65 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( // Process qrc files if (!digest.Qrcs.empty()) { const bool QtV5 = (digest.QtVersionMajor == "5"); - const cmFilePathChecksum fpathCheckSum(makefile); const std::string rcc = RccGetExecutable(target, digest.QtVersionMajor); // Target rcc options std::vector optionsTarget; cmSystemTools::ExpandListArgument( GetSafeProperty(target, "AUTORCC_OPTIONS"), optionsTarget); + // Check if file name is unique for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { - // RCC output file name - { - std::string rccFile = autogenBuildDir + "/"; - rccFile += fpathCheckSum.getPart(qrcDigest.QrcFile); - rccFile += "/qrc_"; - rccFile += - cmSystemTools::GetFilenameWithoutLastExtension(qrcDigest.QrcFile); - rccFile += ".cpp"; - - AddGeneratedSource(target, rccFile, cmQtAutoGen::RCC); - autogenProvides.push_back(rccFile); - qrcDigest.RccFile = std::move(rccFile); + qrcDigest.Unique = true; + for (const cmQtAutoGenDigestQrc& qrcDig2 : digest.Qrcs) { + if ((&qrcDigest != &qrcDig2) && + (qrcDigest.QrcName == qrcDig2.QrcName)) { + qrcDigest.Unique = false; + break; + } } - // RCC options + } + // Path checksum + { + const cmFilePathChecksum fpathCheckSum(makefile); + for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { + qrcDigest.PathChecksum = fpathCheckSum.getPart(qrcDigest.QrcFile); + } + } + // RCC output file name + for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { + std::string rccFile = autogenBuildDir + "/"; + rccFile += qrcDigest.PathChecksum; + rccFile += "/qrc_"; + rccFile += qrcDigest.QrcName; + rccFile += ".cpp"; + qrcDigest.RccFile = std::move(rccFile); + } + // RCC options + for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { + // Target options + std::vector opts = optionsTarget; + // Merge computed "-name XYZ" option { - std::vector opts = optionsTarget; - if (!qrcDigest.Options.empty()) { - cmQtAutoGen::RccMergeOptions(opts, qrcDigest.Options, QtV5); + std::string name = qrcDigest.QrcName; + // Replace '-' with '_'. The former is not valid for symbol names. + std::replace(name.begin(), name.end(), '-', '_'); + if (!qrcDigest.Unique) { + name += "_"; + name += qrcDigest.PathChecksum; } - qrcDigest.Options = std::move(opts); + std::vector nameOpts; + nameOpts.emplace_back("-name"); + nameOpts.emplace_back(std::move(name)); + cmQtAutoGen::RccMergeOptions(opts, nameOpts, QtV5); } - // GENERATED or not + // Merge file option + cmQtAutoGen::RccMergeOptions(opts, qrcDigest.Options, QtV5); + qrcDigest.Options = std::move(opts); + } + for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { + // Register file at target + AddGeneratedSource(target, qrcDigest.RccFile, cmQtAutoGen::RCC); + autogenProvides.push_back(qrcDigest.RccFile); if (qrcDigest.Generated) { // Add GENERATED qrc file to the dependencies autogenDepends.insert(qrcDigest.QrcFile); diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 3369f65..8dc6420 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -166,22 +166,6 @@ static std::string SubDirPrefix(const std::string& fileName) return res; } -static bool FileNameIsUnique(const std::string& filePath, - const std::map& fileMap) -{ - size_t count(0); - const std::string fileName = cmSystemTools::GetFilenameName(filePath); - for (const auto& item : fileMap) { - if (cmSystemTools::GetFilenameName(item.first) == fileName) { - ++count; - if (count > 1) { - return false; - } - } - } - return true; -} - static bool ReadAll(std::string& content, const std::string& filename) { bool success = false; @@ -473,51 +457,51 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( // - Rcc if (this->RccEnabled()) { - InfoGet(makefile, "AM_RCC_SOURCES", this->RccSources); - // File options - { - std::vector rccFilesVec; - std::vector rccOptionsVec; - InfoGet(makefile, "AM_RCC_OPTIONS_FILES", rccFilesVec); - InfoGet(makefile, "AM_RCC_OPTIONS_OPTIONS", rccOptionsVec); - if (rccFilesVec.size() == rccOptionsVec.size()) { - for (std::vector::iterator - fileIt = rccFilesVec.begin(), - optionIt = rccOptionsVec.begin(); - fileIt != rccFilesVec.end(); ++fileIt, ++optionIt) { - // Replace item separator - cmSystemTools::ReplaceString(*optionIt, cmQtAutoGen::listSep, ";"); - this->RccOptions[*fileIt] = *optionIt; - } - } else { - this->LogError( - "AutoGen: Error: RCC files/options lists size missmatch in:\n" + - Quoted(filename)); - return false; - } - } // File lists + auto sources = InfoGetList(makefile, "AM_RCC_SOURCES"); + auto builds = InfoGetList(makefile, "AM_RCC_BUILDS"); + auto options = InfoGetLists(makefile, "AM_RCC_OPTIONS"); + auto inputs = InfoGetLists(makefile, "AM_RCC_INPUTS"); + + if (sources.size() != builds.size()) { + std::ostringstream ost; + ost << "AutoRcc: Error: sources/builds list sizes missmatch (" + << sources.size() << "/" << builds.size() << ")" + << " in\n " << Quoted(filename); + this->LogError(ost.str()); + return false; + } + if (sources.size() != options.size()) { + std::ostringstream ost; + ost << "AutoRcc: Error: sources/options list sizes missmatch (" + << sources.size() << "/" << options.size() << ")" + << " in\n " << Quoted(filename); + this->LogError(ost.str()); + return false; + } + if (sources.size() != inputs.size()) { + std::ostringstream ost; + ost << "AutoRcc: Error: sources/inputs list sizes missmatch (" + << sources.size() << "/" << inputs.size() << ")" + << " in\n " << Quoted(filename); + this->LogError(ost.str()); + return false; + } + { - std::vector rccInputLists; - InfoGet(makefile, "AM_RCC_INPUTS", rccInputLists); - if (this->RccSources.size() == rccInputLists.size()) { - for (std::vector::iterator - fileIt = this->RccSources.begin(), - inputIt = rccInputLists.begin(); - fileIt != this->RccSources.end(); ++fileIt, ++inputIt) { - // Remove braces - *inputIt = inputIt->substr(1, inputIt->size() - 2); - // Replace item separator - cmSystemTools::ReplaceString(*inputIt, cmQtAutoGen::listSep, ";"); - std::vector rccInputFiles; - cmSystemTools::ExpandListArgument(*inputIt, rccInputFiles); - this->RccInputs[*fileIt] = rccInputFiles; - } - } else { - this->LogError( - "AutoGen: Error: RCC sources/inputs lists size missmatch in:\n" + - Quoted(filename)); - 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; } } } @@ -560,8 +544,14 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile) if (this->RccEnabled()) { std::string str; str += this->RccExecutable; - str += sep; - str += JoinOptionsMap(this->RccOptions); + for (const RccJob& rccJob : this->RccJobs) { + str += sep; + str += rccJob.QrcFile; + str += sep; + str += rccJob.RccFile; + str += sep; + str += JoinOptionsList(rccJob.Options); + } str += sep; this->SettingsStringRcc = crypt.HashString(str); } @@ -1622,33 +1612,9 @@ bool cmQtAutoGenerators::RccGenerateAll() return true; } - // generate single map with input / output names - std::map qrcGenMap; - { - const std::string qrcPrefix = "qrc_"; - const std::string qrcSuffix = this->ConfigSuffix + ".cpp"; - for (const std::string& src : this->RccSources) { - qrcGenMap[src] = this->ChecksumedPath(src, qrcPrefix, qrcSuffix); - } - } - - // look for name collisions - { - std::multimap collisions; - if (this->NameCollisionTest(qrcGenMap, collisions)) { - std::ostringstream ost; - ost << "AutoRcc: Error: The same qrc_NAME.cpp file" - " will be generated from different sources.\n" - "To avoid this error rename the source .qrc files.\n"; - this->LogErrorNameCollision(ost.str(), collisions); - return false; - } - } - - // generate qrc files - for (const auto& item : qrcGenMap) { - bool unique = FileNameIsUnique(item.first, qrcGenMap); - if (!this->RccGenerateFile(item.first, item.second, unique)) { + // Generate qrc files + for (const RccJob& rccJob : this->RccJobs) { + if (!this->RccGenerateFile(rccJob)) { if (this->RccRunFailed) { return false; } @@ -1660,28 +1626,37 @@ bool cmQtAutoGenerators::RccGenerateAll() /** * @return True if a rcc file was created. False may indicate an error. */ -bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, - const std::string& rccOutputFile, - bool unique_n) +bool cmQtAutoGenerators::RccGenerateFile(const RccJob& rccJob) { bool rccGenerated = false; bool generateRcc = this->RccSettingsChanged; - const std::string rccBuildFile = - cmSystemTools::CollapseCombinedPath(this->AutogenBuildDir, rccOutputFile); + + std::string rccFileAbs; + if (this->ConfigSuffix.empty()) { + rccFileAbs = rccJob.RccFile; + } else { + rccFileAbs = SubDirPrefix(rccJob.RccFile); + rccFileAbs += + cmSystemTools::GetFilenameWithoutLastExtension(rccJob.RccFile); + rccFileAbs += this->ConfigSuffix; + rccFileAbs += cmSystemTools::GetFilenameLastExtension(rccJob.RccFile); + } + const std::string rccFileRel = cmSystemTools::RelativePath( + this->AutogenBuildDir.c_str(), rccFileAbs.c_str()); // Check if regeneration is required if (!generateRcc) { // Test if the resources list file is newer than build file - generateRcc = FileAbsentOrOlder(rccBuildFile, rccInputFile); + generateRcc = FileAbsentOrOlder(rccFileAbs, rccJob.QrcFile); if (!generateRcc) { // Acquire input file list std::vector readFiles; - const std::vector* files = &this->RccInputs[rccInputFile]; + const std::vector* files = &rccJob.Inputs; if (files->empty()) { // Read input file list from qrc file std::string error; if (cmQtAutoGen::RccListInputs(this->QtMajorVersion, - this->RccExecutable, rccInputFile, + this->RccExecutable, rccJob.QrcFile, readFiles, &error)) { files = &readFiles; } else { @@ -1693,7 +1668,7 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, // Test if any input file is newer than the build file if (files != nullptr) { for (const std::string& file : *files) { - if (FileAbsentOrOlder(rccBuildFile, file)) { + if (FileAbsentOrOlder(rccFileAbs, file)) { generateRcc = true; break; } @@ -1705,37 +1680,18 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, if (generateRcc) { // Log if (this->Verbose) { - this->LogBold("Generating RCC source " + rccOutputFile); + this->LogBold("Generating RCC source " + rccFileRel); } // Make sure the parent directory exists - if (this->MakeParentDirectory(cmQtAutoGen::RCC, rccBuildFile)) { - // Compose symbol name - std::string symbolName = - cmSystemTools::GetFilenameWithoutLastExtension(rccInputFile); - if (!unique_n) { - symbolName += "_"; - symbolName += FPathChecksum.getPart(rccInputFile); - } - // Replace '-' with '_'. The former is valid for - // file names but not for symbol names. - std::replace(symbolName.begin(), symbolName.end(), '-', '_'); - + if (this->MakeParentDirectory(cmQtAutoGen::RCC, rccFileAbs)) { // Compose rcc command std::vector cmd; cmd.push_back(this->RccExecutable); - { - std::map::const_iterator optionIt = - this->RccOptions.find(rccInputFile); - if (optionIt != this->RccOptions.end()) { - cmSystemTools::ExpandListArgument(optionIt->second, cmd); - } - } - cmd.push_back("-name"); - cmd.push_back(symbolName); + cmd.insert(cmd.end(), rccJob.Options.begin(), rccJob.Options.end()); cmd.push_back("-o"); - cmd.push_back(rccBuildFile); - cmd.push_back(rccInputFile); + cmd.push_back(rccFileAbs); + cmd.push_back(rccJob.QrcFile); std::string output; if (this->RunCommand(cmd, output)) { @@ -1746,12 +1702,12 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, { std::ostringstream ost; ost << "AutoRcc: Error: rcc process failed for\n"; - ost << Quoted(rccOutputFile) << "\n"; + ost << Quoted(rccFileRel) << "\n"; ost << "AutoRcc: Command:\n" << QuotedCommand(cmd) << "\n"; ost << "AutoRcc: Command output:\n" << output << "\n"; this->LogError(ost.str()); } - cmSystemTools::RemoveFile(rccBuildFile); + cmSystemTools::RemoveFile(rccFileAbs); this->RccRunFailed = true; } } else { @@ -1762,17 +1718,14 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, // For a multi configuration generator generate a wrapper file if (!this->ConfigSuffix.empty() && !this->RccRunFailed) { // Wrapper file name - const std::string cppSuffix = ".cpp"; - const size_t suffixLength = this->ConfigSuffix.size() + cppSuffix.size(); - const std::string wrapperFileRel = - rccOutputFile.substr(0, rccOutputFile.size() - suffixLength) + cppSuffix; - const std::string wrapperFileAbs = cmSystemTools::CollapseCombinedPath( - this->AutogenBuildDir, wrapperFileRel); + const std::string& wrapperFileAbs = rccJob.RccFile; + const std::string wrapperFileRel = cmSystemTools::RelativePath( + this->AutogenBuildDir.c_str(), wrapperFileAbs.c_str()); // Wrapper file content - std::string content = - "// This is an autogenerated configuration wrapper file. Do not edit.\n" - "#include \""; - content += cmSystemTools::GetFilenameName(rccBuildFile); + std::string content = "// This is an autogenerated configuration " + "wrapper file. Do not edit.\n" + "#include \""; + content += cmSystemTools::GetFilenameName(rccFileRel); content += "\"\n"; // Write content to file if (this->FileDiffers(wrapperFileAbs, content)) { diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index ff31884..975b0b6 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -46,6 +46,15 @@ private: cmsys::RegularExpression RegExp; }; + /// @brief RCC job + struct RccJob + { + std::string QrcFile; + std::string RccFile; + std::vector Options; + std::vector Inputs; + }; + // -- Configuration bool MocDependFilterPush(const std::string& key, const std::string& regExp); bool ReadAutogenInfoFile(cmMakefile* makefile, @@ -135,8 +144,7 @@ private: // -- Rcc file generation bool RccGenerateAll(); - bool RccGenerateFile(const std::string& qrcInputFile, - const std::string& qrcOutputFile, bool unique_n); + bool RccGenerateFile(const RccJob& rccJob); // -- Logging void LogErrorNameCollision( @@ -227,9 +235,7 @@ private: // -- Rcc bool RccSettingsChanged; bool RccRunFailed; - std::vector RccSources; - std::map RccOptions; - std::map> RccInputs; + std::vector RccJobs; }; #endif -- cgit v0.12 From f23a24c2878ffc0b6f769d5a61509b254d082c03 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Thu, 31 Aug 2017 22:26:47 +0200 Subject: Autogen: Use list of lists functions for UIC options --- Source/cmQtAutoGeneratorInitializer.cxx | 9 +++-- Source/cmQtAutoGenerators.cxx | 68 ++++++++++++--------------------- Source/cmQtAutoGenerators.h | 2 +- 3 files changed, 30 insertions(+), 49 deletions(-) diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index c7747b8..ed01a3c 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -487,7 +487,7 @@ static void SetupAutoTargetUic(const cmQtAutoGenDigest& digest, // Uic files options { std::vector uiFileFiles; - std::vector uiFileOptions; + std::vector> uiFileOptions; { const std::string uiExt = "ui"; const std::vector& srcFiles = makefile->GetSourceFiles(); @@ -496,14 +496,15 @@ static void SetupAutoTargetUic(const cmQtAutoGenDigest& digest, const std::string& fPath = sf->GetFullPath(); if (sf->GetExtension() == uiExt) { // Check if the files has uic options - std::string uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS"); + const std::string uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS"); if (!uicOpts.empty()) { const std::string absFile = cmSystemTools::GetRealPath(fPath); // Check if file isn't skipped if (setup.UicSkip.count(absFile) == 0) { uiFileFiles.push_back(absFile); - cmSystemTools::ReplaceString(uicOpts, ";", cmQtAutoGen::listSep); - uiFileOptions.push_back(uicOpts); + std::vector optsVec; + cmSystemTools::ExpandListArgument(uicOpts, optsVec); + uiFileOptions.push_back(std::move(optsVec)); } } } diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 8dc6420..71e51bd 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -200,26 +200,6 @@ static bool ListContains(const std::vector& list, return (std::find(list.begin(), list.end(), entry) != list.end()); } -static std::string JoinOptionsList(const std::vector& opts) -{ - return cmOutputConverter::EscapeForCMake(cmJoin(opts, ";")); -} - -static std::string JoinOptionsMap( - const std::map& opts) -{ - std::string result; - for (const auto& item : opts) { - if (!result.empty()) { - result += cmQtAutoGen::listSep; - } - result += item.first; - result += "==="; - result += item.second; - } - return result; -} - // -- Class methods cmQtAutoGenerators::cmQtAutoGenerators() @@ -433,18 +413,17 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( InfoGetConfig(makefile, "AM_UIC_TARGET_OPTIONS", config, this->UicTargetOptions); { - std::vector uicFilesVec; - std::vector uicOptionsVec; - InfoGet(makefile, "AM_UIC_OPTIONS_FILES", uicFilesVec); - InfoGet(makefile, "AM_UIC_OPTIONS_OPTIONS", uicOptionsVec); + auto uicFiles = InfoGetList(makefile, "AM_UIC_OPTIONS_FILES"); + auto uicOptions = InfoGetLists(makefile, "AM_UIC_OPTIONS_OPTIONS"); // Compare list sizes - if (uicFilesVec.size() == uicOptionsVec.size()) { - for (std::vector::iterator - fileIt = uicFilesVec.begin(), - optionIt = uicOptionsVec.begin(); - fileIt != uicFilesVec.end(); ++fileIt, ++optionIt) { - cmSystemTools::ReplaceString(*optionIt, cmQtAutoGen::listSep, ";"); - this->UicOptions[*fileIt] = *optionIt; + if (uicFiles.size() == uicOptions.size()) { + auto fitEnd = uicFiles.cend(); + auto fit = uicFiles.begin(); + auto oit = uicOptions.begin(); + while (fit != fitEnd) { + this->UicOptions[*fit] = std::move(*oit); + ++fit; + ++oit; } } else { this->LogError( @@ -519,15 +498,15 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile) std::string str; str += this->MocExecutable; str += sep; - str += JoinOptionsList(this->MocDefinitions); + str += cmJoin(this->MocDefinitions, ";"); str += sep; - str += JoinOptionsList(this->MocIncludePaths); + str += cmJoin(this->MocIncludePaths, ";"); str += sep; - str += JoinOptionsList(this->MocOptions); + str += cmJoin(this->MocOptions, ";"); str += sep; str += this->IncludeProjectDirsBefore ? "TRUE" : "FALSE"; str += sep; - str += JoinOptionsList(this->MocPredefsCmd); + str += cmJoin(this->MocPredefsCmd, ";"); str += sep; this->SettingsStringMoc = crypt.HashString(str); } @@ -535,9 +514,13 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile) std::string str; str += this->UicExecutable; str += sep; - str += JoinOptionsList(this->UicTargetOptions); - str += sep; - str += JoinOptionsMap(this->UicOptions); + str += cmJoin(this->UicTargetOptions, ";"); + for (const auto& item : this->UicOptions) { + str += sep; + str += item.first; + str += sep; + str += cmJoin(item.second, ";"); + } str += sep; this->SettingsStringUic = crypt.HashString(str); } @@ -550,7 +533,7 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile) str += sep; str += rccJob.RccFile; str += sep; - str += JoinOptionsList(rccJob.Options); + str += cmJoin(rccJob.Options, ";"); } str += sep; this->SettingsStringRcc = crypt.HashString(str); @@ -1566,12 +1549,9 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, cmd.push_back(this->UicExecutable); { std::vector allOpts = this->UicTargetOptions; - std::map::const_iterator optionIt = - this->UicOptions.find(uiInputFile); + auto optionIt = this->UicOptions.find(uiInputFile); if (optionIt != this->UicOptions.end()) { - std::vector fileOpts; - cmSystemTools::ExpandListArgument(optionIt->second, fileOpts); - cmQtAutoGen::UicMergeOptions(allOpts, fileOpts, + cmQtAutoGen::UicMergeOptions(allOpts, optionIt->second, (this->QtMajorVersion == "5")); } cmd.insert(cmd.end(), allOpts.begin(), allOpts.end()); diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 975b0b6..12d526b 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -229,7 +229,7 @@ private: bool UicRunFailed; std::vector UicSkipList; std::vector UicTargetOptions; - std::map UicOptions; + std::map> UicOptions; std::vector UicSearchPaths; cmsys::RegularExpression UicRegExpInclude; // -- Rcc -- cgit v0.12 From ed216b32a507611a3f2f634ac8d3fc0f8e810ea7 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Fri, 1 Sep 2017 00:36:23 +0200 Subject: Autogen: Touch moc_predefs.h when it's content didn't change --- Source/cmQtAutoGenerators.cxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 71e51bd..d89c121 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -1227,6 +1227,7 @@ bool cmQtAutoGenerators::MocGenerateAll( return false; } } + // (Re)write predefs file only on demand if (this->FileDiffers(this->MocPredefsFileAbs, output)) { if (this->FileWrite(cmQtAutoGen::MOC, this->MocPredefsFileAbs, @@ -1235,6 +1236,12 @@ bool cmQtAutoGenerators::MocGenerateAll( } else { return false; } + } else { + // Touch to update the time stamp + if (this->Verbose) { + this->LogInfo("Touching MOC predefs " + this->MocPredefsFileRel); + } + cmSystemTools::Touch(this->MocPredefsFileAbs, false); } } } -- cgit v0.12 From db80367c91dde9a6f72edf285232efb121b19be1 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Fri, 1 Sep 2017 00:30:14 +0200 Subject: Autogen: Use scoped lambdas intead of named functions --- Source/cmQtAutoGenerators.cxx | 55 ++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index d89c121..003e87c 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -139,24 +139,6 @@ static void InfoGetConfig(cmMakefile* makefile, const char* key, cmSystemTools::ExpandListArgument(value, list); } -inline static bool SettingsMatch(cmMakefile* makefile, const char* key, - const std::string& value) -{ - return (value == makefile->GetSafeDefinition(key)); -} - -static void SettingAppend(std::string& str, const char* key, - const std::string& value) -{ - if (!value.empty()) { - str += "set("; - str += key; - str += " "; - str += cmOutputConverter::EscapeForCMake(value); - str += ")\n"; - } -} - static std::string SubDirPrefix(const std::string& fileName) { std::string res(cmSystemTools::GetFilenamePath(fileName)); @@ -542,14 +524,19 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile) // Read old settings if (makefile->ReadListFile(this->SettingsFile.c_str())) { - if (!SettingsMatch(makefile, SettingsKeyMoc, this->SettingsStringMoc)) { - this->MocSettingsChanged = true; - } - if (!SettingsMatch(makefile, SettingsKeyUic, this->SettingsStringUic)) { - this->UicSettingsChanged = true; - } - if (!SettingsMatch(makefile, SettingsKeyRcc, this->SettingsStringRcc)) { - this->RccSettingsChanged = true; + { + auto SMatch = [makefile](const char* key, const std::string& value) { + return (value == makefile->GetSafeDefinition(key)); + }; + if (!SMatch(SettingsKeyMoc, this->SettingsStringMoc)) { + this->MocSettingsChanged = true; + } + 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 @@ -576,9 +563,19 @@ bool cmQtAutoGenerators::SettingsFileWrite() } // Compose settings file content std::string settings; - SettingAppend(settings, SettingsKeyMoc, this->SettingsStringMoc); - SettingAppend(settings, SettingsKeyUic, this->SettingsStringUic); - SettingAppend(settings, SettingsKeyRcc, this->SettingsStringRcc); + { + auto SettingAppend = [&settings](const char* key, + const std::string& value) { + settings += "set("; + settings += key; + settings += " "; + settings += cmOutputConverter::EscapeForCMake(value); + settings += ")\n"; + }; + SettingAppend(SettingsKeyMoc, this->SettingsStringMoc); + SettingAppend(SettingsKeyUic, this->SettingsStringUic); + SettingAppend(SettingsKeyRcc, this->SettingsStringRcc); + } // Write settings file if (!this->FileWrite(cmQtAutoGen::GEN, this->SettingsFile, settings)) { this->LogError("AutoGen: Error: Could not write old settings file " + -- cgit v0.12 From d561c1fffc4ec68a4e9043e0dc0499832f84fdec Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Fri, 1 Sep 2017 09:30:57 +0200 Subject: Autogen: More use of scoped lambdas --- Source/cmQtAutoGenerators.cxx | 213 +++++++++++++++++++----------------------- Source/cmQtAutoGenerators.h | 1 + 2 files changed, 96 insertions(+), 118 deletions(-) diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 003e87c..2df44d1 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -59,86 +59,6 @@ static std::string QuotedCommand(const std::vector& command) return res; } -static void InfoGet(cmMakefile* makefile, const char* key, std::string& value) -{ - value = makefile->GetSafeDefinition(key); -} - -static void InfoGet(cmMakefile* makefile, const char* key, bool& value) -{ - value = makefile->IsOn(key); -} - -static void InfoGet(cmMakefile* makefile, const char* key, - std::vector& list) -{ - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list); -} - -static std::vector InfoGetList(cmMakefile* makefile, - const char* key) -{ - std::vector list; - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list); - return list; -} - -static std::vector> InfoGetLists(cmMakefile* makefile, - const char* key) -{ - std::vector> lists; - { - const std::string value = makefile->GetSafeDefinition(key); - std::string::size_type pos = 0; - while (pos < value.size()) { - std::string::size_type next = value.find(cmQtAutoGen::listSep, pos); - std::string::size_type length = - (next != std::string::npos) ? next - pos : value.size() - pos; - // Remove enclosing braces - if (length >= 2) { - std::string::const_iterator itBeg = value.begin() + (pos + 1); - std::string::const_iterator itEnd = itBeg + (length - 2); - { - std::string subValue(itBeg, itEnd); - std::vector list; - cmSystemTools::ExpandListArgument(subValue, list); - lists.push_back(std::move(list)); - } - } - pos += length; - pos += cmQtAutoGen::listSep.size(); - } - } - return lists; -} - -static void InfoGetConfig(cmMakefile* makefile, const char* key, - const std::string& config, std::string& value) -{ - const char* valueConf = nullptr; - { - std::string keyConf = key; - if (!config.empty()) { - keyConf += "_"; - keyConf += config; - } - valueConf = makefile->GetDefinition(keyConf); - } - if (valueConf == nullptr) { - valueConf = makefile->GetSafeDefinition(key); - } - value = valueConf; -} - -static void InfoGetConfig(cmMakefile* makefile, const char* key, - const std::string& config, - std::vector& list) -{ - std::string value; - InfoGetConfig(makefile, key, config, value); - cmSystemTools::ExpandListArgument(value, list); -} - static std::string SubDirPrefix(const std::string& fileName) { std::string res(cmSystemTools::GetFilenamePath(fileName)); @@ -282,6 +202,67 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( cmMakefile* makefile, const std::string& targetDirectory, const std::string& config) { + // Lambdas + auto InfoGet = [makefile](const char* key) { + return makefile->GetSafeDefinition(key); + }; + auto InfoGetBool = [makefile](const char* key) { + return makefile->IsOn(key); + }; + auto InfoGetList = [makefile](const char* key) -> std::vector { + std::vector list; + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list); + return list; + }; + auto InfoGetLists = + [makefile](const char* key) -> std::vector> { + std::vector> lists; + { + const std::string value = makefile->GetSafeDefinition(key); + std::string::size_type pos = 0; + while (pos < value.size()) { + std::string::size_type next = value.find(cmQtAutoGen::listSep, pos); + std::string::size_type length = + (next != std::string::npos) ? next - pos : value.size() - pos; + // Remove enclosing braces + if (length >= 2) { + std::string::const_iterator itBeg = value.begin() + (pos + 1); + std::string::const_iterator itEnd = itBeg + (length - 2); + { + std::string subValue(itBeg, itEnd); + std::vector list; + cmSystemTools::ExpandListArgument(subValue, list); + lists.push_back(std::move(list)); + } + } + pos += length; + pos += cmQtAutoGen::listSep.size(); + } + } + return lists; + }; + auto InfoGetConfig = [makefile, &config](const char* key) -> std::string { + const char* valueConf = nullptr; + { + std::string keyConf = key; + if (!config.empty()) { + keyConf += '_'; + keyConf += config; + } + valueConf = makefile->GetDefinition(keyConf); + } + if (valueConf == nullptr) { + valueConf = makefile->GetSafeDefinition(key); + } + return std::string(valueConf); + }; + auto InfoGetConfigList = + [&InfoGetConfig](const char* key) -> std::vector { + std::vector list; + cmSystemTools::ExpandListArgument(InfoGetConfig(key), list); + return list; + }; + std::string filename(cmSystemTools::CollapseFullPath(targetDirectory)); cmSystemTools::ConvertToUnixSlashes(filename); filename += "/AutogenInfo.cmake"; @@ -292,7 +273,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( } // -- Meta - InfoGetConfig(makefile, "AM_CONFIG_SUFFIX", config, this->ConfigSuffix); + this->ConfigSuffix = InfoGetConfig("AM_CONFIG_SUFFIX"); // - Old settings file { @@ -304,28 +285,26 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( } // - Files and directories - InfoGet(makefile, "AM_CMAKE_SOURCE_DIR", this->ProjectSourceDir); - InfoGet(makefile, "AM_CMAKE_BINARY_DIR", this->ProjectBinaryDir); - InfoGet(makefile, "AM_CMAKE_CURRENT_SOURCE_DIR", this->CurrentSourceDir); - InfoGet(makefile, "AM_CMAKE_CURRENT_BINARY_DIR", this->CurrentBinaryDir); - InfoGet(makefile, "AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE", - this->IncludeProjectDirsBefore); - InfoGet(makefile, "AM_BUILD_DIR", this->AutogenBuildDir); + this->ProjectSourceDir = InfoGet("AM_CMAKE_SOURCE_DIR"); + this->ProjectBinaryDir = InfoGet("AM_CMAKE_BINARY_DIR"); + this->CurrentSourceDir = InfoGet("AM_CMAKE_CURRENT_SOURCE_DIR"); + this->CurrentBinaryDir = InfoGet("AM_CMAKE_CURRENT_BINARY_DIR"); + this->IncludeProjectDirsBefore = + InfoGetBool("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"); + this->AutogenBuildDir = InfoGet("AM_BUILD_DIR"); if (this->AutogenBuildDir.empty()) { this->LogError("AutoGen: Error: Missing autogen build directory "); return false; } - InfoGet(makefile, "AM_SOURCES", this->Sources); - InfoGet(makefile, "AM_HEADERS", this->Headers); + this->Sources = InfoGetList("AM_SOURCES"); + this->Headers = InfoGetList("AM_HEADERS"); // - Qt environment - InfoGet(makefile, "AM_QT_VERSION_MAJOR", this->QtMajorVersion); - if (this->QtMajorVersion.empty()) { - InfoGet(makefile, "AM_Qt5Core_VERSION_MAJOR", this->QtMajorVersion); - } - InfoGet(makefile, "AM_QT_MOC_EXECUTABLE", this->MocExecutable); - InfoGet(makefile, "AM_QT_UIC_EXECUTABLE", this->UicExecutable); - InfoGet(makefile, "AM_QT_RCC_EXECUTABLE", this->RccExecutable); + this->QtMajorVersion = InfoGet("AM_QT_VERSION_MAJOR"); + this->QtMinorVersion = InfoGet("AM_QT_VERSION_MINOR"); + 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")) { @@ -336,9 +315,8 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( // - Moc if (this->MocEnabled()) { - InfoGet(makefile, "AM_MOC_SKIP", this->MocSkipList); - InfoGetConfig(makefile, "AM_MOC_DEFINITIONS", config, - this->MocDefinitions); + this->MocSkipList = InfoGetList("AM_MOC_SKIP"); + this->MocDefinitions = InfoGetConfigList("AM_MOC_DEFINITIONS"); #ifdef _WIN32 { const std::string win32("WIN32"); @@ -347,20 +325,20 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( } } #endif - InfoGetConfig(makefile, "AM_MOC_INCLUDES", config, this->MocIncludePaths); - InfoGet(makefile, "AM_MOC_OPTIONS", this->MocOptions); - InfoGet(makefile, "AM_MOC_RELAXED_MODE", this->MocRelaxedMode); + this->MocIncludePaths = InfoGetConfigList("AM_MOC_INCLUDES"); + this->MocOptions = InfoGetList("AM_MOC_OPTIONS"); + this->MocRelaxedMode = InfoGetBool("AM_MOC_RELAXED_MODE"); { - std::vector MocMacroNames; - InfoGet(makefile, "AM_MOC_MACRO_NAMES", MocMacroNames); + const std::vector MocMacroNames = + InfoGetList("AM_MOC_MACRO_NAMES"); for (const std::string& item : MocMacroNames) { this->MocMacroFilters.emplace_back( item, ("[^a-zA-Z0-9_]" + item).append("[^a-zA-Z0-9_]")); } } { - std::vector mocDependFilters; - InfoGet(makefile, "AM_MOC_DEPEND_FILTERS", mocDependFilters); + const std::vector mocDependFilters = + InfoGetList("AM_MOC_DEPEND_FILTERS"); // Insert Q_PLUGIN_METADATA dependency filter if (this->QtMajorVersion != "4") { this->MocDependFilterPush("Q_PLUGIN_METADATA", @@ -385,18 +363,17 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( return false; } } - InfoGet(makefile, "AM_MOC_PREDEFS_CMD", this->MocPredefsCmd); + this->MocPredefsCmd = InfoGetList("AM_MOC_PREDEFS_CMD"); } // - Uic if (this->UicEnabled()) { - InfoGet(makefile, "AM_UIC_SKIP", this->UicSkipList); - InfoGet(makefile, "AM_UIC_SEARCH_PATHS", this->UicSearchPaths); - InfoGetConfig(makefile, "AM_UIC_TARGET_OPTIONS", config, - this->UicTargetOptions); + this->UicSkipList = InfoGetList("AM_UIC_SKIP"); + this->UicSearchPaths = InfoGetList("AM_UIC_SEARCH_PATHS"); + this->UicTargetOptions = InfoGetConfigList("AM_UIC_TARGET_OPTIONS"); { - auto uicFiles = InfoGetList(makefile, "AM_UIC_OPTIONS_FILES"); - auto uicOptions = InfoGetLists(makefile, "AM_UIC_OPTIONS_OPTIONS"); + auto uicFiles = InfoGetList("AM_UIC_OPTIONS_FILES"); + auto uicOptions = InfoGetLists("AM_UIC_OPTIONS_OPTIONS"); // Compare list sizes if (uicFiles.size() == uicOptions.size()) { auto fitEnd = uicFiles.cend(); @@ -419,10 +396,10 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( // - Rcc if (this->RccEnabled()) { // File lists - auto sources = InfoGetList(makefile, "AM_RCC_SOURCES"); - auto builds = InfoGetList(makefile, "AM_RCC_BUILDS"); - auto options = InfoGetLists(makefile, "AM_RCC_OPTIONS"); - auto inputs = InfoGetLists(makefile, "AM_RCC_INPUTS"); + 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; diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 12d526b..d7f4f63 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -190,6 +190,7 @@ private: std::string AutogenIncludeDir; // -- Qt environment std::string QtMajorVersion; + std::string QtMinorVersion; std::string MocExecutable; std::string UicExecutable; std::string RccExecutable; -- cgit v0.12 From 0f9080e235907d54e72041805dd2faf7ee43ce4d Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Fri, 1 Sep 2017 09:37:24 +0200 Subject: Autogen: More use of scoped lambdas --- Source/cmQtAutoGeneratorInitializer.cxx | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index ed01a3c..bfb2945 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -1063,23 +1063,18 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( // Open and write file cmsys::ofstream ofs(infoFile.c_str(), std::ios::app); if (ofs) { + auto OfsWriteMap = [&ofs]( + const char* key, const std::map& map) { + for (const auto& item : map) { + ofs << "set(" << key << "_" << item.first << " " + << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; + } + }; ofs << "# Configuration specific options\n"; - for (const auto& item : configSuffix) { - ofs << "set(AM_CONFIG_SUFFIX_" << item.first << " " - << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; - } - for (const auto& item : setup.ConfigMocDefines) { - ofs << "set(AM_MOC_DEFINITIONS_" << item.first << " " - << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; - } - for (const auto& item : setup.ConfigMocIncludes) { - ofs << "set(AM_MOC_INCLUDES_" << item.first << " " - << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; - } - for (const auto& item : setup.ConfigUicOptions) { - ofs << "set(AM_UIC_TARGET_OPTIONS_" << item.first << " " - << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; - } + OfsWriteMap("AM_CONFIG_SUFFIX", configSuffix); + OfsWriteMap("AM_MOC_DEFINITIONS", setup.ConfigMocDefines); + OfsWriteMap("AM_MOC_INCLUDES", setup.ConfigMocIncludes); + OfsWriteMap("AM_UIC_TARGET_OPTIONS", setup.ConfigUicOptions); } else { // File open error std::string error = "Internal CMake error when trying to open file: "; -- cgit v0.12 From 2ba1b2812290e962e33aa884989b7f57d43b8491 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Thu, 31 Aug 2017 22:34:05 +0200 Subject: Autogen: More use of scoped lambdas --- Source/cmQtAutoGeneratorInitializer.cxx | 63 +++++++++++++++------------------ 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index bfb2945..0cff825 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -134,26 +134,6 @@ static bool QtVersionGreaterOrEqual(const std::string& major, return false; } -static void GetCompileDefinitionsAndDirectories( - cmGeneratorTarget const* target, const std::string& config, - std::string& incs, std::string& defs) -{ - cmLocalGenerator* localGen = target->GetLocalGenerator(); - { - std::vector includeDirs; - // Get the include dirs for this target, without stripping the implicit - // include dirs off, see - // https://gitlab.kitware.com/cmake/cmake/issues/13667 - localGen->GetIncludeDirectories(includeDirs, target, "CXX", config, false); - incs = cmJoin(includeDirs, ";"); - } - { - std::set defines; - localGen->AddCompileDefinitions(defines, target, config, "CXX"); - defs += cmJoin(defines, ";"); - } -} - static std::vector GetConfigurations( cmMakefile* makefile, std::string* config = nullptr) { @@ -381,10 +361,28 @@ static void SetupAutoTargetMoc(const cmQtAutoGenDigest& digest, } // Moc includes and compile definitions { + auto GetCompileDefinitionsAndDirectories = [target, localGen]( + const std::string& cfg, std::string& incs, std::string& defs) { + { + std::vector includeDirs; + // Get the include dirs for this target, without stripping the implicit + // include dirs off, see + // https://gitlab.kitware.com/cmake/cmake/issues/13667 + localGen->GetIncludeDirectories(includeDirs, target, "CXX", cfg, + false); + incs = cmJoin(includeDirs, ";"); + } + { + std::set defines; + localGen->AddCompileDefinitions(defines, target, cfg, "CXX"); + defs += cmJoin(defines, ";"); + } + }; + // Default settings std::string incs; std::string compileDefs; - GetCompileDefinitionsAndDirectories(target, config, incs, compileDefs); + GetCompileDefinitionsAndDirectories(config, incs, compileDefs); AddDefinitionEscaped(makefile, "_moc_incs", incs); AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs); @@ -392,8 +390,7 @@ static void SetupAutoTargetMoc(const cmQtAutoGenDigest& digest, for (const std::string& cfg : configs) { std::string configIncs; std::string configCompileDefs; - GetCompileDefinitionsAndDirectories(target, cfg, configIncs, - configCompileDefs); + GetCompileDefinitionsAndDirectories(cfg, configIncs, configCompileDefs); if (configIncs != incs) { setup.ConfigMocIncludes[cfg] = configIncs; } @@ -435,14 +432,6 @@ static void SetupAutoTargetMoc(const cmQtAutoGenDigest& digest, } } -static void UicGetOpts(cmGeneratorTarget const* target, - const std::string& config, std::string& optString) -{ - std::vector opts; - target->GetAutoUicOptions(opts, config); - optString = cmJoin(opts, ";"); -} - static void SetupAutoTargetUic(const cmQtAutoGenDigest& digest, std::string const& config, std::vector const& configs, @@ -470,15 +459,19 @@ static void SetupAutoTargetUic(const cmQtAutoGenDigest& digest, } // Uic target options { + auto UicGetOpts = [target](const std::string& cfg) -> std::string { + std::vector opts; + target->GetAutoUicOptions(opts, cfg); + return cmJoin(opts, ";"); + }; + // Default settings - std::string uicOpts; - UicGetOpts(target, config, uicOpts); + const std::string uicOpts = UicGetOpts(config); AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts); // Configuration specific settings for (const std::string& cfg : configs) { - std::string configUicOpts; - UicGetOpts(target, cfg, configUicOpts); + const std::string configUicOpts = UicGetOpts(cfg); if (configUicOpts != uicOpts) { setup.ConfigUicOptions[cfg] = configUicOpts; } -- cgit v0.12 From 9468e926b0fb01b2f11b9d4c9c13f7ad64b328e2 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Fri, 1 Sep 2017 14:28:26 +0200 Subject: Autogen: Refactor logging --- Source/cmQtAutoGen.cxx | 14 +- Source/cmQtAutoGenerators.cxx | 587 ++++++++++++++++++++++++------------------ Source/cmQtAutoGenerators.h | 37 ++- 3 files changed, 373 insertions(+), 265 deletions(-) diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index cdd41ca..95cd122 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -102,8 +102,8 @@ static bool RccListInputsQt4(const std::string& fileName, } else { if (errorMessage != nullptr) { std::ostringstream ost; - ost << "AutoRcc: Error: Rcc file not readable:\n" - << cmQtAutoGen::Quoted(fileName) << "\n"; + ost << "rcc file not readable:\n" + << " " << cmQtAutoGen::Quoted(fileName) << "\n"; *errorMessage = ost.str(); } allGood = false; @@ -145,7 +145,7 @@ static bool RccListInputsQt5(const std::string& rccCommand, std::string* errorMessage) { if (rccCommand.empty()) { - cmSystemTools::Error("AutoRcc: Error: rcc executable not available\n"); + cmSystemTools::Error("rcc executable not available"); return false; } @@ -184,7 +184,7 @@ static bool RccListInputsQt5(const std::string& rccCommand, if (!result || retVal) { if (errorMessage != nullptr) { std::ostringstream ost; - ost << "AutoRcc: Error: Rcc list process for " << fileName + ost << "rcc list process for " << cmQtAutoGen::Quoted(fileName) << " failed:\n" << rccStdOut << "\n" << rccStdErr << "\n"; @@ -217,7 +217,7 @@ static bool RccListInputsQt5(const std::string& rccCommand, if (pos == std::string::npos) { if (errorMessage != nullptr) { std::ostringstream ost; - ost << "AutoRcc: Error: Rcc lists unparsable output:\n" + ost << "rcc lists unparsable output:\n" << cmQtAutoGen::Quoted(eline) << "\n"; *errorMessage = ost.str(); } @@ -311,8 +311,8 @@ bool cmQtAutoGen::RccListInputs(const std::string& qtMajorVersion, } else { if (errorMessage != nullptr) { std::ostringstream ost; - ost << "AutoRcc: Error: Rcc file does not exist:\n" - << cmQtAutoGen::Quoted(fileName) << "\n"; + ost << "rcc file does not exist:\n" + << " " << cmQtAutoGen::Quoted(fileName) << "\n"; *errorMessage = ost.str(); } } diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 2df44d1..221a1ac 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -36,11 +36,6 @@ static const char* SettingsKeyRcc = "AM_RCC_SETTINGS_HASH"; // -- Static functions -inline static std::string Quoted(const std::string& text) -{ - return cmQtAutoGen::Quoted(text); -} - static std::string QuotedCommand(const std::vector& command) { std::string res; @@ -48,7 +43,7 @@ static std::string QuotedCommand(const std::vector& command) if (!res.empty()) { res.push_back(' '); } - const std::string cesc = Quoted(item); + const std::string cesc = cmQtAutoGen::Quoted(item); if (item.empty() || (cesc.size() > (item.size() + 2)) || (cesc.find(' ') != std::string::npos)) { res += cesc; @@ -175,27 +170,36 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory, bool cmQtAutoGenerators::MocDependFilterPush(const std::string& key, const std::string& regExp) { - bool success = false; + std::string error; if (!key.empty()) { if (!regExp.empty()) { KeyRegExp filter; filter.Key = key; if (filter.RegExp.compile(regExp)) { this->MocDependFilters.push_back(std::move(filter)); - success = true; } else { - this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Compiling " - "regular expression failed.\n Key: " + - Quoted(key) + "\n RegExp.: " + Quoted(regExp)); + error = "Regular expression compiling failed"; } } else { - this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Regular " - "expression is empty"); + error = "Regular expression is empty"; } } else { - this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Key is empty"); + error = "Key is empty"; } - return success; + if (!error.empty()) { + std::string emsg = "AUTOMOC_DEPEND_FILTERS: "; + emsg += error; + emsg += "\n"; + emsg += " Key: "; + emsg += cmQtAutoGen::Quoted(key); + emsg += "\n"; + emsg += " RegExp: "; + emsg += cmQtAutoGen::Quoted(regExp); + emsg += "\n"; + this->LogError(cmQtAutoGen::MOC, emsg); + return false; + } + return true; } bool cmQtAutoGenerators::ReadAutogenInfoFile( @@ -268,7 +272,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( filename += "/AutogenInfo.cmake"; if (!makefile->ReadListFile(filename.c_str())) { - this->LogError("AutoGen: Error processing file: " + filename); + this->LogFileError(cmQtAutoGen::GEN, filename, "File processing failed"); return false; } @@ -293,7 +297,8 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( InfoGetBool("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"); this->AutogenBuildDir = InfoGet("AM_BUILD_DIR"); if (this->AutogenBuildDir.empty()) { - this->LogError("AutoGen: Error: Missing autogen build directory "); + this->LogFileError(cmQtAutoGen::GEN, filename, + "Autogen build directory missing"); return false; } this->Sources = InfoGetList("AM_SOURCES"); @@ -308,8 +313,8 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( // Check Qt version if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) { - this->LogError("AutoGen: Error: Unsupported Qt version: " + - Quoted(this->QtMajorVersion)); + this->LogFileError(cmQtAutoGen::GEN, filename, "Unsupported Qt version: " + + cmQtAutoGen::Quoted(this->QtMajorVersion)); return false; } @@ -356,10 +361,9 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( } } } else { - this->LogError( - "AutoMoc: Error: AUTOMOC_DEPEND_FILTERS list size is not " - "a multiple of 2 in:\n" + - Quoted(filename)); + this->LogFileError( + cmQtAutoGen::MOC, filename, + "AUTOMOC_DEPEND_FILTERS list size is not a multiple of 2"); return false; } } @@ -372,22 +376,23 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( this->UicSearchPaths = InfoGetList("AM_UIC_SEARCH_PATHS"); this->UicTargetOptions = InfoGetConfigList("AM_UIC_TARGET_OPTIONS"); { - auto uicFiles = InfoGetList("AM_UIC_OPTIONS_FILES"); - auto uicOptions = InfoGetLists("AM_UIC_OPTIONS_OPTIONS"); + auto sources = InfoGetList("AM_UIC_OPTIONS_FILES"); + auto options = InfoGetLists("AM_UIC_OPTIONS_OPTIONS"); // Compare list sizes - if (uicFiles.size() == uicOptions.size()) { - auto fitEnd = uicFiles.cend(); - auto fit = uicFiles.begin(); - auto oit = uicOptions.begin(); + if (sources.size() == options.size()) { + auto fitEnd = sources.cend(); + auto fit = sources.begin(); + auto oit = options.begin(); while (fit != fitEnd) { this->UicOptions[*fit] = std::move(*oit); ++fit; ++oit; } } else { - this->LogError( - "AutoGen: Error: Uic files/options lists size missmatch in:\n" + - Quoted(filename)); + std::ostringstream ost; + ost << "files/options lists sizes missmatch (" << sources.size() << "/" + << options.size() << ")"; + this->LogFileError(cmQtAutoGen::UIC, filename, ost.str()); return false; } } @@ -403,26 +408,23 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( if (sources.size() != builds.size()) { std::ostringstream ost; - ost << "AutoRcc: Error: sources/builds list sizes missmatch (" - << sources.size() << "/" << builds.size() << ")" - << " in\n " << Quoted(filename); - this->LogError(ost.str()); + ost << "sources, builds lists sizes missmatch (" << sources.size() << "/" + << builds.size() << ")"; + this->LogFileError(cmQtAutoGen::RCC, filename, ost.str()); return false; } if (sources.size() != options.size()) { std::ostringstream ost; - ost << "AutoRcc: Error: sources/options list sizes missmatch (" - << sources.size() << "/" << options.size() << ")" - << " in\n " << Quoted(filename); - this->LogError(ost.str()); + ost << "sources, options lists sizes missmatch (" << sources.size() + << "/" << options.size() << ")"; + this->LogFileError(cmQtAutoGen::RCC, filename, ost.str()); return false; } if (sources.size() != inputs.size()) { std::ostringstream ost; - ost << "AutoRcc: Error: sources/inputs list sizes missmatch (" - << sources.size() << "/" << inputs.size() << ")" - << " in\n " << Quoted(filename); - this->LogError(ost.str()); + ost << "sources, inputs lists sizes missmatch (" << sources.size() << "/" + << inputs.size() << ")"; + this->LogFileError(cmQtAutoGen::RCC, filename, ost.str()); return false; } @@ -535,8 +537,8 @@ bool cmQtAutoGenerators::SettingsFileWrite() // Only write if any setting changed if (this->AnySettingsChanged()) { if (this->Verbose) { - this->LogInfo("AutoGen: Writing settings file " + - Quoted(this->SettingsFile)); + this->LogInfo(cmQtAutoGen::GEN, "Writing settings file " + + cmQtAutoGen::Quoted(this->SettingsFile)); } // Compose settings file content std::string settings; @@ -555,8 +557,8 @@ bool cmQtAutoGenerators::SettingsFileWrite() } // Write settings file if (!this->FileWrite(cmQtAutoGen::GEN, this->SettingsFile, settings)) { - this->LogError("AutoGen: Error: Could not write old settings file " + - Quoted(this->SettingsFile)); + this->LogFileError(cmQtAutoGen::GEN, this->SettingsFile, + "File writing failed"); // Remove old settings file to trigger a full rebuild on the next run cmSystemTools::RemoveFile(this->SettingsFile); success = false; @@ -662,8 +664,8 @@ bool cmQtAutoGenerators::RunAutogen() const std::string incDirAbs = cmSystemTools::CollapseCombinedPath( this->AutogenBuildDir, this->AutogenIncludeDir); if (!cmSystemTools::MakeDirectory(incDirAbs)) { - this->LogError("AutoGen: Error: Could not create include directory " + - Quoted(incDirAbs)); + this->LogFileError(cmQtAutoGen::GEN, incDirAbs, + "Could not create directory"); return false; } } @@ -759,13 +761,14 @@ void cmQtAutoGenerators::MocFindDepends( if (this->MocFindIncludedFile(incFile, sourcePath, match)) { mocDepends[absFilename].insert(incFile); if (this->Verbose) { - this->LogInfo("AutoMoc: Found dependency:\n " + - Quoted(absFilename) + "\n " + Quoted(incFile)); + this->LogInfo(cmQtAutoGen::MOC, "Found dependency:\n " + + cmQtAutoGen::Quoted(absFilename) + "\n " + + cmQtAutoGen::Quoted(incFile)); } } else { - this->LogWarning("AutoMoc: Warning: " + Quoted(absFilename) + - "\n" + "Could not find dependency file " + - Quoted(match)); + this->LogFileWarning(cmQtAutoGen::MOC, absFilename, + "Could not find dependency file " + + cmQtAutoGen::Quoted(match)); } } contentChars += filter.RegExp.end(); @@ -826,15 +829,10 @@ bool cmQtAutoGenerators::ParseSourceFile( this->UicParseContent(absFilename, contentText, uisIncluded); } } else { - std::ostringstream ost; - ost << "AutoGen: Warning: The file is empty:\n" - << Quoted(absFilename) << "\n"; - this->LogWarning(ost.str()); + this->LogFileWarning(cmQtAutoGen::GEN, absFilename, "The file is empty"); } } else { - std::ostringstream ost; - ost << "AutoGen: Error: Could not read file:\n" << Quoted(absFilename); - this->LogError(ost.str()); + this->LogFileError(cmQtAutoGen::GEN, absFilename, "Could not read file"); } return success; } @@ -844,7 +842,7 @@ void cmQtAutoGenerators::UicParseContent( std::map>& uisIncluded) { if (this->Verbose) { - this->LogInfo("AutoUic: Checking " + absFilename); + this->LogInfo(cmQtAutoGen::UIC, "Checking " + absFilename); } const char* contentChars = contentText.c_str(); @@ -856,6 +854,36 @@ void cmQtAutoGenerators::UicParseContent( } } +std::string cmQtAutoGenerators::MocMacroNamesString() const +{ + std::string res; + const auto itB = this->MocMacroFilters.cbegin(); + const auto itE = this->MocMacroFilters.cend(); + const auto itL = itE - 1; + auto itC = itB; + for (; itC != itE; ++itC) { + // Separator + if (itC != itB) { + if (itC != itL) { + res += ", "; + } else { + res += " or "; + } + } + // Key + res += itC->Key; + } + return res; +} + +std::string cmQtAutoGenerators::MocHeaderSuffixesString() const +{ + std::string res = ".{"; + res += cmJoin(this->HeaderExtensions, ","); + res += "}"; + return res; +} + /** * @return True on success */ @@ -865,15 +893,15 @@ bool cmQtAutoGenerators::MocParseSourceContent( std::map>& mocDepends, bool relaxed) { if (this->Verbose) { - this->LogInfo("AutoMoc: Checking " + absFilename); + this->LogInfo(cmQtAutoGen::MOC, "Checking " + absFilename); } - const std::string scannedFileAbsPath = SubDirPrefix(absFilename); - const std::string scannedFileBasename = + const std::string scanFileDir = SubDirPrefix(absFilename); + const std::string scanFileBase = cmSystemTools::GetFilenameWithoutLastExtension(absFilename); - std::string macroName; - const bool requiresMoc = this->MocRequired(contentText, ¯oName); + std::string selfMacroName; + const bool selfRequiresMoc = this->MocRequired(contentText, &selfMacroName); bool ownDotMocIncluded = false; std::string ownMocUnderscoreInclude; std::string ownMocUnderscoreHeader; @@ -887,8 +915,8 @@ bool cmQtAutoGenerators::MocParseSourceContent( while (this->MocRegExpInclude.find(contentChars)) { const std::string incString = this->MocRegExpInclude.match(1); // Basename of the moc include - const std::string incSubDir(SubDirPrefix(incString)); - const std::string incBasename = + const std::string incDir(SubDirPrefix(incString)); + const std::string incBase = cmSystemTools::GetFilenameWithoutLastExtension(incString); // If the moc include is of the moc_foo.cpp style we expect @@ -896,110 +924,123 @@ bool cmQtAutoGenerators::MocParseSourceContent( // If the moc include is of the foo.moc style we need to look for // a Q_OBJECT macro in the current source file, if it contains the // macro we generate the moc file from the source file. - if (cmHasLiteralPrefix(incBasename, "moc_")) { + if (cmHasLiteralPrefix(incBase, "moc_")) { // Include: moc_FOO.cxx // Remove the moc_ part - const std::string incRealBasename = incBasename.substr(4); + const std::string incRealBase = incBase.substr(4); const std::string headerToMoc = - this->MocFindHeader(scannedFileAbsPath, incSubDir + incRealBasename); + this->MocFindHeader(scanFileDir, incDir + incRealBase); if (!headerToMoc.empty()) { if (!this->MocSkip(headerToMoc)) { // Register moc job mocsIncluded[headerToMoc] = incString; this->MocFindDepends(headerToMoc, contentText, mocDepends); // Store meta information for relaxed mode - if (relaxed && (incRealBasename == scannedFileBasename)) { + if (relaxed && (incRealBase == scanFileBase)) { ownMocUnderscoreInclude = incString; ownMocUnderscoreHeader = headerToMoc; } } } else { std::ostringstream ost; - ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n" - << "The file includes the moc file " << Quoted(incString) - << ", but could not find header " - << Quoted(incRealBasename + ".{" + - cmJoin(this->HeaderExtensions, ",") + "}"); - this->LogError(ost.str()); + ost << "The file includes the moc file " + << cmQtAutoGen::Quoted(incString) + << ", but could not find header "; + ost << cmQtAutoGen::Quoted(incRealBase + + this->MocHeaderSuffixesString()); + this->LogFileError(cmQtAutoGen::MOC, absFilename, ost.str()); return false; } } else { // Include: FOO.moc + bool ownDotMoc = (incBase == scanFileBase); std::string fileToMoc; if (relaxed) { // Mode: Relaxed - if (requiresMoc && (incBasename == scannedFileBasename)) { + if (selfRequiresMoc && ownDotMoc) { // Include self fileToMoc = absFilename; ownDotMocIncluded = true; } else { // In relaxed mode try to find a header instead but issue a warning const std::string headerToMoc = - this->MocFindHeader(scannedFileAbsPath, incSubDir + incBasename); + this->MocFindHeader(scanFileDir, incDir + incBase); if (!headerToMoc.empty()) { if (!this->MocSkip(headerToMoc)) { // This is for KDE4 compatibility: fileToMoc = headerToMoc; - if (!requiresMoc && (incBasename == scannedFileBasename)) { - std::ostringstream ost; - ost - << "AutoMoc: Warning: " << Quoted(absFilename) << "\n" - << "The file includes the moc file " << Quoted(incString) - << ", but does not contain a Q_OBJECT or Q_GADGET macro.\n" - << "Running moc on " << Quoted(headerToMoc) << "!\n" - << "Include " << Quoted("moc_" + incBasename + ".cpp") - << " for a compatibility with strict mode (see " - "CMAKE_AUTOMOC_RELAXED_MODE).\n"; - this->LogWarning(ost.str()); + + auto quoted_inc = cmQtAutoGen::Quoted(incString); + auto quoted_header = cmQtAutoGen::Quoted(headerToMoc); + auto quoted_base = + cmQtAutoGen::Quoted("moc_" + incBase + ".cpp"); + if (!selfRequiresMoc) { + if (ownDotMoc) { + std::ostringstream ost; + ost << "The file includes the moc file " << quoted_inc + << ", but does not contain a " + << this->MocMacroNamesString() << " macro.\n" + << "Running moc on\n" + << " " << quoted_header << "!\n" + << "Better include " << quoted_base + << " for a compatibility with strict mode.\n" + "(CMAKE_AUTOMOC_RELAXED_MODE warning)\n"; + this->LogFileWarning(cmQtAutoGen::MOC, absFilename, + ost.str()); + } else if (!ownDotMoc) { + std::ostringstream ost; + ost << "The file includes the moc file " << quoted_inc + << " instead of " << quoted_base << ".\n"; + ost << "Running moc on\n" + << " " << quoted_header << "!\n" + << "Better include " << quoted_base + << " for compatibility with strict mode.\n" + "(CMAKE_AUTOMOC_RELAXED_MODE warning)\n"; + this->LogFileWarning(cmQtAutoGen::MOC, absFilename, + ost.str()); + } } else { - std::ostringstream ost; - ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n" - << "The file includes the moc file " << Quoted(incString) - << " instead of " - << Quoted("moc_" + incBasename + ".cpp") << ".\n" - << "Running moc on " << Quoted(headerToMoc) << "!\n" - << "Include " << Quoted("moc_" + incBasename + ".cpp") - << " for compatibility with strict mode (see " - "CMAKE_AUTOMOC_RELAXED_MODE).\n"; - this->LogWarning(ost.str()); + if (!ownDotMoc) { + // Handled further down + } } } } else { std::ostringstream ost; - ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n" - << "The file includes the moc file " << Quoted(incString) + ost << "The file includes the moc file " + << cmQtAutoGen::Quoted(incString) << ", which seems to be the moc file from a different " "source file. CMake also could not find a matching " "header."; - this->LogError(ost.str()); + this->LogFileError(cmQtAutoGen::MOC, absFilename, ost.str()); return false; } } } else { // Mode: Strict - if (incBasename == scannedFileBasename) { + if (ownDotMoc) { // Include self fileToMoc = absFilename; ownDotMocIncluded = true; // Accept but issue a warning if moc isn't required - if (!requiresMoc) { + if (!selfRequiresMoc) { std::ostringstream ost; - ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n" - << "The file includes the moc file " << Quoted(incString) - << ", but does not contain a Q_OBJECT or Q_GADGET " - "macro."; - this->LogWarning(ost.str()); + ost << "The file includes the moc file " + << cmQtAutoGen::Quoted(incString) + << ", but does not contain a " << this->MocMacroNamesString() + << " macro."; + this->LogFileWarning(cmQtAutoGen::MOC, absFilename, ost.str()); } } else { // Don't allow FOO.moc include other than self in strict mode std::ostringstream ost; - ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n" - << "The file includes the moc file " << Quoted(incString) + ost << "The file includes the moc file " + << cmQtAutoGen::Quoted(incString) << ", which seems to be the moc file from a different " "source file. This is not supported. Include " - << Quoted(scannedFileBasename + ".moc") + << cmQtAutoGen::Quoted(scanFileBase + ".moc") << " to run moc on this source file."; - this->LogError(ost.str()); + this->LogFileError(cmQtAutoGen::MOC, absFilename, ost.str()); return false; } } @@ -1013,24 +1054,26 @@ bool cmQtAutoGenerators::MocParseSourceContent( } } - if (requiresMoc && !ownDotMocIncluded) { - // In this case, check whether the scanned file itself contains a Q_OBJECT. + if (selfRequiresMoc && !ownDotMocIncluded) { + // In this case, check whether the scanned file itself contains a + // Q_OBJECT. // If this is the case, the moc_foo.cpp should probably be generated from // foo.cpp instead of foo.h, because otherwise it won't build. // But warn, since this is not how it is supposed to be used. if (relaxed && !ownMocUnderscoreInclude.empty()) { // This is for KDE4 compatibility: std::ostringstream ost; - ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n" - << "The file contains a " << macroName + ost << "The file contains a " << selfMacroName << " macro, but does not include " - << Quoted(scannedFileBasename + ".moc") << ", but instead includes " - << Quoted(ownMocUnderscoreInclude) << ".\n" - << "Running moc on " << Quoted(absFilename) << "!\n" - << "Better include " << Quoted(scannedFileBasename + ".moc") - << " for compatibility with strict mode (see " - "CMAKE_AUTOMOC_RELAXED_MODE)."; - this->LogWarning(ost.str()); + << cmQtAutoGen::Quoted(scanFileBase + ".moc") + << ". Instead it includes " + << cmQtAutoGen::Quoted(ownMocUnderscoreInclude) << ".\n" + << "Running moc on\n" + << " " << cmQtAutoGen::Quoted(absFilename) << "!\n" + << "Better include " << cmQtAutoGen::Quoted(scanFileBase + ".moc") + << " for compatibility with strict mode.\n" + "(CMAKE_AUTOMOC_RELAXED_MODE warning)"; + this->LogFileWarning(cmQtAutoGen::MOC, absFilename, ost.str()); // Use scanned source file instead of scanned header file as moc source mocsIncluded[absFilename] = ownMocUnderscoreInclude; @@ -1040,13 +1083,12 @@ bool cmQtAutoGenerators::MocParseSourceContent( } else { // Otherwise always error out since it will not compile: std::ostringstream ost; - ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n" - << "The file contains a " << macroName + ost << "The file contains a " << selfMacroName << " macro, but does not include " - << Quoted(scannedFileBasename + ".moc") << "!\n" + << cmQtAutoGen::Quoted(scanFileBase + ".moc") << "!\n" << "Consider adding the include or enabling SKIP_AUTOMOC for this " "file."; - this->LogError(ost.str()); + this->LogFileError(cmQtAutoGen::MOC, absFilename, ost.str()); return false; } } @@ -1061,7 +1103,7 @@ void cmQtAutoGenerators::MocParseHeaderContent( { // Log if (this->Verbose) { - this->LogInfo("AutoMoc: Checking " + absFilename); + this->LogInfo(cmQtAutoGen::MOC, "Checking " + absFilename); } if (this->MocRequired(contentText)) { // Register moc job @@ -1128,10 +1170,8 @@ bool cmQtAutoGenerators::ParseHeaders( this->UicParseContent(headerName, contentText, uisIncluded); } } else { - std::ostringstream ost; - ost << "AutoGen: Error: Could not read header file:\n" - << Quoted(headerName); - this->LogError(ost.str()); + this->LogFileError(cmQtAutoGen::GEN, headerName, + "Could not read header file"); success = false; break; } @@ -1155,14 +1195,12 @@ bool cmQtAutoGenerators::MocGenerateAll( std::map mergedMocs(mocsIncluded); mergedMocs.insert(mocsNotIncluded.begin(), mocsNotIncluded.end()); if (this->NameCollisionTest(mergedMocs, collisions)) { - std::ostringstream ost; - ost << "AutoMoc: Error: " - "The same moc file will be generated " - "from different sources.\n" - "To avoid this error either\n" - "- rename the source files or\n" - "- do not include the (moc_NAME.cpp|NAME.moc) file"; - this->LogErrorNameCollision(ost.str(), collisions); + std::string msg = "The same moc file will be generated " + "from different sources.\n" + "To avoid this error either\n" + " - rename the source files or\n" + " - do not include the (moc_NAME.cpp|NAME.moc) file"; + this->LogNameCollisionError(cmQtAutoGen::MOC, msg, collisions); return false; } } @@ -1190,14 +1228,9 @@ bool cmQtAutoGenerators::MocGenerateAll( cmd.insert(cmd.end(), this->MocOptions.begin(), this->MocOptions.end()); // Execute command - if (!this->RunCommand(cmd, output, false)) { - { - std::ostringstream ost; - ost << "AutoMoc: Error: moc predefs generation command failed\n"; - ost << "AutoMoc: Command:\n" << QuotedCommand(cmd) << "\n"; - ost << "AutoMoc: Command output:\n" << output << "\n"; - this->LogError(ost.str()); - } + if (!this->RunCommand(cmd, output)) { + this->LogCommandError(cmQtAutoGen::MOC, + "moc_predefs generation failed", cmd, output); return false; } } @@ -1213,7 +1246,8 @@ bool cmQtAutoGenerators::MocGenerateAll( } else { // Touch to update the time stamp if (this->Verbose) { - this->LogInfo("Touching MOC predefs " + this->MocPredefsFileRel); + this->LogInfo(cmQtAutoGen::MOC, + "Touching moc_predefs " + this->MocPredefsFileRel); } cmSystemTools::Touch(this->MocPredefsFileAbs, false); } @@ -1276,7 +1310,8 @@ bool cmQtAutoGenerators::MocGenerateAll( } else if (mocCompFileGenerated) { // Only touch mocs compilation file if (this->Verbose) { - this->LogInfo("Touching MOC compilation " + this->MocCompFileRel); + this->LogInfo(cmQtAutoGen::MOC, + "Touching mocs compilation " + this->MocCompFileRel); } cmSystemTools::Touch(this->MocCompFileAbs, false); } @@ -1353,15 +1388,9 @@ bool cmQtAutoGenerators::MocGenerateFile( // Success mocGenerated = true; } else { - // Command failed - { - std::ostringstream ost; - ost << "AutoMoc: Error: moc process failed for\n"; - ost << Quoted(mocFileRel) << "\n"; - ost << "AutoMoc: Command:\n" << QuotedCommand(cmd) << "\n"; - ost << "AutoMoc: Command output:\n" << output << "\n"; - this->LogError(ost.str()); - } + this->LogCommandError(cmQtAutoGen::MOC, "moc failed for\n " + + cmQtAutoGen::Quoted(sourceFile), + cmd, output); cmSystemTools::RemoveFile(mocFileAbs); this->MocRunFailed = true; } @@ -1420,12 +1449,11 @@ bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile, // Log error if (!success) { std::ostringstream ost; - ost << "AutoUic: Error: " << Quoted(sourceFile) << "\n"; - ost << "Could not find " << Quoted(searchFile) << " in\n"; + ost << "Could not find " << cmQtAutoGen::Quoted(searchFile) << " in\n"; for (const std::string& testFile : testFiles) { - ost << " " << Quoted(testFile) << "\n"; + ost << " " << cmQtAutoGen::Quoted(testFile) << "\n"; } - this->LogError(ost.str()); + this->LogFileError(cmQtAutoGen::UIC, sourceFile, ost.str()); } return success; @@ -1475,11 +1503,10 @@ bool cmQtAutoGenerators::UicGenerateAll( { std::multimap collisions; if (this->NameCollisionTest(testMap, collisions)) { - std::ostringstream ost; - ost << "AutoUic: Error: The same ui_NAME.h file will be generated " - "from different sources.\n" - "To avoid this error rename the source files.\n"; - this->LogErrorNameCollision(ost.str(), collisions); + std::string msg = "The same ui_NAME.h file will be generated " + "from different sources.\n" + "To avoid this error rename the source files.\n"; + this->LogNameCollisionError(cmQtAutoGen::UIC, msg, collisions); return false; } } @@ -1549,12 +1576,11 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, // Command failed { std::ostringstream ost; - ost << "AutoUic: Error: uic process failed for\n"; - ost << Quoted(uicFileRel) << " needed by\n"; - ost << Quoted(realName) << "\n"; - ost << "AutoUic: Command:\n" << QuotedCommand(cmd) << "\n"; - ost << "AutoUic: Command output:\n" << output << "\n"; - this->LogError(ost.str()); + ost << "uic failed for\n" + << " " << cmQtAutoGen::Quoted(uiInputFile) << "\n" + << "needed by\n" + << " " << cmQtAutoGen::Quoted(realName); + this->LogCommandError(cmQtAutoGen::UIC, ost.str(), cmd, output); } cmSystemTools::RemoveFile(uicFileAbs); this->UicRunFailed = true; @@ -1622,7 +1648,7 @@ bool cmQtAutoGenerators::RccGenerateFile(const RccJob& rccJob) files = &readFiles; } else { files = nullptr; - this->LogError(error); + this->LogFileError(cmQtAutoGen::RCC, rccJob.QrcFile, error); this->RccRunFailed = true; } } @@ -1659,15 +1685,9 @@ bool cmQtAutoGenerators::RccGenerateFile(const RccJob& rccJob) // Success rccGenerated = true; } else { - // Command failed - { - std::ostringstream ost; - ost << "AutoRcc: Error: rcc process failed for\n"; - ost << Quoted(rccFileRel) << "\n"; - ost << "AutoRcc: Command:\n" << QuotedCommand(cmd) << "\n"; - ost << "AutoRcc: Command output:\n" << output << "\n"; - this->LogError(ost.str()); - } + this->LogCommandError(cmQtAutoGen::RCC, "rcc failed for\n " + + cmQtAutoGen::Quoted(rccJob.QrcFile), + cmd, output); cmSystemTools::RemoveFile(rccFileAbs); this->RccRunFailed = true; } @@ -1702,7 +1722,8 @@ bool cmQtAutoGenerators::RccGenerateFile(const RccJob& rccJob) } else if (rccGenerated) { // Only touch wrapper file if the content matches if (this->Verbose) { - this->LogInfo("Touching RCC wrapper " + wrapperFileRel); + this->LogInfo(cmQtAutoGen::RCC, + "Touching RCC wrapper " + wrapperFileRel); } cmSystemTools::Touch(wrapperFileAbs, false); } @@ -1711,25 +1732,6 @@ bool cmQtAutoGenerators::RccGenerateFile(const RccJob& rccJob) return rccGenerated; } -void cmQtAutoGenerators::LogErrorNameCollision( - const std::string& message, - const std::multimap& collisions) const -{ - std::ostringstream ost; - // Add message - if (!message.empty()) { - ost << message; - if (message[message.size() - 1] != '\n') { - ost << '\n'; - } - } - // Append collision list - for (const auto& item : collisions) { - ost << " " << item.first << " : " << item.second << '\n'; - } - this->LogError(ost.str()); -} - void cmQtAutoGenerators::LogBold(const std::string& message) const { cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue | @@ -1737,41 +1739,137 @@ void cmQtAutoGenerators::LogBold(const std::string& message) const message.c_str(), true, this->ColorOutput); } -void cmQtAutoGenerators::LogInfo(const std::string& message) const +void cmQtAutoGenerators::LogInfo(cmQtAutoGen::GeneratorType genType, + const std::string& message) const { - std::string msg(message); - if (!msg.empty()) { - if (msg[msg.size() - 1] != '\n') { - msg.push_back('\n'); - } - cmSystemTools::Stdout(msg.c_str(), msg.size()); + 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(const std::string& message) const +void cmQtAutoGenerators::LogWarning(cmQtAutoGen::GeneratorType genType, + const std::string& message) const { - std::string msg(message); - if (!msg.empty()) { - if (msg[msg.size() - 1] != '\n') { - msg.push_back('\n'); - } - // Append empty line + 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'); - cmSystemTools::Stdout(msg.c_str(), msg.size()); } + msg += "\n"; + cmSystemTools::Stdout(msg.c_str(), msg.size()); } -void cmQtAutoGenerators::LogError(const std::string& message) const +void cmQtAutoGenerators::LogFileWarning(cmQtAutoGen::GeneratorType genType, + const std::string& filename, + const std::string& message) const { - std::string msg(message); - if (!msg.empty()) { - if (msg[msg.size() - 1] != '\n') { - msg.push_back('\n'); + std::string emsg = " "; + emsg += cmQtAutoGen::Quoted(filename); + emsg += "\n"; + // Message + emsg += message; + this->LogWarning(genType, emsg); +} + +void cmQtAutoGenerators::LogError(cmQtAutoGen::GeneratorType genType, + const std::string& message) const +{ + std::string msg; + msg.push_back('\n'); + msg = cmQtAutoGen::GeneratorName(genType); + msg += " error:"; + 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 += "\n"; + cmSystemTools::Stderr(msg.c_str(), msg.size()); +} + +void cmQtAutoGenerators::LogFileError(cmQtAutoGen::GeneratorType genType, + const std::string& filename, + const std::string& message) const +{ + std::string emsg = " "; + emsg += cmQtAutoGen::Quoted(filename); + emsg += "\n"; + // Message + emsg += message; + this->LogError(genType, emsg); +} + +void cmQtAutoGenerators::LogNameCollisionError( + cmQtAutoGen::GeneratorType genType, const std::string& message, + const std::multimap& collisions) const +{ + std::string emsg; + // Add message + if (!message.empty()) { + emsg += message; + if (emsg.back() != '\n') { + emsg.push_back('\n'); } - // Append empty line + } + // Append collision list + for (const auto& item : collisions) { + emsg += " "; + emsg += item.first; + emsg += " -> "; + emsg += item.second; + emsg += "\n"; + } + this->LogError(genType, emsg); +} + +void cmQtAutoGenerators::LogCommandError( + cmQtAutoGen::GeneratorType genType, const std::string& message, + const std::vector& command, const std::string& output) const +{ + std::string msg; + msg.push_back('\n'); + msg += cmQtAutoGen::GeneratorName(genType); + msg += " subprocess error: "; + msg += message; + if (msg.back() != '\n') { + msg.push_back('\n'); + } + msg.push_back('\n'); + msg += "Command\n"; + msg += "-------\n"; + msg += QuotedCommand(command); + if (msg.back() != '\n') { + msg.push_back('\n'); + } + msg.push_back('\n'); + msg += "Output\n"; + msg += "------\n"; + msg += output; + if (msg.back() != '\n') { msg.push_back('\n'); - cmSystemTools::Stderr(msg.c_str(), msg.size()); } + msg += "\n"; + cmSystemTools::Stderr(msg.c_str(), msg.size()); } /** @@ -1832,10 +1930,8 @@ bool cmQtAutoGenerators::MakeParentDirectory( if (!dirName.empty()) { success = cmSystemTools::MakeDirectory(dirName); if (!success) { - std::string error = cmQtAutoGen::GeneratorName(genType); - error += ": Error: Parent directory creation failed for "; - error += Quoted(filename); - this->LogError(error); + this->LogFileError(genType, filename, + "Could not create parent directory"); } } return success; @@ -1867,20 +1963,14 @@ bool cmQtAutoGenerators::FileWrite(cmQtAutoGen::GeneratorType genType, outfile << content; // Check for write errors if (!outfile.good()) { - error = cmQtAutoGen::GeneratorName(genType); - error += ": Error: File writing failed\n"; - error += " "; - error += Quoted(filename); + error = "File writing failed"; } } else { - error = cmQtAutoGen::GeneratorName(genType); - error += ": Error: Opening file for writing failed\n"; - error += " "; - error += Quoted(filename); + error = "Opening file for writing failed"; } } if (!error.empty()) { - this->LogError(error); + this->LogFileError(genType, filename, error); return false; } return true; @@ -1891,17 +1981,18 @@ bool cmQtAutoGenerators::FileWrite(cmQtAutoGen::GeneratorType genType, * @return True on success */ bool cmQtAutoGenerators::RunCommand(const std::vector& command, - std::string& output, bool verbose) const + std::string& output) const { // Log command if (this->Verbose) { - this->LogInfo(QuotedCommand(command)); + 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, - verbose ? cmSystemTools::OUTPUT_MERGE : cmSystemTools::OUTPUT_NONE); + command, &output, &output, &retVal, nullptr, cmSystemTools::OUTPUT_NONE); return (res && (retVal == 0)); } diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index d7f4f63..1bacd49 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -112,6 +112,9 @@ private: const std::string& fileName, const std::string& contentText, std::map>& includedUis); + std::string MocMacroNamesString() const; + std::string MocHeaderSuffixesString() const; + bool MocParseSourceContent( const std::string& absFilename, const std::string& contentText, std::map& mocsIncluded, @@ -146,15 +149,29 @@ private: bool RccGenerateAll(); bool RccGenerateFile(const RccJob& rccJob); - // -- Logging - void LogErrorNameCollision( - const std::string& message, - const std::multimap& collisions) const; + // -- Log info void LogBold(const std::string& message) const; - void LogInfo(const std::string& message) const; - void LogWarning(const std::string& message) const; - void LogError(const std::string& message) const; - void LogCommand(const std::vector& command) const; + void LogInfo(cmQtAutoGen::GeneratorType genType, + const std::string& message) const; + // -- Log warning + void LogWarning(cmQtAutoGen::GeneratorType genType, + const std::string& message) const; + void LogFileWarning(cmQtAutoGen::GeneratorType genType, + const std::string& filename, + const std::string& message) const; + // -- Log error + void LogError(cmQtAutoGen::GeneratorType genType, + const std::string& message) const; + void LogFileError(cmQtAutoGen::GeneratorType genType, + const std::string& filename, + const std::string& message) const; + void LogCommandError(cmQtAutoGen::GeneratorType genType, + const std::string& message, + const std::vector& command, + const std::string& output) const; + void LogNameCollisionError( + cmQtAutoGen::GeneratorType genType, const std::string& message, + const std::multimap& collisions) const; // -- Utility bool NameCollisionTest( @@ -169,8 +186,8 @@ private: bool FileWrite(cmQtAutoGen::GeneratorType genType, const std::string& filename, const std::string& content); - bool RunCommand(const std::vector& command, std::string& output, - bool verbose = true) const; + bool RunCommand(const std::vector& command, + std::string& output) const; bool FindHeader(std::string& header, const std::string& testBasePath) const; -- cgit v0.12 From c330d641af1f17fae5d58783cf46db76238ae000 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Fri, 1 Sep 2017 22:31:49 +0200 Subject: Autogen: Replace CM_AUTO_PTR with std::unique_ptr --- Source/cmQtAutoGenerators.cxx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 221a1ac..5ede9d5 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -21,7 +21,6 @@ #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" -#include "cm_auto_ptr.hxx" #include "cmake.h" #if defined(__APPLE__) @@ -148,15 +147,15 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory, snapshot.GetDirectory().SetCurrentBinary(targetDirectory); snapshot.GetDirectory().SetCurrentSource(targetDirectory); - CM_AUTO_PTR mf(new cmMakefile(&gg, snapshot)); - gg.SetCurrentMakefile(mf.get()); + std::unique_ptr makefile(new cmMakefile(&gg, snapshot)); + gg.SetCurrentMakefile(makefile.get()); bool success = false; - if (this->ReadAutogenInfoFile(mf.get(), targetDirectory, config)) { + if (this->ReadAutogenInfoFile(makefile.get(), targetDirectory, config)) { // Read old settings - this->SettingsFileRead(mf.get()); + this->SettingsFileRead(makefile.get()); // Init and run - this->Init(mf.get()); + this->Init(makefile.get()); if (this->RunAutogen()) { // Write current settings if (this->SettingsFileWrite()) { -- cgit v0.12 From 2e4dab087e87d9fb96f7e526ce5c75283f0212e5 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Fri, 1 Sep 2017 22:35:05 +0200 Subject: Autogen: Set CM_DISABLE_COPY in cmQtAutoGenerators --- Source/cmQtAutoGenerators.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 1bacd49..5d3ad74 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -18,6 +18,7 @@ class cmMakefile; class cmQtAutoGenerators { + CM_DISABLE_COPY(cmQtAutoGenerators) public: cmQtAutoGenerators(); bool Run(const std::string& targetDirectory, const std::string& config); -- cgit v0.12 From 734d236c07ee379454ab4c9f57c89645e83a892d Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Tue, 5 Sep 2017 22:20:58 +0200 Subject: Autogen: Smarter target dependency computation --- Source/cmQtAutoGenDigest.h | 2 - Source/cmQtAutoGeneratorInitializer.cxx | 169 ++++++++++++++++++-------------- 2 files changed, 97 insertions(+), 74 deletions(-) diff --git a/Source/cmQtAutoGenDigest.h b/Source/cmQtAutoGenDigest.h index e756a94..677c397 100644 --- a/Source/cmQtAutoGenDigest.h +++ b/Source/cmQtAutoGenDigest.h @@ -53,9 +53,7 @@ public: bool UicEnabled; bool RccEnabled; std::vector Headers; - std::vector HeadersGenerated; std::vector Sources; - std::vector SourcesGenerated; std::vector Qrcs; }; diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index 0cff825..22ac9d2 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -610,7 +610,8 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( const std::string workingDirectory = cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory()); const std::vector suffixes = GetConfigurationSuffixes(makefile); - std::set autogenDepends; + std::set autogenDependFiles; + std::set autogenDependTargets; std::vector autogenProvides; // Remove build directories on cleanup @@ -680,6 +681,8 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( } // Extract relevant source files + std::vector generatedSources; + std::vector generatedHeaders; { const std::string qrcExt = "qrc"; std::vector srcFiles; @@ -704,13 +707,13 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( const bool generated = sf->GetPropertyAsBool("GENERATED"); if (fileType == cmSystemTools::HEADER_FILE_FORMAT) { if (generated) { - digest.HeadersGenerated.push_back(absPath); + generatedHeaders.push_back(absPath); } else { digest.Headers.push_back(absPath); } } else { if (generated) { - digest.SourcesGenerated.push_back(absPath); + generatedSources.push_back(absPath); } else { digest.Sources.push_back(absPath); } @@ -747,7 +750,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( } // Process GENERATED sources and headers - if (!digest.SourcesGenerated.empty() || !digest.HeadersGenerated.empty()) { + if (!generatedSources.empty() || !generatedHeaders.empty()) { // Check status of policy CMP0071 bool policyAccept = false; bool policyWarn = false; @@ -770,30 +773,43 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( if (policyAccept) { // Accept GENERATED sources - for (const std::string& absFile : digest.HeadersGenerated) { + for (const std::string& absFile : generatedHeaders) { digest.Headers.push_back(absFile); + autogenDependFiles.insert(absFile); } - for (const std::string& absFile : digest.SourcesGenerated) { + for (const std::string& absFile : generatedSources) { digest.Sources.push_back(absFile); + autogenDependFiles.insert(absFile); } - } else if (policyWarn) { - std::ostringstream ost; - ost << cmPolicies::GetPolicyWarning(cmPolicies::CMP0071) << "\n"; - ost << "AUTOMOC,AUTOUIC: Ignoring GENERATED source file(s):\n"; - for (const std::string& absFile : digest.HeadersGenerated) { - ost << " " << cmQtAutoGen::Quoted(absFile) << "\n"; - } - for (const std::string& absFile : digest.SourcesGenerated) { - ost << " " << cmQtAutoGen::Quoted(absFile) << "\n"; + } else { + if (policyWarn) { + std::string msg; + msg += cmPolicies::GetPolicyWarning(cmPolicies::CMP0071); + msg += "\n"; + std::string tools; + if (digest.MocEnabled) { + tools += "AUTOMOC"; + } + if (digest.UicEnabled) { + if (!tools.empty()) { + tools += ","; + } + tools += "AUTOUIC"; + } + if (!generatedHeaders.empty()) { + msg.append(tools).append(": Ignoring GENERATED header file(s):\n"); + for (const std::string& absFile : generatedHeaders) { + msg.append(" ").append(cmQtAutoGen::Quoted(absFile)).append("\n"); + } + } + if (!generatedSources.empty()) { + msg.append(tools).append(": Ignoring GENERATED source file(s):\n"); + for (const std::string& absFile : generatedSources) { + msg.append(" ").append(cmQtAutoGen::Quoted(absFile)).append("\n"); + } + } + makefile->IssueMessage(cmake::AUTHOR_WARNING, msg); } - makefile->IssueMessage(cmake::AUTHOR_WARNING, ost.str()); - } - // Depend on GENERATED sources even when they are not processed by AUTOGEN - for (const std::string& absFile : digest.HeadersGenerated) { - autogenDepends.insert(absFile); - } - for (const std::string& absFile : digest.SourcesGenerated) { - autogenDepends.insert(absFile); } } // Sort headers and sources @@ -825,17 +841,15 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( const cmFilePathChecksum fpathCheckSum(makefile); for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { qrcDigest.PathChecksum = fpathCheckSum.getPart(qrcDigest.QrcFile); + // RCC output file name + std::string rccFile = autogenBuildDir + "/"; + rccFile += qrcDigest.PathChecksum; + rccFile += "/qrc_"; + rccFile += qrcDigest.QrcName; + rccFile += ".cpp"; + qrcDigest.RccFile = std::move(rccFile); } } - // RCC output file name - for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { - std::string rccFile = autogenBuildDir + "/"; - rccFile += qrcDigest.PathChecksum; - rccFile += "/qrc_"; - rccFile += qrcDigest.QrcName; - rccFile += ".cpp"; - qrcDigest.RccFile = std::move(rccFile); - } // RCC options for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { // Target options @@ -862,9 +876,10 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( // Register file at target AddGeneratedSource(target, qrcDigest.RccFile, cmQtAutoGen::RCC); autogenProvides.push_back(qrcDigest.RccFile); + // Dependencies if (qrcDigest.Generated) { - // Add GENERATED qrc file to the dependencies - autogenDepends.insert(qrcDigest.QrcFile); + // Add the GENERATED .qrc file to the dependencies + autogenDependFiles.insert(qrcDigest.QrcFile); } else { // Add the resource files to the dependencies { @@ -872,8 +887,9 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( if (cmQtAutoGen::RccListInputs(digest.QtVersionMajor, rcc, qrcDigest.QrcFile, qrcDigest.Resources, &error)) { - autogenDepends.insert(qrcDigest.Resources.begin(), - qrcDigest.Resources.end()); + for (const std::string& fileName : qrcDigest.Resources) { + autogenDependFiles.insert(fileName); + } } else { cmSystemTools::Error(error.c_str()); } @@ -890,33 +906,18 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( if (!deps.empty()) { std::vector extraDeps; cmSystemTools::ExpandListArgument(deps, extraDeps); - autogenDepends.insert(extraDeps.begin(), extraDeps.end()); - } - } - // Add utility target dependencies to the autogen target dependencies - { - const std::set& utils = target->Target->GetUtilities(); - for (const std::string& targetName : utils) { - if (makefile->FindTargetToUse(targetName) != nullptr) { - autogenDepends.insert(targetName); - } - } - } - // Add link library target dependencies to the autogen target dependencies - { - const auto& libVec = target->Target->GetOriginalLinkLibraries(); - for (const auto& item : libVec) { - if (makefile->FindTargetToUse(item.first) != nullptr) { - autogenDepends.insert(item.first); + for (const std::string& depName : extraDeps) { + // Allow target and file dependencies + auto* depTarget = makefile->FindTargetToUse(depName); + if (depTarget != nullptr) { + autogenDependTargets.insert(depTarget->GetName()); + } else { + autogenDependFiles.insert(depName); + } } } } - // Convert std::set to std::vector - const std::vector depends(autogenDepends.begin(), - autogenDepends.end()); - autogenDepends.clear(); - // Use PRE_BUILD on demand bool usePRE_BUILD = false; if (globalGen->GetName().find("Visual Studio") != std::string::npos) { @@ -928,38 +929,62 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( } // Disable PRE_BUILD in some cases if (usePRE_BUILD) { - // - Cannot use PRE_BUILD with GENERATED qrc files because the - // resource files themselves may not be sources within the target - // so VS may not know the target needs to re-build at all. - for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { - if (qrcDigest.Generated) { - usePRE_BUILD = false; - break; - } + // 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 (const std::string& depTarget : autogenDependTargets) { + target->Target->AddUtility(depTarget, makefile); + } + // 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 no_output; - cmCustomCommand cc(makefile, no_output, autogenProvides, depends, + const std::vector 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 { + + // Add utility target dependencies to the autogen target dependencies + for (const std::string& depTarget : target->Target->GetUtilities()) { + autogenDependTargets.insert(depTarget); + } + // Add link library target dependencies to the autogen target dependencies + for (const auto& item : target->Target->GetOriginalLinkLibraries()) { + if (makefile->FindTargetToUse(item.first) != nullptr) { + autogenDependTargets.insert(item.first); + } + } + + // Convert file dependencies std::set to std::vector + const std::vector autogenDepends(autogenDependFiles.begin(), + autogenDependFiles.end()); + // Create autogen target cmTarget* autogenTarget = makefile->AddUtilityCommand( autogenTargetName, true, workingDirectory.c_str(), - /*byproducts=*/autogenProvides, depends, commandLines, false, + /*byproducts=*/autogenProvides, autogenDepends, commandLines, false, autogenComment.c_str()); - + // Create autogen generator target localGen->AddGeneratorTarget( new cmGeneratorTarget(autogenTarget, localGen)); - // Set autogen target FOLDER + // Add additional autogen target dependencies to autogen target + for (const std::string& depTarget : autogenDependTargets) { + autogenTarget->AddUtility(depTarget, makefile); + } + + // Set FOLDER property in autogen target { const char* autogenFolder = makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER"); @@ -977,7 +1002,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( } // Add autogen target to the origin target dependencies - target->Target->AddUtility(autogenTargetName); + target->Target->AddUtility(autogenTargetName, makefile); } } -- cgit v0.12 From 2be0acb71e25cd425de71b047a0c77087e51c607 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Wed, 6 Sep 2017 13:18:47 +0200 Subject: Autogen: Tests: Add AUTOGEN_TARGET_DEPENDS test to mocDepends tests --- Tests/QtAutogen/mocDepends/CMakeLists.txt | 140 ++++++++++++++++------- Tests/QtAutogen/mocDepends/invalid.hpp.in | 1 - Tests/QtAutogen/mocDepends/object.hpp.in | 14 --- Tests/QtAutogen/mocDepends/object_invalid.hpp.in | 1 + Tests/QtAutogen/mocDepends/object_valid.hpp.in | 14 +++ Tests/QtAutogen/mocDepends/test1.cpp | 8 -- Tests/QtAutogen/mocDepends/test2.cpp | 9 -- Tests/QtAutogen/mocDepends/test3.cpp | 12 -- Tests/QtAutogen/mocDepends/test3.hpp | 16 --- Tests/QtAutogen/mocDepends/testATDFile.cpp | 9 ++ Tests/QtAutogen/mocDepends/testATDTarget.cpp | 9 ++ Tests/QtAutogen/mocDepends/testGenFile.cpp | 8 ++ Tests/QtAutogen/mocDepends/testGenLib.cpp | 12 ++ Tests/QtAutogen/mocDepends/testGenLib.hpp | 16 +++ Tests/QtAutogen/mocDepends/testGenTarget.cpp | 9 ++ 15 files changed, 176 insertions(+), 102 deletions(-) delete mode 100644 Tests/QtAutogen/mocDepends/invalid.hpp.in delete mode 100644 Tests/QtAutogen/mocDepends/object.hpp.in create mode 100644 Tests/QtAutogen/mocDepends/object_invalid.hpp.in create mode 100644 Tests/QtAutogen/mocDepends/object_valid.hpp.in delete mode 100644 Tests/QtAutogen/mocDepends/test1.cpp delete mode 100644 Tests/QtAutogen/mocDepends/test2.cpp delete mode 100644 Tests/QtAutogen/mocDepends/test3.cpp delete mode 100644 Tests/QtAutogen/mocDepends/test3.hpp create mode 100644 Tests/QtAutogen/mocDepends/testATDFile.cpp create mode 100644 Tests/QtAutogen/mocDepends/testATDTarget.cpp create mode 100644 Tests/QtAutogen/mocDepends/testGenFile.cpp create mode 100644 Tests/QtAutogen/mocDepends/testGenLib.cpp create mode 100644 Tests/QtAutogen/mocDepends/testGenLib.hpp create mode 100644 Tests/QtAutogen/mocDepends/testGenTarget.cpp diff --git a/Tests/QtAutogen/mocDepends/CMakeLists.txt b/Tests/QtAutogen/mocDepends/CMakeLists.txt index d71d740..8217b8d 100644 --- a/Tests/QtAutogen/mocDepends/CMakeLists.txt +++ b/Tests/QtAutogen/mocDepends/CMakeLists.txt @@ -15,81 +15,137 @@ else() endif() include_directories(${CMAKE_CURRENT_BINARY_DIR}) +set(CSD ${CMAKE_CURRENT_SOURCE_DIR}) +set(CBD ${CMAKE_CURRENT_BINARY_DIR}) -# -- Test 1: Depend on generated header +# -- Test dependency on header generated by a custom command +# # The ORIGIN_autogen target must depend on the same *GENERATED* source files as # the ORIGIN target. This is a requirement to ensure that all files for the # ORIGIN target are generated before the ORIGIN_autogen target is built. # -# This tests the dependency of the mocDepends1_autogen target of mocDepends1 -# to the source file test1_object.hpp, which is *GENERATED* by a custom command. -# If mocDepends1_autogen gets built *before* or in *parallel* to the -# custom command, the build will fail. That's because test1_object.hpp, -# which is required by mocDepends1_autogen, is only valid after the +# This tests the dependency of the mocDepGenFile_autogen target of +# mocDepGenFile to the source file GenFile.hpp, which is *GENERATED* +# by a custom command. +# If mocDepGenFile_autogen gets built *before* or in *parallel* to the +# custom command, the build will fail. That's because GenFile.hpp, +# which is required by mocDepGenFile_autogen, is only valid after the # custom command has been completed. # # The sleep seconds artificially increase the build time of the custom command # to simulate a slow file generation process that takes longer to run than -# the build of the mocDepends1_autogen target. +# the build of the mocDepGenFile_autogen target. add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/test1_object.hpp - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/invalid.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/test1_object.hpp + OUTPUT ${CBD}/GenFile.hpp + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/object_invalid.hpp.in ${CBD}/GenFile.hpp COMMAND ${CMAKE_COMMAND} -E sleep 3 - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/object.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/test1_object.hpp) + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/object_valid.hpp.in ${CBD}/GenFile.hpp) + +add_executable(mocDepGenFile testGenFile.cpp ${CBD}/GenFile.hpp) +target_link_libraries(mocDepGenFile ${QT_CORE_TARGET}) +set_target_properties(mocDepGenFile PROPERTIES AUTOMOC TRUE) -add_executable(mocDepends1 test1.cpp ${CMAKE_CURRENT_BINARY_DIR}/test1_object.hpp) -target_link_libraries(mocDepends1 ${QT_CORE_TARGET}) -set_target_properties(mocDepends1 PROPERTIES AUTOMOC TRUE) -# -- Test 2: Depend on header generating target +# -- Test dependency on header generating custom target +# # The ORIGIN_autogen target must depend on the same user defined targets # as the ORIGIN target. This is a requirement to ensure that all files for the # ORIGIN target are generated before the ORIGIN_autogen target is built. # -# This tests the dependency of the mocDepends2_autogen target of mocDepends2 -# to the utility target mocDepends2Object. If mocDepends2_autogen gets built -# *before* or in *parallel* to mocDepends2Object, the build will fail. That's -# because test2_object.hpp, which is required by mocDepends2_autogen, -# is only valid after the mocDepends2Object build has been completed. +# This tests the dependency of the mocDepTarget_autogen target of +# mocDepTarget to the utility target mocDepTargetUtil. +# If mocDepTarget_autogen gets built *before* or in *parallel* to +# mocDepTargetUtil, the build will fail. That's +# because GenTarget.hpp, which is required by mocDepTarget_autogen, +# is only valid after the mocDepTargetUtil build has been completed. # -# The sleep seconds artificially increase the build time of mocDepends2Object +# The sleep seconds artificially increase the build time of mocDepTargetUtil # to simulate a slow utility target build that takes longer to run than -# the build of the mocDepends2_autogen target. -add_custom_target(mocDepends2Object - BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/test2_object.hpp - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/invalid.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/test2_object.hpp +# the build of the mocDepTarget_autogen target. +add_custom_target(mocDepTargetUtil + BYPRODUCTS ${CBD}/GenTarget.hpp + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/object_invalid.hpp.in ${CBD}/GenTarget.hpp COMMAND ${CMAKE_COMMAND} -E sleep 3 - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/object.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/test2_object.hpp) + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/object_valid.hpp.in ${CBD}/GenTarget.hpp) + +add_executable(mocDepTarget testGenTarget.cpp) +target_link_libraries(mocDepTarget ${QT_CORE_TARGET}) +set_target_properties(mocDepTarget PROPERTIES AUTOMOC TRUE) +add_dependencies(mocDepTarget mocDepTargetUtil) -add_executable(mocDepends2 test2.cpp) -target_link_libraries(mocDepends2 ${QT_CORE_TARGET}) -set_target_properties(mocDepends2 PROPERTIES AUTOMOC TRUE) -add_dependencies(mocDepends2 mocDepends2Object) # -- Test 3: Depend on generated linked library # The ORIGIN_autogen target must depend on the same linked libraries # as the ORIGIN target. This is a requirement to ensure that all files for the # ORIGIN target are generated before the ORIGIN_autogen target is built. # -# This tests the dependency of the mocDepends3_autogen target of mocDepends3 -# to the user generated library SimpleLib, which mocDepends3 links to. -# If mocDepends3_autogen gets built *before* or in *parallel* to SimpleLib, +# This tests the dependency of the mocDepGenLib_autogen target of mocDepGenLib +# to the user generated library SimpleLib, which mocDepGenLib links to. +# If mocDepGenLib_autogen gets built *before* or in *parallel* to SimpleLib, # the build will fail. That's because simpleLib.hpp, which is required by -# mocDepends3_autogen, is only valid after the SimpleLib build has been +# mocDepGenLib_autogen, is only valid after the SimpleLib build has been # completed. # # The sleep seconds artificially increase the build time of SimpleLib # to simulate a slow utility library build that takes longer to run than -# the build of the mocDepends3_autogen target. +# the build of the mocDepGenLib_autogen target. add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.cpp - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/invalid.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp + OUTPUT ${CBD}/simpleLib.hpp ${CBD}/simpleLib.cpp + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/object_invalid.hpp.in ${CBD}/simpleLib.hpp COMMAND ${CMAKE_COMMAND} -E sleep 3 - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/simpleLib.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/simpleLib.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.cpp) -add_library(SimpleLib STATIC ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.cpp) + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/simpleLib.hpp.in ${CBD}/simpleLib.hpp + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/simpleLib.cpp.in ${CBD}/simpleLib.cpp) +add_library(SimpleLib STATIC ${CBD}/simpleLib.hpp ${CBD}/simpleLib.cpp) target_link_libraries(SimpleLib ${QT_CORE_TARGET}) -add_executable(mocDepends3 test3.cpp) -target_link_libraries(mocDepends3 SimpleLib ${QT_CORE_TARGET}) -set_target_properties(mocDepends3 PROPERTIES AUTOMOC TRUE) +add_executable(mocDepGenLib testGenLib.cpp) +target_link_libraries(mocDepGenLib SimpleLib ${QT_CORE_TARGET}) +set_target_properties(mocDepGenLib PROPERTIES AUTOMOC TRUE) + + +# -- Test AUTOGEN_TARGET_DEPENDS with GENERATED file dependency +# +# This tests the dependency of the mocDepATDFile_autogen target of +# mocDepATDTarget to the utility target mocDepATDFileUtil. +# If mocDepATDFile_autogen gets built *before* or in *parallel* to +# mocDepATDFileUtil, the build will fail. That's +# because ATDFile.hpp, which is required by mocDepATDFile_autogen, +# is only valid after the mocDepATDFileUtil build has been completed. +# +# The sleep seconds artificially increase the build time of +# mocDepATDFileUtil to simulate a slow utility target build that takes +# longer to run than the build of the mocDepATDFile_autogen target. +add_custom_command( + OUTPUT ${CBD}/ATDFile.hpp + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/object_invalid.hpp.in ${CBD}/ATDFile.hpp + COMMAND ${CMAKE_COMMAND} -E sleep 3 + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/object_valid.hpp.in ${CBD}/ATDFile.hpp) + +add_executable(mocDepATDFile testATDFile.cpp) +target_link_libraries(mocDepATDFile ${QT_CORE_TARGET}) +set_target_properties(mocDepATDFile PROPERTIES AUTOMOC TRUE) +set_target_properties(mocDepATDFile PROPERTIES AUTOGEN_TARGET_DEPENDS ${CBD}/ATDFile.hpp) + + +# -- Test AUTOGEN_TARGET_DEPENDS with target dependency +# +# This tests the dependency of the mocDepATDTarget_autogen target of +# mocDepATDTarget to the utility target mocDepATDTargetUtil. +# If mocDepATDTarget_autogen gets built *before* or in *parallel* to +# mocDepATDTargetUtil, the build will fail. That's +# because ATDTarget.hpp, which is required by mocDepATDTarget_autogen, +# is only valid after the mocDepATDTargetUtil build has been completed. +# +# The sleep seconds artificially increase the build time of +# mocDepATDTargetUtil to simulate a slow utility target build that takes +# longer to run than the build of the mocDepATDTarget_autogen target. +add_custom_target(mocDepATDTargetUtil + BYPRODUCTS ${CBD}/ATDTarget.hpp + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/object_invalid.hpp.in ${CBD}/ATDTarget.hpp + COMMAND ${CMAKE_COMMAND} -E sleep 3 + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/object_valid.hpp.in ${CBD}/ATDTarget.hpp) + +add_executable(mocDepATDTarget testATDTarget.cpp) +target_link_libraries(mocDepATDTarget ${QT_CORE_TARGET}) +set_target_properties(mocDepATDTarget PROPERTIES AUTOMOC TRUE) +set_target_properties(mocDepATDTarget PROPERTIES AUTOGEN_TARGET_DEPENDS mocDepATDTargetUtil) diff --git a/Tests/QtAutogen/mocDepends/invalid.hpp.in b/Tests/QtAutogen/mocDepends/invalid.hpp.in deleted file mode 100644 index 854d9a1..0000000 --- a/Tests/QtAutogen/mocDepends/invalid.hpp.in +++ /dev/null @@ -1 +0,0 @@ -#ifndef diff --git a/Tests/QtAutogen/mocDepends/object.hpp.in b/Tests/QtAutogen/mocDepends/object.hpp.in deleted file mode 100644 index f364f7c..0000000 --- a/Tests/QtAutogen/mocDepends/object.hpp.in +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef OBJECT_HPP -#define OBJECT_HPP - -#include - -class Object : public QObject -{ - Q_OBJECT -public: - Q_SLOT - void aSlot(){}; -}; - -#endif diff --git a/Tests/QtAutogen/mocDepends/object_invalid.hpp.in b/Tests/QtAutogen/mocDepends/object_invalid.hpp.in new file mode 100644 index 0000000..854d9a1 --- /dev/null +++ b/Tests/QtAutogen/mocDepends/object_invalid.hpp.in @@ -0,0 +1 @@ +#ifndef diff --git a/Tests/QtAutogen/mocDepends/object_valid.hpp.in b/Tests/QtAutogen/mocDepends/object_valid.hpp.in new file mode 100644 index 0000000..f364f7c --- /dev/null +++ b/Tests/QtAutogen/mocDepends/object_valid.hpp.in @@ -0,0 +1,14 @@ +#ifndef OBJECT_HPP +#define OBJECT_HPP + +#include + +class Object : public QObject +{ + Q_OBJECT +public: + Q_SLOT + void aSlot(){}; +}; + +#endif diff --git a/Tests/QtAutogen/mocDepends/test1.cpp b/Tests/QtAutogen/mocDepends/test1.cpp deleted file mode 100644 index 002dfd8..0000000 --- a/Tests/QtAutogen/mocDepends/test1.cpp +++ /dev/null @@ -1,8 +0,0 @@ - -#include "test1_object.hpp" - -int main() -{ - Object obj; - return 0; -} diff --git a/Tests/QtAutogen/mocDepends/test2.cpp b/Tests/QtAutogen/mocDepends/test2.cpp deleted file mode 100644 index 3fd845e..0000000 --- a/Tests/QtAutogen/mocDepends/test2.cpp +++ /dev/null @@ -1,9 +0,0 @@ - -#include "moc_test2_object.cpp" -#include "test2_object.hpp" - -int main() -{ - Object obj; - return 0; -} diff --git a/Tests/QtAutogen/mocDepends/test3.cpp b/Tests/QtAutogen/mocDepends/test3.cpp deleted file mode 100644 index a009598..0000000 --- a/Tests/QtAutogen/mocDepends/test3.cpp +++ /dev/null @@ -1,12 +0,0 @@ - -#include "test3.hpp" - -int main() -{ - SimpleLib libObject; - LObject lobject; - return 0; -} - -// AUTOMOC the SimpleLib header simpleLib.hpp -#include "moc_simpleLib.cpp" diff --git a/Tests/QtAutogen/mocDepends/test3.hpp b/Tests/QtAutogen/mocDepends/test3.hpp deleted file mode 100644 index 408335b..0000000 --- a/Tests/QtAutogen/mocDepends/test3.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef TEST3_HPP -#define TEST3_HPP - -#include "simpleLib.hpp" -#include - -// This object triggers the AUTOMOC on this file -class LObject : public QObject -{ - Q_OBJECT -public: - Q_SLOT - void aSlot(){}; -}; - -#endif diff --git a/Tests/QtAutogen/mocDepends/testATDFile.cpp b/Tests/QtAutogen/mocDepends/testATDFile.cpp new file mode 100644 index 0000000..6bddfcd --- /dev/null +++ b/Tests/QtAutogen/mocDepends/testATDFile.cpp @@ -0,0 +1,9 @@ + +#include "ATDFile.hpp" +#include "moc_ATDFile.cpp" + +int main() +{ + Object obj; + return 0; +} diff --git a/Tests/QtAutogen/mocDepends/testATDTarget.cpp b/Tests/QtAutogen/mocDepends/testATDTarget.cpp new file mode 100644 index 0000000..831fc26 --- /dev/null +++ b/Tests/QtAutogen/mocDepends/testATDTarget.cpp @@ -0,0 +1,9 @@ + +#include "ATDTarget.hpp" +#include "moc_ATDTarget.cpp" + +int main() +{ + Object obj; + return 0; +} diff --git a/Tests/QtAutogen/mocDepends/testGenFile.cpp b/Tests/QtAutogen/mocDepends/testGenFile.cpp new file mode 100644 index 0000000..7df6e13 --- /dev/null +++ b/Tests/QtAutogen/mocDepends/testGenFile.cpp @@ -0,0 +1,8 @@ + +#include "GenFile.hpp" + +int main() +{ + Object obj; + return 0; +} diff --git a/Tests/QtAutogen/mocDepends/testGenLib.cpp b/Tests/QtAutogen/mocDepends/testGenLib.cpp new file mode 100644 index 0000000..c14e159 --- /dev/null +++ b/Tests/QtAutogen/mocDepends/testGenLib.cpp @@ -0,0 +1,12 @@ + +#include "testGenLib.hpp" + +int main() +{ + SimpleLib libObject; + LObject lobject; + return 0; +} + +// Depend on and AUTOMOC the SimpleLib header simpleLib.hpp +#include "moc_simpleLib.cpp" diff --git a/Tests/QtAutogen/mocDepends/testGenLib.hpp b/Tests/QtAutogen/mocDepends/testGenLib.hpp new file mode 100644 index 0000000..408335b --- /dev/null +++ b/Tests/QtAutogen/mocDepends/testGenLib.hpp @@ -0,0 +1,16 @@ +#ifndef TEST3_HPP +#define TEST3_HPP + +#include "simpleLib.hpp" +#include + +// This object triggers the AUTOMOC on this file +class LObject : public QObject +{ + Q_OBJECT +public: + Q_SLOT + void aSlot(){}; +}; + +#endif diff --git a/Tests/QtAutogen/mocDepends/testGenTarget.cpp b/Tests/QtAutogen/mocDepends/testGenTarget.cpp new file mode 100644 index 0000000..911076e --- /dev/null +++ b/Tests/QtAutogen/mocDepends/testGenTarget.cpp @@ -0,0 +1,9 @@ + +#include "GenTarget.hpp" +#include "moc_GenTarget.cpp" + +int main() +{ + Object obj; + return 0; +} -- cgit v0.12 From 6739a12571bfa8b97b00740981e9f6eb5195529f Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Wed, 6 Sep 2017 16:10:47 +0200 Subject: Autogen: Doc: Add Visual Studio PRE_BUILD note to cmake-qt.rst --- Help/manual/cmake-qt.7.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Help/manual/cmake-qt.7.rst b/Help/manual/cmake-qt.7.rst index 55121df..7052e0a 100644 --- a/Help/manual/cmake-qt.7.rst +++ b/Help/manual/cmake-qt.7.rst @@ -214,6 +214,24 @@ overrides options from the :prop_tgt:`AUTORCC_OPTIONS` target property. Source files can be excluded from :prop_tgt:`AUTORCC` processing by enabling :prop_sf:`SKIP_AUTORCC` or the broader :prop_sf:`SKIP_AUTOGEN`. +Visual Studio Generators +======================== + +When using the :manual:`Visual Studio generators ` +CMake tries to use a ``PRE_BUILD`` +:command:`custom command ` instead +of a :command:`custom target ` for autogen. +``PRE_BUILD`` can't be used when the autogen target depends on files. +This happens when + +- :prop_tgt:`AUTOMOC` or :prop_tgt:`AUTOUIC` is enabled and the origin target + depends on :prop_sf:`GENERATED` files which aren't excluded from autogen by + :prop_sf:`SKIP_AUTOMOC`, :prop_sf:`SKIP_AUTOUIC`, :prop_sf:`SKIP_AUTOGEN` + or :policy:`CMP0071` +- :prop_tgt:`AUTORCC` is enabled and a ``.qrc`` file is listed in + the origin target sources +- :prop_tgt:`AUTOGEN_TARGET_DEPENDS` lists a source file + qtmain.lib on Windows ===================== -- cgit v0.12