From 2e9199b291879d9a47759faa178fb2f35b12bd64 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Mon, 30 Jul 2018 09:18:13 +0200 Subject: cmLocalGenerator: Respect user requested implicit include directories order In ``cmLocalGenerator::GetIncludeDirectories`` append the user requested implicit include directories first, then append the remaining implicit include directories. By By doing so we keep the user requested order of implicit include directories. --- Source/cmLocalGenerator.cxx | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 647697a..a669477 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -960,15 +960,14 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector& dirs, } if (!stripImplicitDirs) { - if (!appendAllImplicitDirs) { - // Append only those implicit directories that were requested by the user - for (std::string const& i : implicitDirs) { - if (std::find(userDirs.begin(), userDirs.end(), i) != userDirs.end()) { - dirs.push_back(i); - } + // Append only implicit directories that were requested by the user + for (std::string const& i : implicitDirs) { + if (std::find(userDirs.begin(), userDirs.end(), i) != userDirs.end()) { + dirs.push_back(i); } - } else { - // Append all implicit directories + } + // Append remaining implicit directories on demand + if (appendAllImplicitDirs) { for (std::string const& i : implicitDirs) { if (std::find(dirs.begin(), dirs.end(), i) == dirs.end()) { dirs.push_back(i); -- cgit v0.12 From 5776639fbfe5b8da5ca7a4fbae31936cdeff6660 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Sun, 22 Jul 2018 14:26:16 +0200 Subject: Autogen: Pass absolute include path in info file --- Source/cmQtAutoGenInitializer.cxx | 39 +++++++++++++++++++------------------- Source/cmQtAutoGenInitializer.h | 2 ++ Source/cmQtAutoGeneratorMocUic.cxx | 13 +++++-------- Source/cmQtAutoGeneratorRcc.cxx | 4 +--- 4 files changed, 28 insertions(+), 30 deletions(-) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index fd9829f..19cdd39 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -244,6 +244,21 @@ bool cmQtAutoGenInitializer::InitCustomTargets() // Working directory this->DirWork = cbd; cmSystemTools::ConvertToUnixSlashes(this->DirWork); + + // Include directory + this->DirInclude = this->DirBuild; + this->DirInclude += "/include"; + if (this->MultiConfig) { + this->DirInclude += "_$"; + } + if (this->MultiConfig) { + for (std::string const& cfg : this->ConfigsList) { + std::string& dir = this->DirConfigInclude[cfg]; + dir = this->DirBuild; + dir += "/include_"; + dir += cfg; + } + } } // Autogen files @@ -305,12 +320,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets() // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES if (this->Moc.Enabled || this->Uic.Enabled || (this->Rcc.Enabled && this->MultiConfig)) { - std::string includeDir = this->DirBuild; - includeDir += "/include"; - if (this->MultiConfig) { - includeDir += "_$"; - } - this->Target->AddIncludeDirectory(includeDir, true); + this->Target->AddIncludeDirectory(this->DirInclude, true); } // Acquire rcc executable and features @@ -833,15 +843,6 @@ bool cmQtAutoGenInitializer::SetupCustomTargets() return false; } - // Configuration include directories - std::string includeDir = "include"; - std::map includeDirs; - for (std::string const& cfg : this->ConfigsList) { - std::string& dir = includeDirs[cfg]; - dir = "include_"; - dir += cfg; - } - // Generate autogen target info file if (this->Moc.Enabled || this->Uic.Enabled) { if (this->Moc.Enabled) { @@ -913,9 +914,9 @@ bool cmQtAutoGenInitializer::SetupCustomTargets() MfDef("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")); CWrite("AM_BUILD_DIR", this->DirBuild); if (this->MultiConfig) { - CWriteMap("AM_INCLUDE_DIR", includeDirs); + CWriteMap("AM_INCLUDE_DIR", this->DirConfigInclude); } else { - CWrite("AM_INCLUDE_DIR", includeDir); + CWrite("AM_INCLUDE_DIR", this->DirInclude); } ofs << "# Files\n"; @@ -1014,9 +1015,9 @@ bool cmQtAutoGenInitializer::SetupCustomTargets() ofs << "# Directories\n"; CWrite("ARCC_BUILD_DIR", this->DirBuild); if (this->MultiConfig) { - CWriteMap("ARCC_INCLUDE_DIR", includeDirs); + CWriteMap("ARCC_INCLUDE_DIR", this->DirConfigInclude); } else { - CWrite("ARCC_INCLUDE_DIR", includeDir); + CWrite("ARCC_INCLUDE_DIR", this->DirInclude); } ofs << "# Rcc executable\n"; diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 0999e0f..387b3bc 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -90,6 +90,8 @@ private: std::string DirInfo; std::string DirBuild; std::string DirWork; + std::string DirInclude; + std::map DirConfigInclude; // Sources std::vector Headers; std::vector Sources; diff --git a/Source/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoGeneratorMocUic.cxx index a6b0247..c364700 100644 --- a/Source/cmQtAutoGeneratorMocUic.cxx +++ b/Source/cmQtAutoGeneratorMocUic.cxx @@ -1247,14 +1247,11 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) return false; } // include directory - { - std::string dirRel = InfoGetConfig("AM_INCLUDE_DIR"); - if (dirRel.empty()) { - Log().ErrorFile(GeneratorT::GEN, InfoFile(), - "Autogen include directory missing"); - return false; - } - Base_.AutogenIncludeDir = Base_.AbsoluteBuildPath(dirRel); + Base_.AutogenIncludeDir = InfoGetConfig("AM_INCLUDE_DIR"); + if (Base_.AutogenIncludeDir.empty()) { + Log().ErrorFile(GeneratorT::GEN, InfoFile(), + "Autogen include directory missing"); + return false; } // - Files diff --git a/Source/cmQtAutoGeneratorRcc.cxx b/Source/cmQtAutoGeneratorRcc.cxx index e49599f..6caa0d8 100644 --- a/Source/cmQtAutoGeneratorRcc.cxx +++ b/Source/cmQtAutoGeneratorRcc.cxx @@ -141,9 +141,7 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile) // Compute rcc output file name if (IsMultiConfig()) { - RccFileOutput_ = AutogenBuildDir_; - RccFileOutput_ += '/'; - RccFileOutput_ += IncludeDir_; + RccFileOutput_ = IncludeDir_; RccFileOutput_ += '/'; RccFileOutput_ += MultiConfigOutput(); } else { -- cgit v0.12 From 8e0d70272d9be5149608ed7441852f53c48c180f Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Sun, 22 Jul 2018 14:52:02 +0200 Subject: Autogen: Move info file write code into methods --- Source/cmQtAutoGenInitializer.cxx | 369 ++++++++++++++++++++------------------ Source/cmQtAutoGenInitializer.h | 3 + 2 files changed, 198 insertions(+), 174 deletions(-) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 19cdd39..89eb5a6 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -214,6 +214,13 @@ bool cmQtAutoGenInitializer::InitCustomTargets() this->ConfigsList.push_back(this->ConfigDefault); } + // Parallel processing + this->Parallel = this->Target->GetSafeProperty("AUTOGEN_PARALLEL"); + if (this->Parallel.empty() || (this->Parallel == "AUTO")) { + // Autodetect number of CPUs + this->Parallel = std::to_string(GetParallelCPUCount()); + } + // Autogen target name this->AutogenTargetName = this->Target->GetName(); this->AutogenTargetName += "_autogen"; @@ -833,8 +840,6 @@ bool cmQtAutoGenInitializer::InitCustomTargets() bool cmQtAutoGenInitializer::SetupCustomTargets() { - cmMakefile* makefile = this->Target->Target->GetMakefile(); - // Create info directory on demand if (!cmSystemTools::MakeDirectory(this->DirInfo)) { std::string emsg = ("AutoGen: Could not create directory: "); @@ -851,43 +856,156 @@ bool cmQtAutoGenInitializer::SetupCustomTargets() if (this->Uic.Enabled) { this->SetupCustomTargetsUic(); } + // Write autogen target info files + if (!this->SetupWriteAutogenInfo()) { + return false; + } + } + + // Write AUTORCC info files + if (this->Rcc.Enabled && !this->SetupWriteRccInfo()) { + return false; + } + + return true; +} + +bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() +{ + cmMakefile* makefile = this->Target->Target->GetMakefile(); + + cmGeneratedFileStream ofs; + ofs.SetCopyIfDifferent(true); + ofs.Open(this->AutogenInfoFile.c_str(), false, true); + if (ofs) { + // Utility lambdas + auto CWrite = [&ofs](const char* key, std::string const& value) { + ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value) + << ")\n"; + }; + auto CWriteList = [&CWrite](const char* key, + std::vector const& list) { + CWrite(key, cmJoin(list, ";")); + }; + auto CWriteNestedLists = + [&CWrite](const char* key, + std::vector> const& lists) { + std::vector seplist; + for (const std::vector& list : lists) { + std::string blist = "{"; + blist += cmJoin(list, ";"); + blist += "}"; + seplist.push_back(std::move(blist)); + } + CWrite(key, cmJoin(seplist, cmQtAutoGen::ListSep)); + }; + auto CWriteSet = [&CWrite](const char* key, + std::set const& list) { + CWrite(key, cmJoin(list, ";")); + }; + auto CWriteMap = [&ofs](const char* key, + std::map const& map) { + for (auto const& item : map) { + ofs << "set(" << key << "_" << item.first << " " + << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; + } + }; + auto MfDef = [makefile](const char* key) { + return std::string(makefile->GetSafeDefinition(key)); + }; - // Parallel processing - this->Parallel = this->Target->GetSafeProperty("AUTOGEN_PARALLEL"); - if (this->Parallel.empty() || (this->Parallel == "AUTO")) { - // Autodetect number of CPUs - this->Parallel = std::to_string(GetParallelCPUCount()); + // Write + ofs << "# Meta\n"; + CWrite("AM_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE"); + CWrite("AM_PARALLEL", this->Parallel); + CWrite("AM_VERBOSITY", this->Verbosity); + + ofs << "# Directories\n"; + CWrite("AM_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR")); + CWrite("AM_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR")); + CWrite("AM_CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR")); + CWrite("AM_CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR")); + CWrite("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE", + MfDef("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")); + CWrite("AM_BUILD_DIR", this->DirBuild); + if (this->MultiConfig) { + CWriteMap("AM_INCLUDE_DIR", this->DirConfigInclude); + } else { + CWrite("AM_INCLUDE_DIR", this->DirInclude); + } + + ofs << "# Files\n"; + CWriteList("AM_SOURCES", this->Sources); + CWriteList("AM_HEADERS", this->Headers); + if (this->MultiConfig) { + std::map settingsFiles; + for (std::string const& cfg : this->ConfigsList) { + settingsFiles[cfg] = + AppendFilenameSuffix(this->AutogenSettingsFile, "_" + cfg); + } + CWriteMap("AM_SETTINGS_FILE", settingsFiles); + } else { + CWrite("AM_SETTINGS_FILE", this->AutogenSettingsFile); + } + + ofs << "# Qt\n"; + CWrite("AM_QT_VERSION_MAJOR", this->QtVersionMajor); + CWrite("AM_QT_MOC_EXECUTABLE", this->Moc.Executable); + CWrite("AM_QT_UIC_EXECUTABLE", this->Uic.Executable); + + if (this->Moc.Enabled) { + ofs << "# MOC settings\n"; + CWriteSet("AM_MOC_SKIP", this->Moc.Skip); + CWrite("AM_MOC_DEFINITIONS", this->Moc.Defines); + CWriteMap("AM_MOC_DEFINITIONS", this->Moc.ConfigDefines); + CWrite("AM_MOC_INCLUDES", this->Moc.Includes); + CWriteMap("AM_MOC_INCLUDES", this->Moc.ConfigIncludes); + CWrite("AM_MOC_OPTIONS", + this->Target->GetSafeProperty("AUTOMOC_MOC_OPTIONS")); + CWrite("AM_MOC_RELAXED_MODE", MfDef("CMAKE_AUTOMOC_RELAXED_MODE")); + CWrite("AM_MOC_MACRO_NAMES", + this->Target->GetSafeProperty("AUTOMOC_MACRO_NAMES")); + CWrite("AM_MOC_DEPEND_FILTERS", + this->Target->GetSafeProperty("AUTOMOC_DEPEND_FILTERS")); + CWrite("AM_MOC_PREDEFS_CMD", this->Moc.PredefsCmd); } + if (this->Uic.Enabled) { + ofs << "# UIC settings\n"; + CWriteSet("AM_UIC_SKIP", this->Uic.Skip); + CWrite("AM_UIC_TARGET_OPTIONS", this->Uic.Options); + CWriteMap("AM_UIC_TARGET_OPTIONS", this->Uic.ConfigOptions); + CWriteList("AM_UIC_OPTIONS_FILES", this->Uic.FileFiles); + CWriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->Uic.FileOptions); + CWriteList("AM_UIC_SEARCH_PATHS", this->Uic.SearchPaths); + } + } else { + std::string err = "AutoGen: Could not write file "; + err += this->AutogenInfoFile; + cmSystemTools::Error(err.c_str()); + return false; + } + + return true; +} + +bool cmQtAutoGenInitializer::SetupWriteRccInfo() +{ + cmMakefile* makefile = this->Target->Target->GetMakefile(); + + for (Qrc const& qrc : this->Rcc.Qrcs) { + // Register rcc info file as generated + makefile->AddCMakeOutputFile(qrc.InfoFile); + cmGeneratedFileStream ofs; ofs.SetCopyIfDifferent(true); - ofs.Open(this->AutogenInfoFile.c_str(), false, true); + ofs.Open(qrc.InfoFile.c_str(), false, true); if (ofs) { // Utility lambdas auto CWrite = [&ofs](const char* key, std::string const& value) { ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value) << ")\n"; }; - auto CWriteList = [&CWrite](const char* key, - std::vector const& list) { - CWrite(key, cmJoin(list, ";")); - }; - auto CWriteNestedLists = - [&CWrite](const char* key, - std::vector> const& lists) { - std::vector seplist; - for (const std::vector& list : lists) { - std::string blist = "{"; - blist += cmJoin(list, ";"); - blist += "}"; - seplist.push_back(std::move(blist)); - } - CWrite(key, cmJoin(seplist, cmQtAutoGen::ListSep)); - }; - auto CWriteSet = [&CWrite](const char* key, - std::set const& list) { - CWrite(key, cmJoin(list, ";")); - }; auto CWriteMap = [&ofs](const char* key, std::map const& map) { for (auto const& item : map) { @@ -895,152 +1013,50 @@ bool cmQtAutoGenInitializer::SetupCustomTargets() << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; } }; - auto MfDef = [makefile](const char* key) { - return std::string(makefile->GetSafeDefinition(key)); - }; // Write - ofs << "# Meta\n"; - CWrite("AM_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE"); - CWrite("AM_PARALLEL", this->Parallel); - CWrite("AM_VERBOSITY", this->Verbosity); - - ofs << "# Directories\n"; - CWrite("AM_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR")); - CWrite("AM_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR")); - CWrite("AM_CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR")); - CWrite("AM_CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR")); - CWrite("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE", - MfDef("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")); - CWrite("AM_BUILD_DIR", this->DirBuild); - if (this->MultiConfig) { - CWriteMap("AM_INCLUDE_DIR", this->DirConfigInclude); - } else { - CWrite("AM_INCLUDE_DIR", this->DirInclude); - } - - ofs << "# Files\n"; - CWriteList("AM_SOURCES", this->Sources); - CWriteList("AM_HEADERS", this->Headers); + ofs << "# Configurations\n"; + CWrite("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE"); + CWrite("ARCC_VERBOSITY", this->Verbosity); + ofs << "# Settings file\n"; if (this->MultiConfig) { std::map settingsFiles; for (std::string const& cfg : this->ConfigsList) { settingsFiles[cfg] = - AppendFilenameSuffix(this->AutogenSettingsFile, "_" + cfg); + AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg); } - CWriteMap("AM_SETTINGS_FILE", settingsFiles); + CWriteMap("ARCC_SETTINGS_FILE", settingsFiles); } else { - CWrite("AM_SETTINGS_FILE", this->AutogenSettingsFile); + CWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile); } - ofs << "# Qt\n"; - CWrite("AM_QT_VERSION_MAJOR", this->QtVersionMajor); - CWrite("AM_QT_MOC_EXECUTABLE", this->Moc.Executable); - CWrite("AM_QT_UIC_EXECUTABLE", this->Uic.Executable); - - if (this->Moc.Enabled) { - ofs << "# MOC settings\n"; - CWriteSet("AM_MOC_SKIP", this->Moc.Skip); - CWrite("AM_MOC_DEFINITIONS", this->Moc.Defines); - CWriteMap("AM_MOC_DEFINITIONS", this->Moc.ConfigDefines); - CWrite("AM_MOC_INCLUDES", this->Moc.Includes); - CWriteMap("AM_MOC_INCLUDES", this->Moc.ConfigIncludes); - CWrite("AM_MOC_OPTIONS", - this->Target->GetSafeProperty("AUTOMOC_MOC_OPTIONS")); - CWrite("AM_MOC_RELAXED_MODE", MfDef("CMAKE_AUTOMOC_RELAXED_MODE")); - CWrite("AM_MOC_MACRO_NAMES", - this->Target->GetSafeProperty("AUTOMOC_MACRO_NAMES")); - CWrite("AM_MOC_DEPEND_FILTERS", - this->Target->GetSafeProperty("AUTOMOC_DEPEND_FILTERS")); - CWrite("AM_MOC_PREDEFS_CMD", this->Moc.PredefsCmd); + ofs << "# Directories\n"; + CWrite("ARCC_BUILD_DIR", this->DirBuild); + if (this->MultiConfig) { + CWriteMap("ARCC_INCLUDE_DIR", this->DirConfigInclude); + } else { + CWrite("ARCC_INCLUDE_DIR", this->DirInclude); } - if (this->Uic.Enabled) { - ofs << "# UIC settings\n"; - CWriteSet("AM_UIC_SKIP", this->Uic.Skip); - CWrite("AM_UIC_TARGET_OPTIONS", this->Uic.Options); - CWriteMap("AM_UIC_TARGET_OPTIONS", this->Uic.ConfigOptions); - CWriteList("AM_UIC_OPTIONS_FILES", this->Uic.FileFiles); - CWriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->Uic.FileOptions); - CWriteList("AM_UIC_SEARCH_PATHS", this->Uic.SearchPaths); - } + ofs << "# Rcc executable\n"; + CWrite("ARCC_RCC_EXECUTABLE", this->Rcc.Executable); + CWrite("ARCC_RCC_LIST_OPTIONS", cmJoin(this->Rcc.ListOptions, ";")); + + ofs << "# Rcc job\n"; + CWrite("ARCC_LOCK_FILE", qrc.LockFile); + CWrite("ARCC_SOURCE", qrc.QrcFile); + CWrite("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum); + CWrite("ARCC_OUTPUT_NAME", cmSystemTools::GetFilenameName(qrc.RccFile)); + CWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";")); + CWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";")); } else { - std::string err = "AutoGen: Could not write file "; - err += this->AutogenInfoFile; + std::string err = "AutoRcc: Could not write file "; + err += qrc.InfoFile; cmSystemTools::Error(err.c_str()); return false; } } - // Generate auto RCC info files - if (this->Rcc.Enabled) { - for (Qrc const& qrc : this->Rcc.Qrcs) { - // Register rcc info file as generated - makefile->AddCMakeOutputFile(qrc.InfoFile); - - cmGeneratedFileStream ofs; - ofs.SetCopyIfDifferent(true); - ofs.Open(qrc.InfoFile.c_str(), false, true); - if (ofs) { - // Utility lambdas - auto CWrite = [&ofs](const char* key, std::string const& value) { - ofs << "set(" << key << " " - << cmOutputConverter::EscapeForCMake(value) << ")\n"; - }; - auto CWriteMap = - [&ofs](const char* key, - std::map const& map) { - for (auto const& item : map) { - ofs << "set(" << key << "_" << item.first << " " - << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; - } - }; - - // Write - ofs << "# Configurations\n"; - CWrite("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE"); - CWrite("ARCC_VERBOSITY", this->Verbosity); - ofs << "# Settings file\n"; - if (this->MultiConfig) { - std::map settingsFiles; - for (std::string const& cfg : this->ConfigsList) { - settingsFiles[cfg] = - AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg); - } - CWriteMap("ARCC_SETTINGS_FILE", settingsFiles); - } else { - CWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile); - } - - ofs << "# Directories\n"; - CWrite("ARCC_BUILD_DIR", this->DirBuild); - if (this->MultiConfig) { - CWriteMap("ARCC_INCLUDE_DIR", this->DirConfigInclude); - } else { - CWrite("ARCC_INCLUDE_DIR", this->DirInclude); - } - - ofs << "# Rcc executable\n"; - CWrite("ARCC_RCC_EXECUTABLE", this->Rcc.Executable); - CWrite("ARCC_RCC_LIST_OPTIONS", cmJoin(this->Rcc.ListOptions, ";")); - - ofs << "# Rcc job\n"; - CWrite("ARCC_LOCK_FILE", qrc.LockFile); - CWrite("ARCC_SOURCE", qrc.QrcFile); - CWrite("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum); - CWrite("ARCC_OUTPUT_NAME", - cmSystemTools::GetFilenameName(qrc.RccFile)); - CWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";")); - CWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";")); - } else { - std::string err = "AutoRcc: Could not write file "; - err += qrc.InfoFile; - cmSystemTools::Error(err.c_str()); - return false; - } - } - } - return true; } @@ -1063,11 +1079,24 @@ bool cmQtAutoGenInitializer::SetupCustomTargetsMoc() // Get the include dirs for this target, without stripping the implicit // include dirs off, see // https://gitlab.kitware.com/cmake/cmake/issues/13667 - std::vector includeDirs; - localGen->GetIncludeDirectories(includeDirs, this->Target, "CXX", cfg, - false); - return cmJoin(includeDirs, ";"); + std::vector dirs; + localGen->GetIncludeDirectories(dirs, this->Target, "CXX", cfg, false); + return cmJoin(dirs, ";"); }; + + // Default configuration include directories + this->Moc.Includes = GetIncludeDirs(this->ConfigDefault); + // Other configuration settings + for (std::string const& cfg : this->ConfigsList) { + std::string configIncludeDirs = GetIncludeDirs(cfg); + if (configIncludeDirs != this->Moc.Includes) { + this->Moc.ConfigIncludes[cfg] = std::move(configIncludeDirs); + } + } + } + + // Moc compile definitions + { auto GetCompileDefinitions = [this, localGen](std::string const& cfg) -> std::string { std::set defines; @@ -1075,26 +1104,18 @@ bool cmQtAutoGenInitializer::SetupCustomTargetsMoc() return cmJoin(defines, ";"); }; - // Default configuration settings - this->Moc.Includes = GetIncludeDirs(this->ConfigDefault); + // Default configuration defines this->Moc.Defines = GetCompileDefinitions(this->ConfigDefault); - // Other configuration settings + // Other configuration defines for (std::string const& cfg : this->ConfigsList) { - { - std::string const configIncludeDirs = GetIncludeDirs(cfg); - if (configIncludeDirs != this->Moc.Includes) { - this->Moc.ConfigIncludes[cfg] = configIncludeDirs; - } - } - { - std::string const configCompileDefs = GetCompileDefinitions(cfg); - if (configCompileDefs != this->Moc.Defines) { - this->Moc.ConfigDefines[cfg] = configCompileDefs; - } + std::string configCompileDefs = GetCompileDefinitions(cfg); + if (configCompileDefs != this->Moc.Defines) { + this->Moc.ConfigDefines[cfg] = std::move(configCompileDefs); } } } + // Moc executable if (!GetMocExecutable()) { return false; } diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 387b3bc..bb2c920 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -57,6 +57,9 @@ private: bool SetupCustomTargetsMoc(); bool SetupCustomTargetsUic(); + bool SetupWriteAutogenInfo(); + bool SetupWriteRccInfo(); + void AddGeneratedSource(std::string const& filename, GeneratorT genType); bool QtVersionGreaterOrEqual(unsigned long requestMajor, -- cgit v0.12 From 84bdae88950584663702be1cab3adf5d8069c58c Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Sun, 22 Jul 2018 15:11:38 +0200 Subject: Autogen: Compute variables in Init stage instead of Setup stage --- Source/cmQtAutoGenInitializer.cxx | 327 ++++++++++++++++++++------------------ Source/cmQtAutoGenInitializer.h | 14 +- 2 files changed, 179 insertions(+), 162 deletions(-) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 89eb5a6..22f9caf 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -317,17 +317,14 @@ bool cmQtAutoGenInitializer::InitCustomTargets() } } - // Add moc compilation to generated files list - if (this->Moc.Enabled) { - std::string mocsComp = this->DirBuild + "/mocs_compilation.cpp"; - this->AddGeneratedSource(mocsComp, GeneratorT::MOC); - autogenProvides.push_back(std::move(mocsComp)); + if (this->Moc.Enabled && !InitCustomTargetsMoc()) { + return false; } - - // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES - if (this->Moc.Enabled || this->Uic.Enabled || - (this->Rcc.Enabled && this->MultiConfig)) { - this->Target->AddIncludeDirectory(this->DirInclude, true); + if (this->Uic.Enabled && !InitCustomTargetsUic()) { + return false; + } + if (this->Uic.Enabled && !InitCustomTargetsRcc()) { + return false; } // Acquire rcc executable and features @@ -337,6 +334,17 @@ bool cmQtAutoGenInitializer::InitCustomTargets() } } + // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES + if (this->Moc.Enabled || this->Uic.Enabled || + (this->Rcc.Enabled && this->MultiConfig)) { + this->Target->AddIncludeDirectory(this->DirInclude, true); + } + + if (this->Moc.Enabled) { + this->AddGeneratedSource(this->Moc.MocsCompilation, GeneratorT::MOC); + autogenProvides.push_back(this->Moc.MocsCompilation); + } + // Extract relevant source files std::vector generatedSources; std::vector generatedHeaders; @@ -838,6 +846,159 @@ bool cmQtAutoGenInitializer::InitCustomTargets() return true; } +bool cmQtAutoGenInitializer::InitCustomTargetsMoc() +{ + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + cmMakefile* makefile = this->Target->Target->GetMakefile(); + + // Add moc compilation to generated files list + + this->Moc.MocsCompilation = this->DirBuild; + this->Moc.MocsCompilation += "/mocs_compilation.cpp"; + + // Moc predefs command + if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") && + this->QtVersionGreaterOrEqual(5, 8)) { + this->Moc.PredefsCmd = + makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"); + } + + // Moc includes and compile definitions + { + auto GetIncludeDirs = [this, + localGen](std::string const& cfg) -> std::string { + // Get the include dirs for this target, without stripping the implicit + // include dirs off, see + // https://gitlab.kitware.com/cmake/cmake/issues/13667 + std::vector dirs; + localGen->GetIncludeDirectories(dirs, this->Target, "CXX", cfg, false); + return cmJoin(dirs, ";"); + }; + + // Default configuration include directories + this->Moc.Includes = GetIncludeDirs(this->ConfigDefault); + // Other configuration settings + for (std::string const& cfg : this->ConfigsList) { + std::string configIncludeDirs = GetIncludeDirs(cfg); + if (configIncludeDirs != this->Moc.Includes) { + this->Moc.ConfigIncludes[cfg] = std::move(configIncludeDirs); + } + } + } + + // Moc compile definitions + { + auto GetCompileDefinitions = + [this, localGen](std::string const& cfg) -> std::string { + std::set defines; + localGen->AddCompileDefinitions(defines, this->Target, cfg, "CXX"); + return cmJoin(defines, ";"); + }; + + // Default configuration defines + this->Moc.Defines = GetCompileDefinitions(this->ConfigDefault); + // Other configuration defines + for (std::string const& cfg : this->ConfigsList) { + std::string configCompileDefs = GetCompileDefinitions(cfg); + if (configCompileDefs != this->Moc.Defines) { + this->Moc.ConfigDefines[cfg] = std::move(configCompileDefs); + } + } + } + + // Moc executable + if (!GetMocExecutable()) { + return false; + } + + return true; +} + +bool cmQtAutoGenInitializer::InitCustomTargetsUic() +{ + cmMakefile* makefile = this->Target->Target->GetMakefile(); + + // Uic search paths + { + std::string const usp = + this->Target->GetSafeProperty("AUTOUIC_SEARCH_PATHS"); + if (!usp.empty()) { + cmSystemTools::ExpandListArgument(usp, this->Uic.SearchPaths); + std::string const srcDir = makefile->GetCurrentSourceDirectory(); + for (std::string& path : this->Uic.SearchPaths) { + path = cmSystemTools::CollapseFullPath(path, srcDir); + } + } + } + // Uic target options + { + auto UicGetOpts = [this](std::string const& cfg) -> std::string { + std::vector opts; + this->Target->GetAutoUicOptions(opts, cfg); + return cmJoin(opts, ";"); + }; + + // Default settings + this->Uic.Options = UicGetOpts(this->ConfigDefault); + + // Configuration specific settings + for (std::string const& cfg : this->ConfigsList) { + std::string const configUicOpts = UicGetOpts(cfg); + if (configUicOpts != this->Uic.Options) { + this->Uic.ConfigOptions[cfg] = configUicOpts; + } + } + } + // .ui files skip and options + { + std::string const uiExt = "ui"; + std::string pathError; + for (cmSourceFile* sf : makefile->GetSourceFiles()) { + // sf->GetExtension() is only valid after sf->GetFullPath() ... + // Since we're iterating over source files that might be not in the + // target we need to check for path errors (not existing files). + std::string const& fPath = sf->GetFullPath(&pathError); + if (!pathError.empty()) { + pathError.clear(); + continue; + } + if (sf->GetExtension() == uiExt) { + std::string const absFile = cmSystemTools::GetRealPath(fPath); + // Check if the .ui file should be skipped + if (sf->GetPropertyAsBool("SKIP_AUTOUIC") || + sf->GetPropertyAsBool("SKIP_AUTOGEN")) { + this->Uic.Skip.insert(absFile); + } + // Check if the .ui file has uic options + std::string const uicOpts = sf->GetSafeProperty("AUTOUIC_OPTIONS"); + if (!uicOpts.empty()) { + // Check if file isn't skipped + if (this->Uic.Skip.count(absFile) == 0) { + this->Uic.FileFiles.push_back(absFile); + std::vector optsVec; + cmSystemTools::ExpandListArgument(uicOpts, optsVec); + this->Uic.FileOptions.push_back(std::move(optsVec)); + } + } + } + } + } + + if (!GetUicExecutable()) { + return false; + } + + return true; +} + +bool cmQtAutoGenInitializer::InitCustomTargetsRcc() +{ + if (!GetRccExecutable()) { + return false; + } + return true; +} + bool cmQtAutoGenInitializer::SetupCustomTargets() { // Create info directory on demand @@ -850,12 +1011,6 @@ bool cmQtAutoGenInitializer::SetupCustomTargets() // Generate autogen target info file if (this->Moc.Enabled || this->Uic.Enabled) { - if (this->Moc.Enabled) { - this->SetupCustomTargetsMoc(); - } - if (this->Uic.Enabled) { - this->SetupCustomTargetsUic(); - } // Write autogen target info files if (!this->SetupWriteAutogenInfo()) { return false; @@ -1060,146 +1215,6 @@ bool cmQtAutoGenInitializer::SetupWriteRccInfo() return true; } -bool cmQtAutoGenInitializer::SetupCustomTargetsMoc() -{ - cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); - cmMakefile* makefile = this->Target->Target->GetMakefile(); - - // Moc predefs command - if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") && - this->QtVersionGreaterOrEqual(5, 8)) { - this->Moc.PredefsCmd = - makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"); - } - - // Moc includes and compile definitions - { - auto GetIncludeDirs = [this, - localGen](std::string const& cfg) -> std::string { - // Get the include dirs for this target, without stripping the implicit - // include dirs off, see - // https://gitlab.kitware.com/cmake/cmake/issues/13667 - std::vector dirs; - localGen->GetIncludeDirectories(dirs, this->Target, "CXX", cfg, false); - return cmJoin(dirs, ";"); - }; - - // Default configuration include directories - this->Moc.Includes = GetIncludeDirs(this->ConfigDefault); - // Other configuration settings - for (std::string const& cfg : this->ConfigsList) { - std::string configIncludeDirs = GetIncludeDirs(cfg); - if (configIncludeDirs != this->Moc.Includes) { - this->Moc.ConfigIncludes[cfg] = std::move(configIncludeDirs); - } - } - } - - // Moc compile definitions - { - auto GetCompileDefinitions = - [this, localGen](std::string const& cfg) -> std::string { - std::set defines; - localGen->AddCompileDefinitions(defines, this->Target, cfg, "CXX"); - return cmJoin(defines, ";"); - }; - - // Default configuration defines - this->Moc.Defines = GetCompileDefinitions(this->ConfigDefault); - // Other configuration defines - for (std::string const& cfg : this->ConfigsList) { - std::string configCompileDefs = GetCompileDefinitions(cfg); - if (configCompileDefs != this->Moc.Defines) { - this->Moc.ConfigDefines[cfg] = std::move(configCompileDefs); - } - } - } - - // Moc executable - if (!GetMocExecutable()) { - return false; - } - - return true; -} - -bool cmQtAutoGenInitializer::SetupCustomTargetsUic() -{ - cmMakefile* makefile = this->Target->Target->GetMakefile(); - - // Uic search paths - { - std::string const usp = - this->Target->GetSafeProperty("AUTOUIC_SEARCH_PATHS"); - if (!usp.empty()) { - cmSystemTools::ExpandListArgument(usp, this->Uic.SearchPaths); - std::string const srcDir = makefile->GetCurrentSourceDirectory(); - for (std::string& path : this->Uic.SearchPaths) { - path = cmSystemTools::CollapseFullPath(path, srcDir); - } - } - } - // Uic target options - { - auto UicGetOpts = [this](std::string const& cfg) -> std::string { - std::vector opts; - this->Target->GetAutoUicOptions(opts, cfg); - return cmJoin(opts, ";"); - }; - - // Default settings - this->Uic.Options = UicGetOpts(this->ConfigDefault); - - // Configuration specific settings - for (std::string const& cfg : this->ConfigsList) { - std::string const configUicOpts = UicGetOpts(cfg); - if (configUicOpts != this->Uic.Options) { - this->Uic.ConfigOptions[cfg] = configUicOpts; - } - } - } - // .ui files skip and options - { - std::string const uiExt = "ui"; - std::string pathError; - for (cmSourceFile* sf : makefile->GetSourceFiles()) { - // sf->GetExtension() is only valid after sf->GetFullPath() ... - // Since we're iterating over source files that might be not in the - // target we need to check for path errors (not existing files). - std::string const& fPath = sf->GetFullPath(&pathError); - if (!pathError.empty()) { - pathError.clear(); - continue; - } - if (sf->GetExtension() == uiExt) { - std::string const absFile = cmSystemTools::GetRealPath(fPath); - // Check if the .ui file should be skipped - if (sf->GetPropertyAsBool("SKIP_AUTOUIC") || - sf->GetPropertyAsBool("SKIP_AUTOGEN")) { - this->Uic.Skip.insert(absFile); - } - // Check if the .ui file has uic options - std::string const uicOpts = sf->GetSafeProperty("AUTOUIC_OPTIONS"); - if (!uicOpts.empty()) { - // Check if file isn't skipped - if (this->Uic.Skip.count(absFile) == 0) { - this->Uic.FileFiles.push_back(absFile); - std::vector optsVec; - cmSystemTools::ExpandListArgument(uicOpts, optsVec); - this->Uic.FileOptions.push_back(std::move(optsVec)); - } - } - } - } - } - - if (!GetUicExecutable()) { - return false; - } - - return true; -} - void cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename, GeneratorT genType) { diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index bb2c920..6ade2ed 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -54,8 +54,9 @@ public: bool SetupCustomTargets(); private: - bool SetupCustomTargetsMoc(); - bool SetupCustomTargetsUic(); + bool InitCustomTargetsMoc(); + bool InitCustomTargetsUic(); + bool InitCustomTargetsRcc(); bool SetupWriteAutogenInfo(); bool SetupWriteRccInfo(); @@ -75,7 +76,7 @@ private: private: cmGeneratorTarget* Target; - bool MultiConfig; + bool MultiConfig = false; // Qt std::string QtVersionMajor; std::string QtVersionMinor; @@ -101,7 +102,7 @@ private: // Moc struct { - bool Enabled; + bool Enabled = false; std::string Executable; std::string PredefsCmd; std::set Skip; @@ -109,11 +110,12 @@ private: std::map ConfigIncludes; std::string Defines; std::map ConfigDefines; + std::string MocsCompilation; } Moc; // Uic struct { - bool Enabled; + bool Enabled = false; std::string Executable; std::set Skip; std::vector SearchPaths; @@ -125,7 +127,7 @@ private: // Rcc struct { - bool Enabled; + bool Enabled = false; std::string Executable; std::vector ListOptions; std::vector Qrcs; -- cgit v0.12 From 2d6cfe26770d8062081061f9dbcc4e3e6eaa0091 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Sun, 22 Jul 2018 16:09:18 +0200 Subject: Autogen: Split initializer main method --- Source/cmQtAutoGenInitializer.cxx | 1098 +++++++++++++++++++------------------ Source/cmQtAutoGenInitializer.h | 27 +- 2 files changed, 578 insertions(+), 547 deletions(-) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 22f9caf..607afbf 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -195,15 +195,13 @@ bool cmQtAutoGenInitializer::InitCustomTargets() cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator(); // Verbosity - { - this->Verbosity = makefile->GetSafeDefinition("CMAKE_AUTOGEN_VERBOSE"); - if (!this->Verbosity.empty()) { - unsigned long iVerb = 0; - if (!cmSystemTools::StringToULong(this->Verbosity.c_str(), &iVerb)) { - // Non numeric verbosity - this->Verbosity = - cmSystemTools::IsOn(this->Verbosity.c_str()) ? "1" : "0"; - } + this->Verbosity = makefile->GetSafeDefinition("CMAKE_AUTOGEN_VERBOSE"); + if (!this->Verbosity.empty()) { + unsigned long iVerb = 0; + if (!cmSystemTools::StringToULong(this->Verbosity.c_str(), &iVerb)) { + // Non numeric verbosity + this->Verbosity = + cmSystemTools::IsOn(this->Verbosity.c_str()) ? "1" : "0"; } } @@ -247,6 +245,8 @@ bool cmQtAutoGenInitializer::InitCustomTargets() this->DirBuild += this->AutogenTargetName; } cmSystemTools::ConvertToUnixSlashes(this->DirBuild); + // Remove build directories on cleanup + AddCleanFile(makefile, this->DirBuild); // Working directory this->DirWork = cbd; @@ -268,13 +268,23 @@ bool cmQtAutoGenInitializer::InitCustomTargets() } } - // Autogen files + // Autogen info and settings files { this->AutogenInfoFile = this->DirInfo; this->AutogenInfoFile += "/AutogenInfo.cmake"; this->AutogenSettingsFile = this->DirInfo; this->AutogenSettingsFile += "/AutogenOldSettings.txt"; + + if (this->MultiConfig) { + for (std::string const& cfg : this->ConfigsList) { + std::string& filename = this->AutogenConfigSettingsFile[cfg]; + filename = AppendFilenameSuffix(this->AutogenSettingsFile, "_" + cfg); + AddCleanFile(makefile, filename); + } + } else { + AddCleanFile(makefile, this->AutogenSettingsFile); + } } // Autogen target FOLDER property @@ -294,60 +304,228 @@ bool cmQtAutoGenInitializer::InitCustomTargets() } } - std::set autogenDependFiles; - std::set autogenDependTargets; - std::vector autogenProvides; + if (this->Moc.Enabled || this->Uic.Enabled) { + // Init moc specific settings + if (this->Moc.Enabled && !InitMoc()) { + return false; + } + // Init uic specific settings + if (this->Uic.Enabled && !InitUic()) { + return false; + } + + // Autogen target: Compute user defined dependencies + { + std::string const deps = + this->Target->GetSafeProperty("AUTOGEN_TARGET_DEPENDS"); + if (!deps.empty()) { + std::vector extraDeps; + cmSystemTools::ExpandListArgument(deps, extraDeps); + for (std::string const& depName : extraDeps) { + // Allow target and file dependencies + auto* depTarget = makefile->FindTargetToUse(depName); + if (depTarget != nullptr) { + this->AutogenDependTargets.insert(depTarget); + } else { + this->AutogenDependFiles.insert(depName); + } + } + } + } + } + // Init rcc specific settings + if (this->Rcc.Enabled && !InitRcc()) { + return false; + } + + // Add autogen include directory to the origin target INCLUDE_DIRECTORIES + if (this->Moc.Enabled || this->Uic.Enabled || + (this->Rcc.Enabled && this->MultiConfig)) { + this->Target->AddIncludeDirectory(this->DirInclude, true); + } + + // Scan files + if (!this->InitScanFiles()) { + return false; + } + + // Create autogen target + if ((this->Moc.Enabled || this->Uic.Enabled) && !this->InitAutogenTarget()) { + return false; + } - // Remove build directories on cleanup - AddCleanFile(makefile, this->DirBuild); - // Remove old settings on cleanup + // Create rcc targets + if (this->Rcc.Enabled && !this->InitRccTargets()) { + return false; + } + + return true; +} + +bool cmQtAutoGenInitializer::InitMoc() +{ + cmMakefile* makefile = this->Target->Target->GetMakefile(); + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + + // Mocs compilation file + this->Moc.MocsCompilation = this->DirBuild; + this->Moc.MocsCompilation += "/mocs_compilation.cpp"; + + // Moc predefs command + if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") && + this->QtVersionGreaterOrEqual(5, 8)) { + this->Moc.PredefsCmd = + makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"); + } + + // Moc includes { - std::string base = this->DirInfo; - base += "/AutogenOldSettings"; + auto GetIncludeDirs = [this, + localGen](std::string const& cfg) -> std::string { + // Get the include dirs for this target, without stripping the implicit + // include dirs off, see + // https://gitlab.kitware.com/cmake/cmake/issues/13667 + std::vector dirs; + localGen->GetIncludeDirectories(dirs, this->Target, "CXX", cfg, false); + return cmJoin(dirs, ";"); + }; + + // Default configuration include directories + this->Moc.Includes = GetIncludeDirs(this->ConfigDefault); + // Other configuration settings if (this->MultiConfig) { for (std::string const& cfg : this->ConfigsList) { - std::string filename = base; - filename += '_'; - filename += cfg; - filename += ".cmake"; - AddCleanFile(makefile, filename); + std::string dirs = GetIncludeDirs(cfg); + if (dirs != this->Moc.Includes) { + this->Moc.ConfigIncludes[cfg] = std::move(dirs); + } } - } else { - AddCleanFile(makefile, base.append(".cmake")); } } - if (this->Moc.Enabled && !InitCustomTargetsMoc()) { - return false; + // Moc compile definitions + { + auto GetCompileDefinitions = + [this, localGen](std::string const& cfg) -> std::string { + std::set defines; + localGen->AddCompileDefinitions(defines, this->Target, cfg, "CXX"); + return cmJoin(defines, ";"); + }; + + // Default configuration defines + this->Moc.Defines = GetCompileDefinitions(this->ConfigDefault); + // Other configuration defines + if (this->MultiConfig) { + for (std::string const& cfg : this->ConfigsList) { + std::string defines = GetCompileDefinitions(cfg); + if (defines != this->Moc.Defines) { + this->Moc.ConfigDefines[cfg] = std::move(defines); + } + } + } } - if (this->Uic.Enabled && !InitCustomTargetsUic()) { + + // Moc executable + if (!GetMocExecutable()) { return false; } - if (this->Uic.Enabled && !InitCustomTargetsRcc()) { - return false; + + return true; +} + +bool cmQtAutoGenInitializer::InitUic() +{ + cmMakefile* makefile = this->Target->Target->GetMakefile(); + + // Uic search paths + { + std::string const usp = + this->Target->GetSafeProperty("AUTOUIC_SEARCH_PATHS"); + if (!usp.empty()) { + cmSystemTools::ExpandListArgument(usp, this->Uic.SearchPaths); + std::string const srcDir = makefile->GetCurrentSourceDirectory(); + for (std::string& path : this->Uic.SearchPaths) { + path = cmSystemTools::CollapseFullPath(path, srcDir); + } + } } + // Uic target options + { + auto UicGetOpts = [this](std::string const& cfg) -> std::string { + std::vector opts; + this->Target->GetAutoUicOptions(opts, cfg); + return cmJoin(opts, ";"); + }; - // Acquire rcc executable and features - if (this->Rcc.Enabled) { - if (!GetRccExecutable()) { - return false; + // Default settings + this->Uic.Options = UicGetOpts(this->ConfigDefault); + + // Configuration specific settings + if (this->MultiConfig) { + for (std::string const& cfg : this->ConfigsList) { + std::string options = UicGetOpts(cfg); + if (options != this->Uic.Options) { + this->Uic.ConfigOptions[cfg] = std::move(options); + } + } + } + } + // .ui files skip and options + { + std::string const uiExt = "ui"; + std::string pathError; + for (cmSourceFile* sf : makefile->GetSourceFiles()) { + // sf->GetExtension() is only valid after sf->GetFullPath() ... + // Since we're iterating over source files that might be not in the + // target we need to check for path errors (not existing files). + std::string const& fPath = sf->GetFullPath(&pathError); + if (!pathError.empty()) { + pathError.clear(); + continue; + } + if (sf->GetExtension() == uiExt) { + std::string const absFile = cmSystemTools::GetRealPath(fPath); + // Check if the .ui file should be skipped + if (sf->GetPropertyAsBool("SKIP_AUTOUIC") || + sf->GetPropertyAsBool("SKIP_AUTOGEN")) { + this->Uic.Skip.insert(absFile); + } + // Check if the .ui file has uic options + std::string const uicOpts = sf->GetSafeProperty("AUTOUIC_OPTIONS"); + if (!uicOpts.empty()) { + // Check if file isn't skipped + if (this->Uic.Skip.count(absFile) == 0) { + this->Uic.FileFiles.push_back(absFile); + std::vector optsVec; + cmSystemTools::ExpandListArgument(uicOpts, optsVec); + this->Uic.FileOptions.push_back(std::move(optsVec)); + } + } + } } } - // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES - if (this->Moc.Enabled || this->Uic.Enabled || - (this->Rcc.Enabled && this->MultiConfig)) { - this->Target->AddIncludeDirectory(this->DirInclude, true); + // Uic executable + if (!GetUicExecutable()) { + return false; } - if (this->Moc.Enabled) { - this->AddGeneratedSource(this->Moc.MocsCompilation, GeneratorT::MOC); - autogenProvides.push_back(this->Moc.MocsCompilation); + return true; +} + +bool cmQtAutoGenInitializer::InitRcc() +{ + if (!GetRccExecutable()) { + return false; } + return true; +} + +bool cmQtAutoGenInitializer::InitScanFiles() +{ + cmMakefile* makefile = this->Target->Target->GetMakefile(); - // Extract relevant source files - std::vector generatedSources; - std::vector generatedHeaders; + // Scan through target files { std::string const qrcExt = "qrc"; std::vector srcFiles; @@ -372,15 +550,15 @@ bool cmQtAutoGenInitializer::InitCustomTargets() const bool generated = sf->GetPropertyAsBool("GENERATED"); if (fileType == cmSystemTools::HEADER_FILE_FORMAT) { if (generated) { - generatedHeaders.push_back(absPath); + this->MocUic.HeadersGenerated.push_back(absPath); } else { - this->Headers.push_back(absPath); + this->MocUic.Headers.push_back(absPath); } } else { if (generated) { - generatedSources.push_back(absPath); + this->MocUic.SourcesGenerated.push_back(absPath); } else { - this->Sources.push_back(absPath); + this->MocUic.Sources.push_back(absPath); } } } @@ -407,125 +585,126 @@ bool cmQtAutoGenInitializer::InitCustomTargets() } } } - // cmGeneratorTarget::GetConfigCommonSourceFiles computes the target's - // sources meta data cache. Clear it so that OBJECT library targets that - // are AUTOGEN initialized after this target get their added - // mocs_compilation.cpp source acknowledged by this target. - this->Target->ClearSourcesCache(); } - // Read skip files from makefile sources + // cmGeneratorTarget::GetConfigCommonSourceFiles computes the target's + // sources meta data cache. Clear it so that OBJECT library targets that + // are AUTOGEN initialized after this target get their added + // mocs_compilation.cpp source acknowledged by this target. + this->Target->ClearSourcesCache(); + if (this->Moc.Enabled || this->Uic.Enabled) { - std::string pathError; - for (cmSourceFile* sf : makefile->GetSourceFiles()) { - // sf->GetExtension() is only valid after sf->GetFullPath() ... - // Since we're iterating over source files that might be not in the - // target we need to check for path errors (not existing files). - std::string const& fPath = sf->GetFullPath(&pathError); - if (!pathError.empty()) { - pathError.clear(); - continue; - } - cmSystemTools::FileFormat const fileType = - cmSystemTools::GetFileFormat(sf->GetExtension().c_str()); - if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) && - !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) { - continue; - } - const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN"); - const bool mocSkip = this->Moc.Enabled && - (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC")); - const bool uicSkip = this->Uic.Enabled && - (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC")); - if (mocSkip || uicSkip) { - std::string const absFile = cmSystemTools::GetRealPath(fPath); - if (mocSkip) { - this->Moc.Skip.insert(absFile); + // Read skip files from makefile sources + { + std::string pathError; + for (cmSourceFile* sf : makefile->GetSourceFiles()) { + // sf->GetExtension() is only valid after sf->GetFullPath() ... + // Since we're iterating over source files that might be not in the + // target we need to check for path errors (not existing files). + std::string const& fPath = sf->GetFullPath(&pathError); + if (!pathError.empty()) { + pathError.clear(); + continue; } - if (uicSkip) { - this->Uic.Skip.insert(absFile); + cmSystemTools::FileFormat const fileType = + cmSystemTools::GetFileFormat(sf->GetExtension().c_str()); + if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) && + !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) { + continue; + } + const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN"); + const bool mocSkip = this->Moc.Enabled && + (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC")); + const bool uicSkip = this->Uic.Enabled && + (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC")); + if (mocSkip || uicSkip) { + std::string const absFile = cmSystemTools::GetRealPath(fPath); + if (mocSkip) { + this->Moc.Skip.insert(absFile); + } + if (uicSkip) { + this->Uic.Skip.insert(absFile); + } } } } - } - - // Process GENERATED sources and headers - if (!generatedSources.empty() || !generatedHeaders.empty()) { - // Check status of policy CMP0071 - bool policyAccept = false; - bool policyWarn = false; - cmPolicies::PolicyStatus const CMP0071_status = - 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 (std::string const& absFile : generatedHeaders) { - this->Headers.push_back(absFile); - autogenDependFiles.insert(absFile); - } - for (std::string const& absFile : generatedSources) { - this->Sources.push_back(absFile); - autogenDependFiles.insert(absFile); + // Process GENERATED sources and headers + if (!this->MocUic.SourcesGenerated.empty() || + !this->MocUic.HeadersGenerated.empty()) { + // Check status of policy CMP0071 + bool policyAccept = false; + bool policyWarn = false; + cmPolicies::PolicyStatus const CMP0071_status = + 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; } - } else { - if (policyWarn) { - std::string msg; - msg += cmPolicies::GetPolicyWarning(cmPolicies::CMP0071); - msg += "\n"; - std::string tools; - std::string property; - if (this->Moc.Enabled && this->Uic.Enabled) { - tools = "AUTOMOC and AUTOUIC"; - property = "SKIP_AUTOGEN"; - } else if (this->Moc.Enabled) { - tools = "AUTOMOC"; - property = "SKIP_AUTOMOC"; - } else if (this->Uic.Enabled) { - tools = "AUTOUIC"; - property = "SKIP_AUTOUIC"; + + if (policyAccept) { + // Accept GENERATED sources + for (std::string const& absFile : this->MocUic.HeadersGenerated) { + this->MocUic.Headers.push_back(absFile); + this->AutogenDependFiles.insert(absFile); } - msg += "For compatibility, CMake is excluding the GENERATED source " - "file(s):\n"; - for (const std::string& absFile : generatedHeaders) { - msg.append(" ").append(Quoted(absFile)).append("\n"); + for (std::string const& absFile : this->MocUic.SourcesGenerated) { + this->MocUic.Sources.push_back(absFile); + this->AutogenDependFiles.insert(absFile); } - for (const std::string& absFile : generatedSources) { - msg.append(" ").append(Quoted(absFile)).append("\n"); + } else { + if (policyWarn) { + std::string msg; + msg += cmPolicies::GetPolicyWarning(cmPolicies::CMP0071); + msg += "\n"; + std::string tools; + std::string property; + if (this->Moc.Enabled && this->Uic.Enabled) { + tools = "AUTOMOC and AUTOUIC"; + property = "SKIP_AUTOGEN"; + } else if (this->Moc.Enabled) { + tools = "AUTOMOC"; + property = "SKIP_AUTOMOC"; + } else if (this->Uic.Enabled) { + tools = "AUTOUIC"; + property = "SKIP_AUTOUIC"; + } + msg += "For compatibility, CMake is excluding the GENERATED source " + "file(s):\n"; + for (const std::string& absFile : this->MocUic.HeadersGenerated) { + msg.append(" ").append(Quoted(absFile)).append("\n"); + } + for (const std::string& absFile : this->MocUic.SourcesGenerated) { + msg.append(" ").append(Quoted(absFile)).append("\n"); + } + msg += "from processing by "; + msg += tools; + msg += + ". If any of the files should be processed, set CMP0071 to NEW. " + "If any of the files should not be processed, " + "explicitly exclude them by setting the source file property "; + msg += property; + msg += ":\n set_property(SOURCE file.h PROPERTY "; + msg += property; + msg += " ON)\n"; + makefile->IssueMessage(cmake::AUTHOR_WARNING, msg); } - msg += "from processing by "; - msg += tools; - msg += - ". If any of the files should be processed, set CMP0071 to NEW. " - "If any of the files should not be processed, " - "explicitly exclude them by setting the source file property "; - msg += property; - msg += ":\n set_property(SOURCE file.h PROPERTY "; - msg += property; - msg += " ON)\n"; - makefile->IssueMessage(cmake::AUTHOR_WARNING, msg); } } - // Clear lists - generatedSources.clear(); - generatedHeaders.clear(); - } - // Sort headers and sources - if (this->Moc.Enabled || this->Uic.Enabled) { - std::sort(this->Headers.begin(), this->Headers.end()); - std::sort(this->Sources.begin(), this->Sources.end()); + // Sort headers and sources + if (this->Moc.Enabled || this->Uic.Enabled) { + std::sort(this->MocUic.Headers.begin(), this->MocUic.Headers.end()); + std::sort(this->MocUic.Sources.begin(), this->MocUic.Sources.end()); + } } // Process qrc files @@ -576,6 +755,13 @@ bool cmQtAutoGenInitializer::InitCustomTargets() qrc.SettingsFile = base; qrc.SettingsFile += "Settings.txt"; + + if (this->MultiConfig) { + for (std::string const& cfg : this->ConfigsList) { + qrc.ConfigSettingsFile[cfg] = + AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg); + } + } } } } @@ -601,401 +787,258 @@ bool cmQtAutoGenInitializer::InitCustomTargets() RccMergeOptions(opts, qrc.Options, QtV5); qrc.Options = std::move(opts); } + // RCC resources for (Qrc& qrc : this->Rcc.Qrcs) { - // Register file at target - this->AddGeneratedSource(qrc.RccFile, GeneratorT::RCC); - - std::vector ccOutput; - ccOutput.push_back(qrc.RccFile); - - cmCustomCommandLines commandLines; - if (this->MultiConfig) { - // Build for all configurations - for (std::string const& config : this->ConfigsList) { - cmCustomCommandLine currentLine; - currentLine.push_back(cmSystemTools::GetCMakeCommand()); - currentLine.push_back("-E"); - currentLine.push_back("cmake_autorcc"); - currentLine.push_back(qrc.InfoFile); - currentLine.push_back(config); - commandLines.push_back(std::move(currentLine)); + if (!qrc.Generated) { + std::string error; + if (!RccListInputs(qrc.QrcFile, qrc.Resources, error)) { + cmSystemTools::Error(error.c_str()); + return false; } - } else { - cmCustomCommandLine currentLine; - currentLine.push_back(cmSystemTools::GetCMakeCommand()); - currentLine.push_back("-E"); - currentLine.push_back("cmake_autorcc"); - currentLine.push_back(qrc.InfoFile); - currentLine.push_back("$"); - commandLines.push_back(std::move(currentLine)); } - std::string ccComment = "Automatic RCC for "; - ccComment += FileProjectRelativePath(makefile, qrc.QrcFile); + } + } - if (qrc.Generated) { - // Create custom rcc target - std::string ccName; - { - ccName = this->Target->GetName(); - ccName += "_arcc_"; - ccName += qrc.QrcName; - if (!qrc.Unique) { - ccName += "_"; - ccName += qrc.PathChecksum; - } - std::vector ccDepends; - // Add the .qrc and info file to the custom target dependencies - ccDepends.push_back(qrc.QrcFile); - ccDepends.push_back(qrc.InfoFile); - - cmTarget* autoRccTarget = makefile->AddUtilityCommand( - ccName, cmMakefile::TargetOrigin::Generator, true, - this->DirWork.c_str(), ccOutput, ccDepends, commandLines, false, - ccComment.c_str()); - // Create autogen generator target - localGen->AddGeneratorTarget( - new cmGeneratorTarget(autoRccTarget, localGen)); - - // Set FOLDER property in autogen target - if (!this->AutogenFolder.empty()) { - autoRccTarget->SetProperty("FOLDER", this->AutogenFolder.c_str()); - } - } - // Add autogen target to the origin target dependencies - this->Target->Target->AddUtility(ccName, makefile); - } else { - // Create custom rcc command - { - std::vector ccByproducts; - std::vector ccDepends; - // Add the .qrc and info file to the custom command dependencies - ccDepends.push_back(qrc.QrcFile); - ccDepends.push_back(qrc.InfoFile); + return true; +} - // Add the resource files to the dependencies - { - std::string error; - if (RccListInputs(qrc.QrcFile, qrc.Resources, error)) { - for (std::string const& fileName : qrc.Resources) { - // Add resource file to the custom command dependencies - ccDepends.push_back(fileName); - } - } else { - cmSystemTools::Error(error.c_str()); - return false; - } - } - makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends, - /*main_dependency*/ std::string(), - commandLines, ccComment.c_str(), - this->DirWork.c_str()); - } - // Reconfigure when .qrc file changes - makefile->AddCMakeDependFile(qrc.QrcFile); - } - } +bool cmQtAutoGenInitializer::InitAutogenTarget() +{ + cmMakefile* makefile = this->Target->Target->GetMakefile(); + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator(); + + // Register info file as generated by CMake + makefile->AddCMakeOutputFile(this->AutogenInfoFile); + + // Files provided by the autogen target + std::vector autogenProvides; + if (this->Moc.Enabled) { + this->AddGeneratedSource(this->Moc.MocsCompilation, GeneratorT::MOC); + autogenProvides.push_back(this->Moc.MocsCompilation); } - // Create _autogen target - if (this->Moc.Enabled || this->Uic.Enabled) { - // Add user defined autogen target dependencies - { - std::string const deps = - this->Target->GetSafeProperty("AUTOGEN_TARGET_DEPENDS"); - if (!deps.empty()) { - std::vector extraDeps; - cmSystemTools::ExpandListArgument(deps, extraDeps); - for (std::string const& depName : extraDeps) { - // Allow target and file dependencies - auto* depTarget = makefile->FindTargetToUse(depName); - if (depTarget != nullptr) { - autogenDependTargets.insert(depTarget); - } else { - autogenDependFiles.insert(depName); - } - } - } + // Compose target comment + std::string autogenComment; + { + std::string tools; + if (this->Moc.Enabled) { + tools += "MOC"; } - - // Compose target comment - std::string autogenComment; - { - std::string tools; - if (this->Moc.Enabled) { - tools += "MOC"; - } - if (this->Uic.Enabled) { - if (!tools.empty()) { - tools += " and "; - } - tools += "UIC"; + if (this->Uic.Enabled) { + if (!tools.empty()) { + tools += " and "; } - autogenComment = "Automatic "; - autogenComment += tools; - autogenComment += " for target "; - autogenComment += this->Target->GetName(); + tools += "UIC"; } + autogenComment = "Automatic "; + autogenComment += tools; + autogenComment += " for target "; + autogenComment += this->Target->GetName(); + } - // Compose command lines - cmCustomCommandLines commandLines; - { - cmCustomCommandLine currentLine; - currentLine.push_back(cmSystemTools::GetCMakeCommand()); - currentLine.push_back("-E"); - currentLine.push_back("cmake_autogen"); - currentLine.push_back(this->AutogenInfoFile); - currentLine.push_back("$"); - commandLines.push_back(std::move(currentLine)); - } + // Compose command lines + cmCustomCommandLines commandLines; + { + cmCustomCommandLine currentLine; + currentLine.push_back(cmSystemTools::GetCMakeCommand()); + currentLine.push_back("-E"); + currentLine.push_back("cmake_autogen"); + currentLine.push_back(this->AutogenInfoFile); + currentLine.push_back("$"); + commandLines.push_back(std::move(currentLine)); + } - // 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; + // Use PRE_BUILD on demand + bool usePRE_BUILD = false; + if (globalGen->GetName().find("Visual Studio") != std::string::npos) { + // Under VS use a PRE_BUILD event instead of a separate target to + // reduce the number of targets loaded into the IDE. + // This also works around a VS 11 bug that may skip updating the target: + // https://connect.microsoft.com/VisualStudio/feedback/details/769495 + usePRE_BUILD = true; + } + // Disable PRE_BUILD in some cases + if (usePRE_BUILD) { + // Cannot use PRE_BUILD with file depends + if (!this->AutogenDependFiles.empty()) { + usePRE_BUILD = false; } - // Disable PRE_BUILD in some cases - if (usePRE_BUILD) { - // Cannot use PRE_BUILD with file depends - if (!autogenDependFiles.empty()) { - usePRE_BUILD = false; - } + } + // Create the autogen target/command + if (usePRE_BUILD) { + // Add additional autogen target dependencies to origin target + for (cmTarget* depTarget : this->AutogenDependTargets) { + this->Target->Target->AddUtility(depTarget->GetName(), makefile); } - // Create the autogen target/command - if (usePRE_BUILD) { - // Add additional autogen target dependencies to origin target - for (cmTarget* depTarget : autogenDependTargets) { - this->Target->Target->AddUtility(depTarget->GetName(), makefile); - } - // Add the pre-build command directly to bypass the OBJECT_LIBRARY - // rejection in cmMakefile::AddCustomCommandToTarget because we know - // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case. - // - // PRE_BUILD does not support file dependencies! - const std::vector no_output; - const std::vector no_deps; - cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps, - commandLines, autogenComment.c_str(), - this->DirWork.c_str()); - cc.SetEscapeOldStyle(false); - cc.SetEscapeAllowMakeVars(true); - this->Target->Target->AddPreBuildCommand(cc); - } else { + // Add the pre-build command directly to bypass the OBJECT_LIBRARY + // rejection in cmMakefile::AddCustomCommandToTarget because we know + // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case. + // + // PRE_BUILD does not support file dependencies! + const std::vector no_output; + const std::vector no_deps; + cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps, + commandLines, autogenComment.c_str(), + this->DirWork.c_str()); + cc.SetEscapeOldStyle(false); + cc.SetEscapeAllowMakeVars(true); + this->Target->Target->AddPreBuildCommand(cc); + } else { - // Add link library target dependencies to the autogen target - // dependencies - { - // add_dependencies/addUtility do not support generator expressions. - // We depend only on the libraries found in all configs therefore. - std::map commonTargets; - for (std::string const& config : this->ConfigsList) { - cmLinkImplementationLibraries const* libs = - this->Target->GetLinkImplementationLibraries(config); - if (libs != nullptr) { - for (cmLinkItem const& item : libs->Libraries) { - cmGeneratorTarget const* libTarget = item.Target; - if ((libTarget != nullptr) && - !StaticLibraryCycle(this->Target, libTarget, config)) { - // Increment target config count - commonTargets[libTarget]++; - } + // Add link library target dependencies to the autogen target + // dependencies + { + // add_dependencies/addUtility do not support generator expressions. + // We depend only on the libraries found in all configs therefore. + std::map commonTargets; + for (std::string const& config : this->ConfigsList) { + cmLinkImplementationLibraries const* libs = + this->Target->GetLinkImplementationLibraries(config); + if (libs != nullptr) { + for (cmLinkItem const& item : libs->Libraries) { + cmGeneratorTarget const* libTarget = item.Target; + if ((libTarget != nullptr) && + !StaticLibraryCycle(this->Target, libTarget, config)) { + // Increment target config count + commonTargets[libTarget]++; } } } - for (auto const& item : commonTargets) { - if (item.second == this->ConfigsList.size()) { - autogenDependTargets.insert(item.first->Target); - } - } - } - - // Create autogen target - cmTarget* autogenTarget = makefile->AddUtilityCommand( - this->AutogenTargetName, cmMakefile::TargetOrigin::Generator, true, - this->DirWork.c_str(), /*byproducts=*/autogenProvides, - std::vector(autogenDependFiles.begin(), - autogenDependFiles.end()), - commandLines, false, autogenComment.c_str()); - // Create autogen generator target - localGen->AddGeneratorTarget( - new cmGeneratorTarget(autogenTarget, localGen)); - - // Forward origin utilities to autogen target - for (std::string const& depName : this->Target->Target->GetUtilities()) { - autogenTarget->AddUtility(depName, makefile); } - // Add additional autogen target dependencies to autogen target - for (cmTarget* depTarget : autogenDependTargets) { - autogenTarget->AddUtility(depTarget->GetName(), makefile); - } - - // Set FOLDER property in autogen target - if (!this->AutogenFolder.empty()) { - autogenTarget->SetProperty("FOLDER", this->AutogenFolder.c_str()); + for (auto const& item : commonTargets) { + if (item.second == this->ConfigsList.size()) { + this->AutogenDependTargets.insert(item.first->Target); + } } - - // Add autogen target to the origin target dependencies - this->Target->Target->AddUtility(this->AutogenTargetName, makefile); } - } - return true; -} - -bool cmQtAutoGenInitializer::InitCustomTargetsMoc() -{ - cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); - cmMakefile* makefile = this->Target->Target->GetMakefile(); - - // Add moc compilation to generated files list - - this->Moc.MocsCompilation = this->DirBuild; - this->Moc.MocsCompilation += "/mocs_compilation.cpp"; - - // Moc predefs command - if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") && - this->QtVersionGreaterOrEqual(5, 8)) { - this->Moc.PredefsCmd = - makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"); - } - - // Moc includes and compile definitions - { - auto GetIncludeDirs = [this, - localGen](std::string const& cfg) -> std::string { - // Get the include dirs for this target, without stripping the implicit - // include dirs off, see - // https://gitlab.kitware.com/cmake/cmake/issues/13667 - std::vector dirs; - localGen->GetIncludeDirectories(dirs, this->Target, "CXX", cfg, false); - return cmJoin(dirs, ";"); - }; - - // Default configuration include directories - this->Moc.Includes = GetIncludeDirs(this->ConfigDefault); - // Other configuration settings - for (std::string const& cfg : this->ConfigsList) { - std::string configIncludeDirs = GetIncludeDirs(cfg); - if (configIncludeDirs != this->Moc.Includes) { - this->Moc.ConfigIncludes[cfg] = std::move(configIncludeDirs); - } + // Create autogen target + cmTarget* autogenTarget = makefile->AddUtilityCommand( + this->AutogenTargetName, cmMakefile::TargetOrigin::Generator, true, + this->DirWork.c_str(), /*byproducts=*/autogenProvides, + std::vector(this->AutogenDependFiles.begin(), + this->AutogenDependFiles.end()), + commandLines, false, autogenComment.c_str()); + // Create autogen generator target + localGen->AddGeneratorTarget( + new cmGeneratorTarget(autogenTarget, localGen)); + + // Forward origin utilities to autogen target + for (std::string const& depName : this->Target->Target->GetUtilities()) { + autogenTarget->AddUtility(depName, makefile); + } + // Add additional autogen target dependencies to autogen target + for (cmTarget* depTarget : this->AutogenDependTargets) { + autogenTarget->AddUtility(depTarget->GetName(), makefile); } - } - - // Moc compile definitions - { - auto GetCompileDefinitions = - [this, localGen](std::string const& cfg) -> std::string { - std::set defines; - localGen->AddCompileDefinitions(defines, this->Target, cfg, "CXX"); - return cmJoin(defines, ";"); - }; - // Default configuration defines - this->Moc.Defines = GetCompileDefinitions(this->ConfigDefault); - // Other configuration defines - for (std::string const& cfg : this->ConfigsList) { - std::string configCompileDefs = GetCompileDefinitions(cfg); - if (configCompileDefs != this->Moc.Defines) { - this->Moc.ConfigDefines[cfg] = std::move(configCompileDefs); - } + // Set FOLDER property in autogen target + if (!this->AutogenFolder.empty()) { + autogenTarget->SetProperty("FOLDER", this->AutogenFolder.c_str()); } - } - // Moc executable - if (!GetMocExecutable()) { - return false; + // Add autogen target to the origin target dependencies + this->Target->Target->AddUtility(this->AutogenTargetName, makefile); } return true; } -bool cmQtAutoGenInitializer::InitCustomTargetsUic() +bool cmQtAutoGenInitializer::InitRccTargets() { cmMakefile* makefile = this->Target->Target->GetMakefile(); + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); - // Uic search paths - { - std::string const usp = - this->Target->GetSafeProperty("AUTOUIC_SEARCH_PATHS"); - if (!usp.empty()) { - cmSystemTools::ExpandListArgument(usp, this->Uic.SearchPaths); - std::string const srcDir = makefile->GetCurrentSourceDirectory(); - for (std::string& path : this->Uic.SearchPaths) { - path = cmSystemTools::CollapseFullPath(path, srcDir); - } - } - } - // Uic target options - { - auto UicGetOpts = [this](std::string const& cfg) -> std::string { - std::vector opts; - this->Target->GetAutoUicOptions(opts, cfg); - return cmJoin(opts, ";"); - }; + for (Qrc const& qrc : this->Rcc.Qrcs) { + // Register info file as generated by CMake + makefile->AddCMakeOutputFile(qrc.InfoFile); + // Register file at target + this->AddGeneratedSource(qrc.RccFile, GeneratorT::RCC); - // Default settings - this->Uic.Options = UicGetOpts(this->ConfigDefault); + std::vector ccOutput; + ccOutput.push_back(qrc.RccFile); - // Configuration specific settings - for (std::string const& cfg : this->ConfigsList) { - std::string const configUicOpts = UicGetOpts(cfg); - if (configUicOpts != this->Uic.Options) { - this->Uic.ConfigOptions[cfg] = configUicOpts; + cmCustomCommandLines commandLines; + if (this->MultiConfig) { + // Build for all configurations + for (std::string const& config : this->ConfigsList) { + cmCustomCommandLine currentLine; + currentLine.push_back(cmSystemTools::GetCMakeCommand()); + currentLine.push_back("-E"); + currentLine.push_back("cmake_autorcc"); + currentLine.push_back(qrc.InfoFile); + currentLine.push_back(config); + commandLines.push_back(std::move(currentLine)); } + } else { + cmCustomCommandLine currentLine; + currentLine.push_back(cmSystemTools::GetCMakeCommand()); + currentLine.push_back("-E"); + currentLine.push_back("cmake_autorcc"); + currentLine.push_back(qrc.InfoFile); + currentLine.push_back("$"); + commandLines.push_back(std::move(currentLine)); } - } - // .ui files skip and options - { - std::string const uiExt = "ui"; - std::string pathError; - for (cmSourceFile* sf : makefile->GetSourceFiles()) { - // sf->GetExtension() is only valid after sf->GetFullPath() ... - // Since we're iterating over source files that might be not in the - // target we need to check for path errors (not existing files). - std::string const& fPath = sf->GetFullPath(&pathError); - if (!pathError.empty()) { - pathError.clear(); - continue; - } - if (sf->GetExtension() == uiExt) { - std::string const absFile = cmSystemTools::GetRealPath(fPath); - // Check if the .ui file should be skipped - if (sf->GetPropertyAsBool("SKIP_AUTOUIC") || - sf->GetPropertyAsBool("SKIP_AUTOGEN")) { - this->Uic.Skip.insert(absFile); + std::string ccComment = "Automatic RCC for "; + ccComment += FileProjectRelativePath(makefile, qrc.QrcFile); + + if (qrc.Generated) { + // Create custom rcc target + std::string ccName; + { + ccName = this->Target->GetName(); + ccName += "_arcc_"; + ccName += qrc.QrcName; + if (!qrc.Unique) { + ccName += "_"; + ccName += qrc.PathChecksum; } - // Check if the .ui file has uic options - std::string const uicOpts = sf->GetSafeProperty("AUTOUIC_OPTIONS"); - if (!uicOpts.empty()) { - // Check if file isn't skipped - if (this->Uic.Skip.count(absFile) == 0) { - this->Uic.FileFiles.push_back(absFile); - std::vector optsVec; - cmSystemTools::ExpandListArgument(uicOpts, optsVec); - this->Uic.FileOptions.push_back(std::move(optsVec)); - } + std::vector ccDepends; + // Add the .qrc and info file to the custom target dependencies + ccDepends.push_back(qrc.QrcFile); + ccDepends.push_back(qrc.InfoFile); + + cmTarget* autoRccTarget = makefile->AddUtilityCommand( + ccName, cmMakefile::TargetOrigin::Generator, true, + this->DirWork.c_str(), ccOutput, ccDepends, commandLines, false, + ccComment.c_str()); + // Create autogen generator target + localGen->AddGeneratorTarget( + new cmGeneratorTarget(autoRccTarget, localGen)); + + // Set FOLDER property in autogen target + if (!this->AutogenFolder.empty()) { + autoRccTarget->SetProperty("FOLDER", this->AutogenFolder.c_str()); } } + // Add autogen target to the origin target dependencies + this->Target->Target->AddUtility(ccName, makefile); + } else { + // Create custom rcc command + { + std::vector ccByproducts; + std::vector ccDepends; + // Add the .qrc and info file to the custom command dependencies + ccDepends.push_back(qrc.QrcFile); + ccDepends.push_back(qrc.InfoFile); + + // Add the resource files to the dependencies + for (std::string const& fileName : qrc.Resources) { + // Add resource file to the custom command dependencies + ccDepends.push_back(fileName); + } + makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends, + /*main_dependency*/ std::string(), + commandLines, ccComment.c_str(), + this->DirWork.c_str()); + } + // Reconfigure when .qrc file changes + makefile->AddCMakeDependFile(qrc.QrcFile); } } - if (!GetUicExecutable()) { - return false; - } - - return true; -} - -bool cmQtAutoGenInitializer::InitCustomTargetsRcc() -{ - if (!GetRccExecutable()) { - return false; - } return true; } @@ -1083,25 +1126,14 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() CWrite("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE", MfDef("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")); CWrite("AM_BUILD_DIR", this->DirBuild); - if (this->MultiConfig) { - CWriteMap("AM_INCLUDE_DIR", this->DirConfigInclude); - } else { - CWrite("AM_INCLUDE_DIR", this->DirInclude); - } + CWrite("AM_INCLUDE_DIR", this->DirInclude); + CWriteMap("AM_INCLUDE_DIR", this->DirConfigInclude); ofs << "# Files\n"; - CWriteList("AM_SOURCES", this->Sources); - CWriteList("AM_HEADERS", this->Headers); - if (this->MultiConfig) { - std::map settingsFiles; - for (std::string const& cfg : this->ConfigsList) { - settingsFiles[cfg] = - AppendFilenameSuffix(this->AutogenSettingsFile, "_" + cfg); - } - CWriteMap("AM_SETTINGS_FILE", settingsFiles); - } else { - CWrite("AM_SETTINGS_FILE", this->AutogenSettingsFile); - } + CWriteList("AM_SOURCES", this->MocUic.Sources); + CWriteList("AM_HEADERS", this->MocUic.Headers); + CWrite("AM_SETTINGS_FILE", this->AutogenSettingsFile); + CWriteMap("AM_SETTINGS_FILE", this->AutogenConfigSettingsFile); ofs << "# Qt\n"; CWrite("AM_QT_VERSION_MAJOR", this->QtVersionMajor); @@ -1146,12 +1178,7 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() bool cmQtAutoGenInitializer::SetupWriteRccInfo() { - cmMakefile* makefile = this->Target->Target->GetMakefile(); - for (Qrc const& qrc : this->Rcc.Qrcs) { - // Register rcc info file as generated - makefile->AddCMakeOutputFile(qrc.InfoFile); - cmGeneratedFileStream ofs; ofs.SetCopyIfDifferent(true); ofs.Open(qrc.InfoFile.c_str(), false, true); @@ -1174,24 +1201,13 @@ bool cmQtAutoGenInitializer::SetupWriteRccInfo() CWrite("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE"); CWrite("ARCC_VERBOSITY", this->Verbosity); ofs << "# Settings file\n"; - if (this->MultiConfig) { - std::map settingsFiles; - for (std::string const& cfg : this->ConfigsList) { - settingsFiles[cfg] = - AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg); - } - CWriteMap("ARCC_SETTINGS_FILE", settingsFiles); - } else { - CWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile); - } + CWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile); + CWriteMap("ARCC_SETTINGS_FILE", qrc.ConfigSettingsFile); ofs << "# Directories\n"; CWrite("ARCC_BUILD_DIR", this->DirBuild); - if (this->MultiConfig) { - CWriteMap("ARCC_INCLUDE_DIR", this->DirConfigInclude); - } else { - CWrite("ARCC_INCLUDE_DIR", this->DirInclude); - } + CWrite("ARCC_INCLUDE_DIR", this->DirInclude); + CWriteMap("ARCC_INCLUDE_DIR", this->DirConfigInclude); ofs << "# Rcc executable\n"; CWrite("ARCC_RCC_EXECUTABLE", this->Rcc.Executable); diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 6ade2ed..16f9cdd 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -12,6 +12,7 @@ #include class cmGeneratorTarget; +class cmTarget; /// @brief Initializes the QtAutoGen generators class cmQtAutoGenInitializer : public cmQtAutoGen @@ -38,6 +39,7 @@ public: std::string PathChecksum; std::string InfoFile; std::string SettingsFile; + std::map ConfigSettingsFile; std::string RccFile; bool Generated; bool Unique; @@ -54,9 +56,13 @@ public: bool SetupCustomTargets(); private: - bool InitCustomTargetsMoc(); - bool InitCustomTargetsUic(); - bool InitCustomTargetsRcc(); + bool InitMoc(); + bool InitUic(); + bool InitRcc(); + + bool InitScanFiles(); + bool InitAutogenTarget(); + bool InitRccTargets(); bool SetupWriteAutogenInfo(); bool SetupWriteRccInfo(); @@ -90,15 +96,24 @@ private: std::string AutogenFolder; std::string AutogenInfoFile; std::string AutogenSettingsFile; + std::map AutogenConfigSettingsFile; + std::set AutogenDependFiles; + std::set AutogenDependTargets; // Directories std::string DirInfo; std::string DirBuild; std::string DirWork; std::string DirInclude; std::map DirConfigInclude; - // Sources - std::vector Headers; - std::vector Sources; + // Moc and UIC + struct + { + // Sources + std::vector Headers; + std::vector Sources; + std::vector HeadersGenerated; + std::vector SourcesGenerated; + } MocUic; // Moc struct { -- cgit v0.12 From f3451358456dc10169f56bfbd2de7d311df1eef3 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Wed, 25 Jul 2018 13:42:45 +0200 Subject: Autogen: For Qt5 pass all implicit include directories to moc For Qt4 it was not possible to pass all compiler implicit include directories to moc because it couldn't handle some system headers. For reference see commit 753b905ec86ffe369d4f59a7a8ced5fedc42939f, commit d2536579d51e77827b8e55f39123316324314781 and [QTBUG-28045](https://bugreports.qt.io/browse/QTBUG-28045). For Qt5's moc the problem does not persist anymore so we can (and should) pass all implicit include directories to moc. Fixes #18041 --- Source/cmQtAutoGenInitializer.cxx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 607afbf..7cfdeba 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -380,13 +380,15 @@ bool cmQtAutoGenInitializer::InitMoc() // Moc includes { - auto GetIncludeDirs = [this, - localGen](std::string const& cfg) -> std::string { + bool const appendImplicit = (this->QtVersionMajor == "5"); + auto GetIncludeDirs = + [this, localGen, appendImplicit](std::string const& cfg) -> std::string { // Get the include dirs for this target, without stripping the implicit // include dirs off, see // https://gitlab.kitware.com/cmake/cmake/issues/13667 std::vector dirs; - localGen->GetIncludeDirectories(dirs, this->Target, "CXX", cfg, false); + localGen->GetIncludeDirectories(dirs, this->Target, "CXX", cfg, false, + appendImplicit); return cmJoin(dirs, ";"); }; -- cgit v0.12 From 7bb70054e443813dfc21d1b4acc0e719b40f55d8 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Sun, 22 Jul 2018 19:02:39 +0200 Subject: Autogen: Add test for Q_OS_ macros --- Tests/QtAutogen/CommonTests.cmake | 3 ++ Tests/QtAutogen/MocOsMacros/CMakeLists.txt | 16 +++++++ Tests/QtAutogen/MocOsMacros/TestClass.cpp | 77 ++++++++++++++++++++++++++++++ Tests/QtAutogen/MocOsMacros/TestClass.hpp | 52 ++++++++++++++++++++ Tests/QtAutogen/MocOsMacros/main.cpp | 32 +++++++++++++ 5 files changed, 180 insertions(+) create mode 100644 Tests/QtAutogen/MocOsMacros/CMakeLists.txt create mode 100644 Tests/QtAutogen/MocOsMacros/TestClass.cpp create mode 100644 Tests/QtAutogen/MocOsMacros/TestClass.hpp create mode 100644 Tests/QtAutogen/MocOsMacros/main.cpp diff --git a/Tests/QtAutogen/CommonTests.cmake b/Tests/QtAutogen/CommonTests.cmake index cd05aeb..55d36e6 100644 --- a/Tests/QtAutogen/CommonTests.cmake +++ b/Tests/QtAutogen/CommonTests.cmake @@ -23,6 +23,9 @@ endif() if(QT_TEST_ALLOW_QT_MACROS) ADD_AUTOGEN_TEST(MocCMP0071) endif() +if(NOT QT_TEST_VERSION STREQUAL 4) + ADD_AUTOGEN_TEST(MocOsMacros mocOsMacros) +endif() ADD_AUTOGEN_TEST(UicInclude uicInclude) ADD_AUTOGEN_TEST(UicInterface QtAutoUicInterface) ADD_AUTOGEN_TEST(ObjectLibrary someProgram) diff --git a/Tests/QtAutogen/MocOsMacros/CMakeLists.txt b/Tests/QtAutogen/MocOsMacros/CMakeLists.txt new file mode 100644 index 0000000..51a0ebd --- /dev/null +++ b/Tests/QtAutogen/MocOsMacros/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.11) +project(MocOsMacros) +include("../AutogenTest.cmake") + +# Tests if moc processes the macro Q_OS_MAC + +set(CMAKE_AUTOMOC True) + +add_executable(mocOsMacros + main.cpp + TestClass.cpp + TestClass.hpp +) +target_link_libraries(mocOsMacros PRIVATE ${QT_QTCORE_TARGET}) + +message ( "CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES: ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}" ) diff --git a/Tests/QtAutogen/MocOsMacros/TestClass.cpp b/Tests/QtAutogen/MocOsMacros/TestClass.cpp new file mode 100644 index 0000000..340d130 --- /dev/null +++ b/Tests/QtAutogen/MocOsMacros/TestClass.cpp @@ -0,0 +1,77 @@ +#include "TestClass.hpp" +#include + +// -- Mac +#ifndef Q_OS_MAC +void TestClass::MacNotDef() +{ + std::cout << "MacNotDef\n"; +} +#else +void TestClass::MacNotDefElse() +{ + std::cout << "MacNotDefElse\n"; +} +#endif + +#ifdef Q_OS_MAC +void TestClass::MacDef() +{ + std::cout << "MacDef\n"; +} +#else +void TestClass::MacDefElse() +{ + std::cout << "MacDefElse\n"; +} +#endif + +// -- Unix +#ifndef Q_OS_UNIX +void TestClass::UnixNotDef() +{ + std::cout << "UnixNotDef\n"; +} +#else +void TestClass::UnixNotDefElse() +{ + std::cout << "UnixNotDefElse\n"; +} +#endif + +#ifdef Q_OS_UNIX +void TestClass::UnixDef() +{ + std::cout << "UnixDef\n"; +} +#else +void TestClass::UnixDefElse() +{ + std::cout << "UnixDefElse\n"; +} +#endif + +// -- Windows +#ifndef Q_OS_WIN +void TestClass::WindowsNotDef() +{ + std::cout << "WindowsNotDef\n"; +} +#else +void TestClass::WindowsNotDefElse() +{ + std::cout << "WindowsNotDefElse\n"; +} +#endif + +#ifdef Q_OS_WIN +void TestClass::WindowsDef() +{ + std::cout << "WindowsDef\n"; +} +#else +void TestClass::WindowsDefElse() +{ + std::cout << "WindowsDefElse\n"; +} +#endif diff --git a/Tests/QtAutogen/MocOsMacros/TestClass.hpp b/Tests/QtAutogen/MocOsMacros/TestClass.hpp new file mode 100644 index 0000000..53000aa --- /dev/null +++ b/Tests/QtAutogen/MocOsMacros/TestClass.hpp @@ -0,0 +1,52 @@ +#ifndef TestClass_hpp +#define TestClass_hpp + +#include +#include + +class TestClass : public QObject +{ + Q_OBJECT +public Q_SLOTS: + +// -- Mac +#ifndef Q_OS_MAC + void MacNotDef(); +#else + void MacNotDefElse(); +#endif + +#ifdef Q_OS_MAC + void MacDef(); +#else + void MacDefElse(); +#endif + +// -- Unix +#ifndef Q_OS_UNIX + void UnixNotDef(); +#else + void UnixNotDefElse(); +#endif + +#ifdef Q_OS_UNIX + void UnixDef(); +#else + void UnixDefElse(); +#endif + +// -- Windows +#ifndef Q_OS_WIN + void WindowsNotDef(); +#else + void WindowsNotDefElse(); +#endif + +#ifdef Q_OS_WIN + void WindowsDef(); +#else + void WindowsDefElse(); +#endif +}; + +#endif /* TestClass_hpp */ diff --git a/Tests/QtAutogen/MocOsMacros/main.cpp b/Tests/QtAutogen/MocOsMacros/main.cpp new file mode 100644 index 0000000..f8eec3c --- /dev/null +++ b/Tests/QtAutogen/MocOsMacros/main.cpp @@ -0,0 +1,32 @@ +#include "TestClass.hpp" +#include + +int main() +{ + TestClass a; +#ifdef Q_OS_MAC + a.MacNotDefElse(); + a.MacDef(); +#else + a.MacNotDef(); + a.MacDefElse(); +#endif + +#ifdef Q_OS_UNIX + a.UnixNotDefElse(); + a.UnixDef(); +#else + a.UnixNotDef(); + a.UnixDefElse(); +#endif + +#ifdef Q_OS_WIN + a.WindowsNotDefElse(); + a.WindowsDef(); +#else + a.WindowsNotDef(); + a.WindowsDefElse(); +#endif + + return 0; +} -- cgit v0.12