Commit d1e5eb84 authored by Sebastian Holtermann's avatar Sebastian Holtermann
Browse files

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.
parent 25ac91a7
......@@ -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@)
......@@ -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
......
......@@ -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(
......
......@@ -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;
......
/* 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();
}
}
......
/* 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);
......
/* 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
This diff is collapsed.
......@@ -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
This diff is collapsed.
......@@ -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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment