diff options
-rw-r--r-- | Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst | 3 | ||||
-rw-r--r-- | Source/cmQtAutoGenInitializer.cxx | 1 | ||||
-rw-r--r-- | Source/cmQtAutoMocUic.cxx | 92 | ||||
-rw-r--r-- | Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleA.hpp | 2 | ||||
-rw-r--r-- | Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleB.hpp | 2 | ||||
-rw-r--r-- | Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleC.hpp | 2 | ||||
-rw-r--r-- | Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleD.hpp | 2 | ||||
-rw-r--r-- | Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleEInclude.hpp | 2 | ||||
-rw-r--r-- | Tests/QtAutogen/RerunMocPlugin/MocPlugin/UtilityMacros.hpp | 4 | ||||
-rw-r--r-- | Tests/RunCMake/NinjaMultiConfig/Qt5.cmake | 8 |
10 files changed, 97 insertions, 21 deletions
diff --git a/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst b/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst index 69957bf..6eda26c 100644 --- a/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst +++ b/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst @@ -26,6 +26,9 @@ See :prop_tgt:`AUTOGEN_TARGET_DEPENDS` for reference. By default :prop_tgt:`AUTOMOC_DEPEND_FILTERS` is initialized from :variable:`CMAKE_AUTOMOC_DEPEND_FILTERS`, which is empty by default. +From Qt 5.15.0 on this variable is ignored as moc is able to output the correct +dependencies. + See the :manual:`cmake-qt(7)` manual for more information on using CMake with Qt. diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index ebb522b..d9b0aff 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -1409,6 +1409,7 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() info.SetConfig("INCLUDE_DIR", this->Dir.Include); info.SetUInt("QT_VERSION_MAJOR", this->QtVersion.Major); + info.SetUInt("QT_VERSION_MINOR", this->QtVersion.Minor); info.Set("QT_MOC_EXECUTABLE", this->Moc.Executable); info.Set("QT_UIC_EXECUTABLE", this->Uic.Executable); diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index fa5129d..82464a7 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -25,6 +25,8 @@ #include "cmCryptoHash.h" #include "cmFileTime.h" +#include "cmGccDepfileReader.h" +#include "cmGccDepfileReaderTypes.h" #include "cmGeneratedFileStream.h" #include "cmQtAutoGen.h" #include "cmQtAutoGenerator.h" @@ -170,7 +172,7 @@ public: // -- Attributes // - Config bool MultiConfig = false; - unsigned int QtVersionMajor = 4; + IntegerVersion QtVersion = { 4, 0 }; unsigned int ThreadCount = 0; // - Directories std::string AutogenBuildDir; @@ -216,6 +218,7 @@ public: bool SettingsChanged = false; bool RelaxedMode = false; bool PathPrefix = false; + bool CanOutputDependencies = false; cmFileTime ExecutableTime; std::string Executable; std::string CompFileAbs; @@ -485,8 +488,17 @@ public: class JobCompileMocT : public JobCompileT { public: - using JobCompileT::JobCompileT; + JobCompileMocT(MappingHandleT uicMapping, + std::unique_ptr<std::string> reason, + ParseCacheT::FileHandleT cacheEntry) + : JobCompileT(std::move(uicMapping), std::move(reason)) + , CacheEntry(std::move(cacheEntry)) + { + } void Process() override; + + protected: + ParseCacheT::FileHandleT CacheEntry; }; /** uic compiles a file. */ @@ -546,6 +558,9 @@ private: void Abort(bool error); // -- Generation bool CreateDirectories(); + // -- Support for depfiles + static std::vector<std::string> dependenciesFromDepFile( + const char* filePath); private: // -- Settings @@ -951,7 +966,7 @@ void cmQtAutoMocUicT::JobParseT::MocMacro() void cmQtAutoMocUicT::JobParseT::MocDependecies() { - if (MocConst().DependFilters.empty()) { + if (MocConst().DependFilters.empty() || MocConst().CanOutputDependencies) { return; } @@ -1674,8 +1689,13 @@ bool cmQtAutoMocUicT::JobProbeDepsMocT::Generate(MappingHandleT const& mapping, if (Probe(*mapping, reason.get())) { // Register the parent directory for creation MocEval().OutputDirs.emplace(cmQtAutoGen::ParentDir(mapping->OutputFile)); + // Fetch the cache entry for the source file + std::string const& sourceFile = mapping->SourceFile->FileName; + ParseCacheT::GetOrInsertT cacheEntry = + BaseEval().ParseCache.GetOrInsert(sourceFile); // Add moc job - Gen()->WorkerPool().EmplaceJob<JobCompileMocT>(mapping, std::move(reason)); + Gen()->WorkerPool().EmplaceJob<JobCompileMocT>( + mapping, std::move(reason), std::move(cacheEntry.first)); // Check if a moc job for a mocs_compilation.cpp entry was generated if (compFile) { MocEval().CompUpdated = true; @@ -1779,6 +1799,14 @@ cmQtAutoMocUicT::JobProbeDepsMocT::FindDependency( std::string const& sourceDir, std::string const& includeString) const { using ResPair = std::pair<std::string, cmFileTime>; + // moc's dependency file contains absolute paths + if (MocConst().CanOutputDependencies) { + ResPair res{ includeString, {} }; + if (res.second.Load(res.first)) { + return res; + } + return {}; + } // Search in vicinity of the source { ResPair res{ sourceDir + includeString, {} }; @@ -1947,6 +1975,9 @@ void cmQtAutoMocUicT::JobCompileMocT::Process() } // Add extra options cm::append(cmd, MocConst().OptionsExtra); + if (MocConst().CanOutputDependencies) { + cmd.emplace_back("--output-dep-file"); + } // Add output file cmd.emplace_back("-o"); cmd.push_back(outputFile); @@ -1956,12 +1987,7 @@ void cmQtAutoMocUicT::JobCompileMocT::Process() // Execute moc command cmWorkerPool::ProcessResultT result; - if (RunProcess(GenT::MOC, result, cmd, Reason.get())) { - // Moc command success. Print moc output. - if (!result.StdOut.empty()) { - Log().Info(GenT::MOC, result.StdOut); - } - } else { + if (!RunProcess(GenT::MOC, result, cmd, Reason.get())) { // Moc command failed std::string includers; if (!Mapping->IncluderFiles.empty()) { @@ -1976,6 +2002,28 @@ void cmQtAutoMocUicT::JobCompileMocT::Process() MessagePath(outputFile), '\n', includers, result.ErrorMessage), cmd, result.StdOut); + return; + } + + // Moc command success. Print moc output. + if (!result.StdOut.empty()) { + Log().Info(GenT::MOC, result.StdOut); + } + + // Extract dependencies from the dep file moc generated for us + if (MocConst().CanOutputDependencies) { + const std::string depfile = outputFile + ".d"; + if (Log().Verbose()) { + Log().Info(GenT::MOC, + "Reading dependencies from " + MessagePath(depfile)); + } + if (!cmSystemTools::FileExists(depfile)) { + Log().Warning(GenT::MOC, + "Dependency file " + MessagePath(depfile) + + " does not exist."); + return; + } + CacheEntry->Moc.Depends = dependenciesFromDepFile(depfile.c_str()); } } @@ -1992,7 +2040,7 @@ void cmQtAutoMocUicT::JobCompileUicT::Process() auto optionIt = UicConst().UiFiles.find(sourceFile); if (optionIt != UicConst().UiFiles.end()) { UicMergeOptions(allOpts, optionIt->second.Options, - (BaseConst().QtVersionMajor == 5)); + (BaseConst().QtVersion.Major == 5)); } cm::append(cmd, allOpts); } @@ -2082,7 +2130,8 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info) { // -- Required settings if (!info.GetBool("MULTI_CONFIG", BaseConst_.MultiConfig, true) || - !info.GetUInt("QT_VERSION_MAJOR", BaseConst_.QtVersionMajor, true) || + !info.GetUInt("QT_VERSION_MAJOR", BaseConst_.QtVersion.Major, true) || + !info.GetUInt("QT_VERSION_MINOR", BaseConst_.QtVersion.Minor, true) || !info.GetUInt("PARALLEL", BaseConst_.ThreadCount, false) || !info.GetString("BUILD_DIR", BaseConst_.AutogenBuildDir, true) || !info.GetStringConfig("INCLUDE_DIR", BaseConst_.AutogenIncludeDir, @@ -2143,8 +2192,10 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info) MocConst_.MacroFilters.emplace_back( item, ("[\n][ \t]*{?[ \t]*" + item).append("[^a-zA-Z0-9_]")); } - // Dependency filters - { + // Can moc output dependencies or do we need to setup dependency filters? + if (BaseConst_.QtVersion >= IntegerVersion(5, 15)) { + MocConst_.CanOutputDependencies = true; + } else { Json::Value const& val = info.GetValue("MOC_DEPEND_FILTERS"); if (!val.isArray()) { return info.LogError("MOC_DEPEND_FILTERS JSON value is not an array."); @@ -2660,6 +2711,19 @@ bool cmQtAutoMocUicT::CreateDirectories() return true; } +std::vector<std::string> cmQtAutoMocUicT::dependenciesFromDepFile( + const char* filePath) +{ + cmGccDepfileContent content = cmReadGccDepfile(filePath); + if (content.empty()) { + return {}; + } + + // Moc outputs a depfile with exactly one rule. + // Discard the rule and return the dependencies. + return content.front().paths; +} + void cmQtAutoMocUicT::Abort(bool error) { if (error) { diff --git a/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleA.hpp b/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleA.hpp index e1fdf0b..198ae98 100644 --- a/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleA.hpp +++ b/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleA.hpp @@ -10,7 +10,7 @@ class StyleA : public QStylePlugin Q_OBJECT // Json file in source local directory Q_PLUGIN_METADATA(IID "org.styles.A" FILE "StyleA.json") - A_CUSTOM_MACRO(SomeArg, "StyleA_Custom.json", AnotherArg) + A_CUSTOM_MACRO(org.styles.A, "StyleA_Custom.json", AnotherArg) public: QStyle* create(const QString& key); }; diff --git a/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleB.hpp b/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleB.hpp index 7550d0c..8ce8d77 100644 --- a/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleB.hpp +++ b/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleB.hpp @@ -10,7 +10,7 @@ class StyleB : public QStylePlugin Q_OBJECT // Json file in source local subdirectory Q_PLUGIN_METADATA(IID "org.styles.B" FILE "jsonIn/StyleB.json") - A_CUSTOM_MACRO(SomeArg, "jsonIn/StyleB_Custom.json", AnotherArg) + A_CUSTOM_MACRO(org.styles.B, "jsonIn/StyleB_Custom.json", AnotherArg) public: QStyle* create(const QString& key); }; diff --git a/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleC.hpp b/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleC.hpp index ec71bec..53171e3 100644 --- a/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleC.hpp +++ b/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleC.hpp @@ -10,7 +10,7 @@ class StyleC : public QStylePlugin Q_OBJECT // Json file in global root directory Q_PLUGIN_METADATA(IID "org.styles.C" FILE "StyleC.json") - A_CUSTOM_MACRO(SomeArg, "StyleC_Custom.json", AnotherArg) + A_CUSTOM_MACRO(org.styles.C, "StyleC_Custom.json", AnotherArg) public: QStyle* create(const QString& key); }; diff --git a/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleD.hpp b/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleD.hpp index 3c093b9..29674f9 100644 --- a/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleD.hpp +++ b/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleD.hpp @@ -10,7 +10,7 @@ class StyleD : public QStylePlugin Q_OBJECT // Json file in global sub director Q_PLUGIN_METADATA(IID "org.styles.D" FILE "sub/StyleD.json") - A_CUSTOM_MACRO(SomeArg, "sub/StyleD_Custom.json", AnotherArg) + A_CUSTOM_MACRO(org.styles.D, "sub/StyleD_Custom.json", AnotherArg) public: QStyle* create(const QString& key); }; diff --git a/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleEInclude.hpp b/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleEInclude.hpp index 5f10fb4..7318220 100644 --- a/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleEInclude.hpp +++ b/Tests/QtAutogen/RerunMocPlugin/MocPlugin/StyleEInclude.hpp @@ -10,7 +10,7 @@ class StyleE : public QStylePlugin Q_OBJECT // Json files in global root directory Q_PLUGIN_METADATA(IID "org.styles.E" FILE "StyleE.json") - A_CUSTOM_MACRO(SomeArg, "StyleE_Custom.json", AnotherArg) + A_CUSTOM_MACRO(org.styles.E, "StyleE_Custom.json", AnotherArg) public: QStyle* create(const QString& key); }; diff --git a/Tests/QtAutogen/RerunMocPlugin/MocPlugin/UtilityMacros.hpp b/Tests/QtAutogen/RerunMocPlugin/MocPlugin/UtilityMacros.hpp index 53a4284..2f558a8 100644 --- a/Tests/QtAutogen/RerunMocPlugin/MocPlugin/UtilityMacros.hpp +++ b/Tests/QtAutogen/RerunMocPlugin/MocPlugin/UtilityMacros.hpp @@ -1,7 +1,7 @@ #ifndef UTILITYMACROS_HPP #define UTILITYMACROS_HPP -// Empty test macro definition -#define A_CUSTOM_MACRO(name, jsonFile, pluginRegistrations) +#define A_CUSTOM_MACRO(url, jsonFile, pluginRegistrations) \ + Q_PLUGIN_METADATA(IID #url FILE jsonFile) #endif diff --git a/Tests/RunCMake/NinjaMultiConfig/Qt5.cmake b/Tests/RunCMake/NinjaMultiConfig/Qt5.cmake index 6a80b1d..dfc0f50 100644 --- a/Tests/RunCMake/NinjaMultiConfig/Qt5.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/Qt5.cmake @@ -11,8 +11,16 @@ target_link_libraries(exe PRIVATE Qt5::Core) include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake) generate_output_files(exe) +set(moc_writes_depfiles 0) +if(Qt5Core_VERSION VERSION_GREATER_EQUAL "5.15.0") + set(moc_writes_depfiles 1) +endif() + set(autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/mocs_compilation.cpp") foreach(c IN LISTS CMAKE_CONFIGURATION_TYPES) list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/include_${c}/moc_qt5.cpp") + if(moc_writes_depfiles) + list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/include_${c}/moc_qt5.cpp.d") + endif() endforeach() file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "set(AUTOGEN_FILES [==[${autogen_files}]==])\n") |