diff options
author | Sebastian Holtermann <sebholt@xwmw.org> | 2017-08-26 11:59:57 (GMT) |
---|---|---|
committer | Sebastian Holtermann <sebholt@xwmw.org> | 2017-09-07 15:53:18 (GMT) |
commit | d1e5eb849704f73d646f64105d44807f3de50e48 (patch) | |
tree | 2246c9fd4e76d5f6eecdf42372d7c28adfc19b0a /Source | |
parent | 25ac91a715ee5f21fd169c47d55e02234c00915f (diff) | |
download | CMake-d1e5eb849704f73d646f64105d44807f3de50e48.zip CMake-d1e5eb849704f73d646f64105d44807f3de50e48.tar.gz CMake-d1e5eb849704f73d646f64105d44807f3de50e48.tar.bz2 |
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.
Diffstat (limited to 'Source')
-rw-r--r-- | Source/CMakeLists.txt | 5 | ||||
-rw-r--r-- | Source/cmGlobalGenerator.cxx | 74 | ||||
-rw-r--r-- | Source/cmGlobalGenerator.h | 4 | ||||
-rw-r--r-- | Source/cmQtAutoGen.cxx (renamed from Source/cmQtAutoGeneratorCommon.cxx) | 49 | ||||
-rw-r--r-- | Source/cmQtAutoGen.h (renamed from Source/cmQtAutoGeneratorCommon.h) | 18 | ||||
-rw-r--r-- | Source/cmQtAutoGenDigest.h | 62 | ||||
-rw-r--r-- | Source/cmQtAutoGeneratorInitializer.cxx | 784 | ||||
-rw-r--r-- | Source/cmQtAutoGeneratorInitializer.h | 13 | ||||
-rw-r--r-- | Source/cmQtAutoGenerators.cxx | 300 | ||||
-rw-r--r-- | Source/cmQtAutoGenerators.h | 7 |
10 files changed, 658 insertions, 658 deletions
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<cmGeneratorTarget const*> 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<cmGeneratorTarget const*>::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<const cmGeneratorTarget*> -cmGlobalGenerator::CreateQtAutoGeneratorsTargets() +cmQtAutoGenDigestUPV cmGlobalGenerator::CreateQtAutoGeneratorsTargets() { - std::vector<const cmGeneratorTarget*> autogenTargets; + cmQtAutoGenDigestUPV autogenDigests; #ifdef CMAKE_BUILD_WITH_CMAKE - for (std::vector<cmLocalGenerator*>::const_iterator lgit = - this->LocalGenerators.begin(); - lgit != this->LocalGenerators.end(); ++lgit) { - cmLocalGenerator* localGen = *lgit; + for (cmLocalGenerator* localGen : this->LocalGenerators) { const std::vector<cmGeneratorTarget*>& targets = localGen->GetGeneratorTargets(); // Find targets that require AUTOGEN processing - std::vector<cmGeneratorTarget*> filteredTargets; - filteredTargets.reserve(targets.size()); - for (std::vector<cmGeneratorTarget*>::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<cmGeneratorTarget*>::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<const cmGeneratorTarget*> CreateQtAutoGeneratorsTargets(); + // Qt auto generators + cmQtAutoGenDigestUPV CreateQtAutoGeneratorsTargets(); std::string SelectMakeProgram(const std::string& makeProgram, const std::string& makeDefault = "") const; diff --git a/Source/cmQtAutoGeneratorCommon.cxx b/Source/cmQtAutoGen.cxx index a8e6b96..f1453b4 100644 --- a/Source/cmQtAutoGeneratorCommon.cxx +++ b/Source/cmQtAutoGen.cxx @@ -1,6 +1,6 @@ /* 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 "cmQtAutoGen.h" #include "cmAlgorithms.h" #include "cmSystemTools.h" @@ -10,6 +10,13 @@ #include <sstream> #include <stddef.h> +// - 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) @@ -41,7 +48,7 @@ static bool RccListInputsQt4(const std::string& fileName, if (errorMessage != nullptr) { std::ostringstream ost; ost << "AutoRcc: Error: Rcc file not readable:\n" - << cmQtAutoGeneratorCommon::Quoted(fileName) << "\n"; + << cmQtAutoGen::Quoted(fileName) << "\n"; *errorMessage = ost.str(); } allGood = false; @@ -156,7 +163,7 @@ static bool RccListInputsQt5(const std::string& rccCommand, if (errorMessage != nullptr) { std::ostringstream ost; ost << "AutoRcc: Error: Rcc lists unparsable output:\n" - << cmQtAutoGeneratorCommon::Quoted(eline) << "\n"; + << cmQtAutoGen::Quoted(eline) << "\n"; *errorMessage = ost.str(); } return false; @@ -173,9 +180,29 @@ static bool RccListInputsQt5(const std::string& rccCommand, // - Class definitions -const char* cmQtAutoGeneratorCommon::listSep = "@LSEP@"; +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 cmQtAutoGeneratorCommon::Quoted(const std::string& text) +std::string cmQtAutoGen::Quoted(const std::string& text) { static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a", "\b", "\\b", "\f", "\\f", "\n", "\\n", @@ -191,11 +218,11 @@ std::string cmQtAutoGeneratorCommon::Quoted(const std::string& text) return res; } -bool cmQtAutoGeneratorCommon::RccListInputs(const std::string& qtMajorVersion, - const std::string& rccCommand, - const std::string& fileName, - std::vector<std::string>& files, - std::string* errorMessage) +bool cmQtAutoGen::RccListInputs(const std::string& qtMajorVersion, + const std::string& rccCommand, + const std::string& fileName, + std::vector<std::string>& files, + std::string* errorMessage) { bool allGood = false; if (cmsys::SystemTools::FileExists(fileName.c_str())) { @@ -208,7 +235,7 @@ bool cmQtAutoGeneratorCommon::RccListInputs(const std::string& qtMajorVersion, if (errorMessage != nullptr) { std::ostringstream ost; ost << "AutoRcc: Error: Rcc file does not exist:\n" - << cmQtAutoGeneratorCommon::Quoted(fileName) << "\n"; + << cmQtAutoGen::Quoted(fileName) << "\n"; *errorMessage = ost.str(); } } diff --git a/Source/cmQtAutoGeneratorCommon.h b/Source/cmQtAutoGen.h index 23a882a..88fd0fc 100644 --- a/Source/cmQtAutoGeneratorCommon.h +++ b/Source/cmQtAutoGen.h @@ -1,27 +1,35 @@ /* 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 +#ifndef cmQtAutoGen_h +#define cmQtAutoGen_h #include "cmConfigure.h" // IWYU pragma: keep #include <string> #include <vector> -class cmQtAutoGeneratorCommon +/** \class cmQtAutoGen + * \brief Class used as namespace for QtAutogen related types and functions + */ +class cmQtAutoGen { - // - Types and statics public: - static const char* listSep; + 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); 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 <memory> +#include <string> +#include <vector> + +class cmGeneratorTarget; + +class cmQtAutoGenDigestQrc +{ +public: + cmQtAutoGenDigestQrc() + : Generated(false) + { + } + +public: + std::string QrcFile; + std::string RccFile; + bool Generated; + std::vector<std::string> Options; + std::vector<std::string> Resources; +}; + +/** \class cmQtAutoGenDigest + * \brief Filtered set of QtAutogen variables for a specific target + */ +class cmQtAutoGenDigest +{ +public: + cmQtAutoGenDigest(cmGeneratorTarget* target) + : Target(target) + , MocEnabled(false) + , UicEnabled(false) + , RccEnabled(false) + { + } + +public: + cmGeneratorTarget* Target; + std::string QtVersionMajor; + std::string QtVersionMinor; + bool MocEnabled; + bool UicEnabled; + bool RccEnabled; + std::vector<std::string> Headers; + std::vector<std::string> HeadersGenerated; + std::vector<std::string> Sources; + std::vector<std::string> SourcesGenerated; + std::vector<cmQtAutoGenDigestQrc> Qrcs; +}; + +// Utility types +typedef std::unique_ptr<cmQtAutoGenDigest> cmQtAutoGenDigestUP; +typedef std::vector<cmQtAutoGenDigestUP> cmQtAutoGenDigestUPV; + +#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 <algorithm> +#include <array> #include <map> #include <set> #include <sstream> @@ -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<std::string> GetConfigurationSuffixes(cmMakefile* makefile) std::vector<std::string> suffixes; if (AutogenMultiConfig(makefile->GetGlobalGenerator())) { makefile->GetConfigurations(suffixes); - for (std::vector<std::string>::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<std::string, 2> 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<std::string> sources; - std::vector<std::string> headers; + std::set<std::string> MocSkip; + std::set<std::string> UicSkip; - std::set<std::string> mocSkip; - std::set<std::string> uicSkip; - - std::map<std::string, std::string> configSuffix; - std::map<std::string, std::string> configMocIncludes; - std::map<std::string, std::string> configMocDefines; - std::map<std::string, std::string> configUicOptions; + std::map<std::string, std::string> ConfigMocIncludes; + std::map<std::string, std::string> ConfigMocDefines; + std::map<std::string, std::string> ConfigUicOptions; }; -static void SetupAcquireScanFiles(cmGeneratorTarget const* target, - bool mocEnabled, bool uicEnabled, - const std::vector<cmSourceFile*>& srcFiles, - AutogenSetup& setup) +static void SetupAcquireSkipFiles(cmQtAutoGenDigest const& digest, + cmQtAutoGenSetup& setup) { // Read skip files from makefile sources { const std::vector<cmSourceFile*>& allSources = - target->Makefile->GetSourceFiles(); - for (std::vector<cmSourceFile*>::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<cmSourceFile*>::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<std::string> 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<std::string>::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<std::string> 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<std::string>::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<std::string>::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<cmSourceFile*>& srcFiles = makefile->GetSourceFiles(); - for (std::vector<cmSourceFile*>::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<std::string>& opts, const std::vector<std::string>& fileOpts, bool isQt5) { - static const char* valueOptions[] = { "name", "root", "compress", - "threshold" }; + typedef std::vector<std::string>::iterator Iter; + typedef std::vector<std::string>::const_iterator CIter; + static const char* valueOptions[4] = { "name", "root", "compress", + "threshold" }; + std::vector<std::string> extraOpts; - for (std::vector<std::string>::const_iterator fit = fileOpts.begin(); - fit != fileOpts.end(); ++fit) { - std::vector<std::string>::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<std::string>& opts, if ((optName != fit->c_str()) && std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), cmStrCmp(optName)) != cmArrayEnd(valueOptions)) { - const std::vector<std::string>::iterator existValueIt(existingIt + 1); - const std::vector<std::string>::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<std::string>& 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<cmSourceFile*>& 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<std::string> rccFiles; std::vector<std::string> rccInputs; std::vector<std::string> rccFileFiles; std::vector<std::string> rccFileOptions; - std::vector<std::string> rccOptionsTarget; - - cmSystemTools::ExpandListArgument(GetSafeProperty(target, "AUTORCC_OPTIONS"), - rccOptionsTarget); - - for (std::vector<cmSourceFile*>::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<std::string> 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<std::string> rccOptions(rccOptionsTarget); - if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) { - std::vector<std::string> 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<std::string> suffixes = GetConfigurationSuffixes(makefile); - std::set<std::string> autogenDependsSet; + std::set<std::string> autogenDepends; std::vector<std::string> 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<std::string>::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<std::string> 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 += "_$<CONFIG>"; @@ -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<std::string> extraDepends; - cmSystemTools::ExpandListArgument(deps, extraDepends); - autogenDependsSet.insert(extraDepends.begin(), extraDepends.end()); - } - } - // Add utility target dependencies to the autogen dependencies - { - const std::set<std::string>& utils = target->Target->GetUtilities(); - for (std::set<std::string>::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<std::string> generatedSources; - std::vector<std::pair<std::string, bool>> qrcSources; { const std::string qrcExt = "qrc"; std::vector<cmSourceFile*> srcFiles; target->GetConfigCommonSourceFiles(srcFiles); - for (std::vector<cmSourceFile*>::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<std::string, bool>(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<std::string>::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<std::pair<std::string, bool>>::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<std::string> 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<std::string> 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<std::string> 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<std::string> extraDeps; + cmSystemTools::ExpandListArgument(deps, extraDeps); + autogenDepends.insert(extraDeps.begin(), extraDeps.end()); + } + } + // Add utility target dependencies to the autogen target dependencies + { + const std::set<std::string>& 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<std::string> autogenDepends(autogenDependsSet.begin(), - autogenDependsSet.end()); - // Disable PRE_BUILD on demand + const std::vector<std::string> 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<std::string>::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<std::string> no_output; - cmCustomCommand cc(makefile, no_output, autogenProvides, autogenDepends, + const std::vector<std::string> 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<std::string, std::string> configSuffix; if (AutogenMultiConfig(target->GetGlobalGenerator())) { - for (std::vector<std::string>::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<cmSourceFile*> 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<std::string, std::string>::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<std::string, std::string>::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<std::string, std::string>::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<std::string, std::string>::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 <string> 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 <algorithm> +#include <array> #include <assert.h> #include <list> #include <sstream> @@ -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<std::string>& command) { std::string res; - for (std::vector<std::string>::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<std::string, std::string>::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<std::string, std::string>& opts) { std::string result; - for (std::map<std::string, std::string>::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<std::string>& lst) -{ - std::string result; - if (!lst.empty()) { - const std::string separator = ","; - for (std::vector<std::string>::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<std::string> MocMacroNames; InfoGet(makefile, "AM_MOC_MACRO_NAMES", MocMacroNames); - for (std::vector<std::string>::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<std::string>::const_iterator dit = - mocDependFilters.begin(); - dit != mocDependFilters.end(); dit += 2) { + for (std::vector<std::string>::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<std::string> 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<const std::string*, 2> movePaths = { + { &this->ProjectBinaryDir, &this->ProjectSourceDir } + }; + for (const std::string* ppath : movePaths) { std::list<std::string>::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<std::string> frameworkPaths; - for (std::vector<std::string>::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<std::string>::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<std::string> uicHeaderFiles; // Parse sources - for (std::vector<std::string>::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<std::string>::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<MocMacroFilter>::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<std::string, std::set<std::string>>& mocDepends) { - for (std::vector<MocDependFilter>::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<std::string>& mocHeaderFiles, std::set<std::string>& uicHeaderFiles) const { - std::string basepaths[2]; + std::array<std::string, 2> 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<std::string>::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<std::string>::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<std::string> 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<std::string>::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<std::string> 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<std::string>::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<std::string>::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<std::string>::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<std::string>::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<std::string>& sourceIncs(sit->second); // insert new source/destination map std::map<std::string, std::string>& uiGenMap = sourceGenMap[source]; - for (std::vector<std::string>::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<std::string, - std::map<std::string, std::string>>::const_iterator it = - sourceGenMap.begin(); - it != sourceGenMap.end(); ++it) { - for (std::map<std::string, std::string>::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<std::string> 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<std::string>::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<std::string, std::string>::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<std::string>::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<std::string, std::string>& collisions) const { - typedef std::multimap<std::string, std::string>::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<std::string>& command, bool cmQtAutoGenerators::FindHeader(std::string& header, const std::string& testBasePath) const { - for (std::vector<std::string>::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<std::string>::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<std::string>::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 <map> @@ -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<std::string>& command, std::string& output, bool verbose = true) const; |