summaryrefslogtreecommitdiffstats
path: root/Source/cmQtAutoMocUic.h
diff options
context:
space:
mode:
authorSebastian Holtermann <sebholt@xwmw.org>2019-05-02 09:03:13 (GMT)
committerSebastian Holtermann <sebholt@xwmw.org>2019-05-07 10:42:19 (GMT)
commit7d50e1c6118b292ea3061ec9fee0230c5d50a5ff (patch)
tree48d3f4c459c88cc2c02fa78b0279324e2fbb5cce /Source/cmQtAutoMocUic.h
parentc6f6e2b3053de02de149e80bd6a0f686a6731f68 (diff)
downloadCMake-7d50e1c6118b292ea3061ec9fee0230c5d50a5ff.zip
CMake-7d50e1c6118b292ea3061ec9fee0230c5d50a5ff.tar.gz
CMake-7d50e1c6118b292ea3061ec9fee0230c5d50a5ff.tar.bz2
Autogen: Refactor AUTOMOC and AUTOUIC and add source file parse data caching
New features ------------ CMake's `AUTOMOC` and `AUTOUIC` now cache information extracted when parsing source files in `CMakeFiles/<ORIGIN>_autogen.dir/ParseCache.txt`. This leads to faster `<ORIGIN>_autogen` target rebuilds, because source files will be parsed again only if they're newer than the `ParseCache.txt` file. The parse cache will be recomputed if it is older than the CMake executable. `AUTOMOC` and `AUTOUIC` now check if `moc` or `uic` output files are older than the `moc` or `uic` executable. If an output file is older than the compiler, it will be regenerated. Therefore if a new `moc` or `uic` version is installed, all output files will be regenerated. `AUTOMOC` and `AUTOUIC` error and warning messages are more detailed. Internal changes ---------------- `moc` and `uic` output file names are not computed in the `_autogen` target anymore but in `cmQtAutoGenInitializer`. This makes the available at the configuration stage for improved dependency computations (to be done). In `AutogenInfo.cmake`, equally sized lists for "source file names", "source file flags" and "compiler output file names" are passed to the `_autogen` target. This replaces the separate file lists for `AUTOMOC` and `AUTOUIC`. Files times are read from the file system only once by using `cmFileTime` instances instead of `cmQtAutoGenerator::FileSystem::FileIsOlderThan` calls. All calls to not thread safe file system functions are moved to non concurrent fence jobs (see `cmWorkerPool::JobT::IsFence()`). This renders the `cmQtAutoGenerator::FileSystem` wrapper class obsolete and it is removed. Instead of composing a single large settings string that is fed to the `cmCryptoHash`, now all setting sub strings are fed one by one to the `cmCryptoHash` and the finalized result is stored. The `std::mutex` in `cmQtAutoGenerator::Logger` is tagged `mutable` and most `cmQtAutoGenerator::Logger` methods become `const`. Outlook ------- This patch provides the framework required to - extract dependencies from `.ui` files in `AUTOUIC`. These will help to address issue #15420 "AUTOUIC: Track uic external inputs". - generate adaptive `make` and `ninja` files in the `_autogen` target. These will help to address issue #16776 "AUTOUIC: Ninja needs two passes to correctly build Qt project". - generate (possibly empty) `moc` and `uic` files for all headers instead of a `mocs_compilation.cpp` file. This will help to address issue #17277 "AUTOMOC: Provide a option to allow AUTOMOC to compile individual " "moc_x.cxx instead of including all in mocs_compilation.cxx"
Diffstat (limited to 'Source/cmQtAutoMocUic.h')
-rw-r--r--Source/cmQtAutoMocUic.h485
1 files changed, 324 insertions, 161 deletions
diff --git a/Source/cmQtAutoMocUic.h b/Source/cmQtAutoMocUic.h
index 3902abb..8061c13 100644
--- a/Source/cmQtAutoMocUic.h
+++ b/Source/cmQtAutoMocUic.h
@@ -5,25 +5,28 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include "cmFileTime.h"
#include "cmQtAutoGen.h"
#include "cmQtAutoGenerator.h"
#include "cmWorkerPool.h"
#include "cmsys/RegularExpression.hxx"
-#include <array>
#include <atomic>
+#include <cstddef>
#include <map>
#include <memory> // IWYU pragma: keep
-#include <mutex>
#include <set>
#include <string>
+#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
class cmMakefile;
-// @brief AUTOMOC and AUTOUIC generator
+/** \class cmQtAutoMocUic
+ * \brief AUTOMOC and AUTOUIC generator
+ */
class cmQtAutoMocUic : public cmQtAutoGenerator
{
public:
@@ -35,10 +38,10 @@ public:
public:
// -- Types
- typedef std::multimap<std::string, std::array<std::string, 2>> IncludesMap;
- /// @brief Search key plus regular expression pair
- ///
+ /**
+ * Search key plus regular expression pair
+ */
struct KeyExpT
{
KeyExpT() = default;
@@ -59,35 +62,123 @@ public:
cmsys::RegularExpression Exp;
};
- /// @brief Common settings
- ///
- class BaseSettingsT
+ /**
+ * Include string with sub parts
+ */
+ struct IncludeKeyT
+ {
+ IncludeKeyT(std::string const& key, std::size_t basePrefixLength);
+
+ std::string Key; // Full include string
+ std::string Dir; // Include directory
+ std::string Base; // Base part of the include file name
+ };
+
+ /**
+ * Source file parsing cache
+ */
+ class ParseCacheT
+ {
+ public:
+ // -- Types
+ /**
+ * Entry of the file parsing cache
+ */
+ struct FileT
+ {
+ void Clear();
+
+ struct MocT
+ {
+ std::string Macro;
+ struct IncludeT
+ {
+ std::vector<IncludeKeyT> Underscore;
+ std::vector<IncludeKeyT> Dot;
+ } Include;
+ std::vector<std::string> Depends;
+ } Moc;
+
+ struct UicT
+ {
+ std::vector<IncludeKeyT> Include;
+ std::vector<std::string> Depends;
+ } Uic;
+ };
+ typedef std::shared_ptr<FileT> FileHandleT;
+ typedef std::pair<FileHandleT, bool> GetOrInsertT;
+
+ public:
+ ParseCacheT();
+ ~ParseCacheT();
+
+ void Clear();
+
+ bool ReadFromFile(std::string const& fileName);
+ bool WriteToFile(std::string const& fileName);
+
+ //! Might return an invalid handle
+ FileHandleT Get(std::string const& fileName) const;
+ //! Always returns a valid handle
+ GetOrInsertT GetOrInsert(std::string const& fileName);
+
+ private:
+ std::unordered_map<std::string, FileHandleT> Map_;
+ };
+
+ /**
+ * Source file data
+ */
+ class SourceFileT
{
public:
- // -- Volatile methods
- BaseSettingsT(FileSystem* fileSystem)
- : MultiConfig(false)
- , IncludeProjectDirsBefore(false)
- , QtVersionMajor(4)
- , NumThreads(1)
- , FileSys(fileSystem)
+ SourceFileT(std::string fileName)
+ : FileName(std::move(fileName))
{
}
+ public:
+ std::string FileName;
+ cmFileTime FileTime;
+ ParseCacheT::FileHandleT ParseData;
+ std::string BuildPath;
+ bool Moc = false;
+ bool Uic = false;
+ };
+ typedef std::shared_ptr<SourceFileT> SourceFileHandleT;
+ typedef std::map<std::string, SourceFileHandleT> SourceFileMapT;
+
+ /**
+ * Meta compiler file mapping information
+ */
+ struct MappingT
+ {
+ SourceFileHandleT SourceFile;
+ std::string OutputFile;
+ std::string IncludeString;
+ std::vector<SourceFileHandleT> IncluderFiles;
+ };
+ typedef std::shared_ptr<MappingT> MappingHandleT;
+ typedef std::map<std::string, MappingHandleT> MappingMapT;
+
+ /**
+ * Common settings
+ */
+ class BaseSettingsT
+ {
+ public:
+ // -- Constructors
+ BaseSettingsT();
+ ~BaseSettingsT();
+
BaseSettingsT(BaseSettingsT const&) = delete;
BaseSettingsT& operator=(BaseSettingsT const&) = delete;
- // -- Const methods
- std::string AbsoluteBuildPath(std::string const& relativePath) const;
- bool FindHeader(std::string& header,
- std::string const& testBasePath) const;
-
// -- Attributes
// - Config
- bool MultiConfig;
- bool IncludeProjectDirsBefore;
- unsigned int QtVersionMajor;
- unsigned int NumThreads;
+ bool MultiConfig = false;
+ bool IncludeProjectDirsBefore = false;
+ unsigned int QtVersionMajor = 4;
// - Directories
std::string ProjectSourceDir;
std::string ProjectBinaryDir;
@@ -96,37 +187,50 @@ public:
std::string AutogenBuildDir;
std::string AutogenIncludeDir;
// - Files
+ std::string CMakeExecutable;
+ cmFileTime CMakeExecutableTime;
+ std::string ParseCacheFile;
std::vector<std::string> HeaderExtensions;
- // - File system
- FileSystem* FileSys;
};
- /// @brief Moc settings
- ///
+ /**
+ * Shared common variables
+ */
+ class BaseEvalT
+ {
+ public:
+ // -- Parse Cache
+ bool ParseCacheChanged = false;
+ cmFileTime ParseCacheTime;
+ ParseCacheT ParseCache;
+
+ // -- Sources
+ SourceFileMapT Headers;
+ SourceFileMapT Sources;
+ };
+
+ /**
+ * Moc settings
+ */
class MocSettingsT
{
public:
- MocSettingsT(FileSystem* fileSys)
- : FileSys(fileSys)
- {
- }
+ // -- Constructors
+ MocSettingsT();
+ ~MocSettingsT();
MocSettingsT(MocSettingsT const&) = delete;
MocSettingsT& operator=(MocSettingsT const&) = delete;
// -- Const methods
bool skipped(std::string const& fileName) const;
- std::string FindMacro(std::string const& content) const;
std::string MacrosString() const;
- std::string FindIncludedFile(std::string const& sourcePath,
- std::string const& includeString) const;
- void FindDependencies(std::string const& content,
- std::set<std::string>& depends) const;
// -- Attributes
bool Enabled = false;
bool SettingsChanged = false;
bool RelaxedMode = false;
+ cmFileTime ExecutableTime;
std::string Executable;
std::string CompFileAbs;
std::string PredefsFileRel;
@@ -141,16 +245,35 @@ public:
std::vector<KeyExpT> DependFilters;
std::vector<KeyExpT> MacroFilters;
cmsys::RegularExpression RegExpInclude;
- // - File system
- FileSystem* FileSys;
};
- /// @brief Uic settings
- ///
+ /**
+ * Moc shared variables
+ */
+ class MocEvalT
+ {
+ public:
+ // -- predefines file
+ cmFileTime PredefsTime;
+ // -- Mappings
+ MappingMapT HeaderMappings;
+ MappingMapT SourceMappings;
+ MappingMapT Includes;
+ // -- Discovered files
+ SourceFileMapT HeadersDiscovered;
+ // -- Mocs compilation
+ bool CompUpdated = false;
+ std::vector<std::string> CompFiles;
+ };
+
+ /**
+ * Uic settings
+ */
class UicSettingsT
{
public:
- UicSettingsT() = default;
+ UicSettingsT();
+ ~UicSettingsT();
UicSettingsT(UicSettingsT const&) = delete;
UicSettingsT& operator=(UicSettingsT const&) = delete;
@@ -161,6 +284,7 @@ public:
// -- Attributes
bool Enabled = false;
bool SettingsChanged = false;
+ cmFileTime ExecutableTime;
std::string Executable;
std::unordered_set<std::string> SkipList;
std::vector<std::string> TargetOptions;
@@ -169,8 +293,19 @@ public:
cmsys::RegularExpression RegExpInclude;
};
- /// @brief Abstract job class for concurrent job processing
- ///
+ /**
+ * Uic shared variables
+ */
+ class UicEvalT
+ {
+ public:
+ SourceFileMapT UiFiles;
+ MappingMapT Includes;
+ };
+
+ /**
+ * Abstract job class for concurrent job processing
+ */
class JobT : public cmWorkerPool::JobT
{
protected:
@@ -188,10 +323,14 @@ public:
return static_cast<cmQtAutoMocUic*>(UserData());
};
- //! Get the file system interface. Only valid during Process() call!
- FileSystem& FileSys() { return Gen()->FileSys(); }
- //! Get the logger. Only valid during Process() call!
- Logger& Log() { return Gen()->Log(); }
+ // -- Accessors. Only valid during Process() call!
+ Logger const& Log() const { return Gen()->Log(); }
+ BaseSettingsT const& BaseConst() const { return Gen()->BaseConst(); }
+ BaseEvalT& BaseEval() const { return Gen()->BaseEval(); }
+ MocSettingsT const& MocConst() const { return Gen()->MocConst(); }
+ MocEvalT& MocEval() const { return Gen()->MocEval(); }
+ UicSettingsT const& UicConst() const { return Gen()->UicConst(); }
+ UicEvalT& UicEval() const { return Gen()->UicEval(); }
// -- Error logging with automatic abort
void LogError(GenT genType, std::string const& message) const;
@@ -205,11 +344,13 @@ public:
* @brief Run an external process. Use only during Process() call!
*/
bool RunProcess(GenT genType, cmWorkerPool::ProcessResultT& result,
- std::vector<std::string> const& command);
+ std::vector<std::string> const& command,
+ std::string* infoMessage = nullptr);
};
- /// @brief Fence job utility class
- ///
+ /**
+ * Fence job utility class
+ */
class JobFenceT : public JobT
{
public:
@@ -220,121 +361,152 @@ public:
void Process() override{};
};
- /// @brief Generate moc_predefs.h
- ///
- class JobMocPredefsT : public JobT
+ /**
+ * Generate moc_predefs.h
+ */
+ class JobMocPredefsT : public JobFenceT
{
- private:
void Process() override;
+ bool Update(std::string* reason) const;
};
- /// @brief Parses a source file
- ///
+ /**
+ * File parse job base class
+ */
class JobParseT : public JobT
{
public:
- JobParseT(std::string fileName, bool moc, bool uic, bool header = false)
- : FileName(std::move(fileName))
- , AutoMoc(moc)
- , AutoUic(uic)
- , Header(header)
+ JobParseT(SourceFileHandleT fileHandle)
+ : FileHandle(std::move(fileHandle))
{
}
- private:
- struct MetaT
- {
- std::string Content;
- std::string FileDir;
- std::string FileBase;
- };
+ protected:
+ bool ReadFile();
+ void CreateKeys(std::vector<IncludeKeyT>& container,
+ std::set<std::string> const& source,
+ std::size_t basePrefixLength);
+ void MocMacro();
+ void MocDependecies();
+ void MocIncludes();
+ void UicIncludes();
+
+ protected:
+ SourceFileHandleT FileHandle;
+ std::string Content;
+ };
+ /**
+ * Header file parse job
+ */
+ class JobParseHeaderT : public JobParseT
+ {
+ public:
+ using JobParseT::JobParseT;
void Process() override;
- bool ParseMocSource(MetaT const& meta);
- bool ParseMocHeader(MetaT const& meta);
- std::string MocStringHeaders(std::string const& fileBase) const;
- std::string MocFindIncludedHeader(std::string const& includerDir,
- std::string const& includeBase);
- bool ParseUic(MetaT const& meta);
- bool ParseUicInclude(MetaT const& meta, std::string&& includeString);
- std::string UicFindIncludedFile(MetaT const& meta,
- std::string const& includeString);
+ };
- private:
- std::string FileName;
- bool AutoMoc = false;
- bool AutoUic = false;
- bool Header = false;
+ /**
+ * Source file parse job
+ */
+ class JobParseSourceT : public JobParseT
+ {
+ public:
+ using JobParseT::JobParseT;
+ void Process() override;
};
- /// @brief Generates additional jobs after all files have been parsed
- ///
- class JobPostParseT : public JobFenceT
+ /**
+ * Evaluate parsed files
+ */
+ class JobEvaluateT : public JobFenceT
{
- private:
void Process() override;
+
+ // -- Moc
+ bool MocEvalHeader(SourceFileHandleT source);
+ bool MocEvalSource(SourceFileHandleT const& source);
+ SourceFileHandleT MocFindIncludedHeader(
+ std::string const& includerDir, std::string const& includeBase) const;
+ SourceFileHandleT MocFindHeader(std::string const& basePath) const;
+ std::string MocMessageTestHeaders(std::string const& fileBase) const;
+ bool MocRegisterIncluded(std::string const& includeString,
+ SourceFileHandleT includerFileHandle,
+ SourceFileHandleT sourceFileHandle,
+ bool sourceIsHeader) const;
+ void MocRegisterMapping(MappingHandleT mappingHandle,
+ bool sourceIsHeader) const;
+
+ // -- Uic
+ bool UicEval(SourceFileMapT const& fileMap);
+ bool UicEvalFile(SourceFileHandleT sourceFileHandle);
+ SourceFileHandleT UicFindIncludedUi(std::string const& sourceFile,
+ std::string const& sourceDir,
+ IncludeKeyT const& incKey) const;
+ bool UicRegisterMapping(std::string const& includeString,
+ SourceFileHandleT uiFileHandle,
+ SourceFileHandleT includerFileHandle);
};
- /// @brief Generate mocs_compilation.cpp
- ///
- class JobMocsCompilationT : public JobFenceT
+ /**
+ * Generates moc/uic jobs
+ */
+ class JobGenerateT : public JobFenceT
{
- private:
void Process() override;
+ // -- Moc
+ bool MocGenerate(MappingHandleT const& mapping, bool compFile) const;
+ bool MocUpdate(MappingT const& mapping, std::string* reason) const;
+ std::pair<std::string, cmFileTime> MocFindDependency(
+ std::string const& sourceDir, std::string const& includeString) const;
+ // -- Uic
+ bool UicGenerate(MappingHandleT const& mapping) const;
+ bool UicUpdate(MappingT const& mapping, std::string* reason) const;
};
- /// @brief Moc a file job
- ///
- class JobMocT : public JobT
+ /**
+ * File compiling base job
+ */
+ class JobCompileT : public JobT
{
public:
- JobMocT(std::string sourceFile, std::string includerFile,
- std::string includeString)
- : SourceFile(std::move(sourceFile))
- , IncluderFile(std::move(includerFile))
- , IncludeString(std::move(includeString))
+ JobCompileT(MappingHandleT uicMapping, std::unique_ptr<std::string> reason)
+ : Mapping(std::move(uicMapping))
+ , Reason(std::move(reason))
{
}
- void FindDependencies(std::string const& content);
+ protected:
+ MappingHandleT Mapping;
+ std::unique_ptr<std::string> Reason;
+ };
- private:
+ /**
+ * moc compiles a file
+ */
+ class JobMocT : public JobCompileT
+ {
+ public:
+ using JobCompileT::JobCompileT;
void Process() override;
- bool UpdateRequired();
- void GenerateMoc();
+ };
+ /**
+ * uic compiles a file
+ */
+ class JobUicT : public JobCompileT
+ {
public:
- std::string SourceFile;
- std::string IncluderFile;
- std::string IncludeString;
- std::string BuildFile;
- bool DependsValid = false;
- std::set<std::string> Depends;
+ using JobCompileT::JobCompileT;
+ void Process() override;
};
- /// @brief Uic a file job
+ /// @brief Generate mocs_compilation.cpp
///
- class JobUicT : public JobT
+ class JobMocsCompilationT : public JobFenceT
{
- public:
- JobUicT(std::string sourceFile, std::string includerFile,
- std::string includeString)
- : SourceFile(std::move(sourceFile))
- , IncluderFile(std::move(includerFile))
- , IncludeString(std::move(includeString))
- {
- }
-
private:
void Process() override;
- bool UpdateRequired();
- void GenerateUic();
-
- public:
- std::string SourceFile;
- std::string IncluderFile;
- std::string IncludeString;
- std::string BuildFile;
};
/// @brief The last job
@@ -346,39 +518,37 @@ public:
};
// -- Const settings interface
- const BaseSettingsT& Base() const { return this->Base_; }
- const MocSettingsT& Moc() const { return this->Moc_; }
- const UicSettingsT& Uic() const { return this->Uic_; }
+ BaseSettingsT const& BaseConst() const { return this->BaseConst_; }
+ BaseEvalT& BaseEval() { return this->BaseEval_; }
+ MocSettingsT const& MocConst() const { return this->MocConst_; }
+ MocEvalT& MocEval() { return this->MocEval_; }
+ UicSettingsT const& UicConst() const { return this->UicConst_; }
+ UicEvalT& UicEval() { return this->UicEval_; }
// -- Parallel job processing interface
cmWorkerPool& WorkerPool() { return WorkerPool_; }
void AbortError() { Abort(true); }
void AbortSuccess() { Abort(false); }
- bool ParallelJobPushMoc(cmWorkerPool::JobHandleT&& jobHandle);
- bool ParallelJobPushUic(cmWorkerPool::JobHandleT&& jobHandle);
- // -- Mocs compilation include file updated flag
- void ParallelMocAutoUpdated() { MocAutoFileUpdated_.store(true); }
- bool MocAutoFileUpdated() const { return MocAutoFileUpdated_.load(); }
-
- // -- Mocs compilation file register
- std::string ParallelMocAutoRegister(std::string const& baseName);
- bool ParallelMocIncluded(std::string const& sourceFile);
- std::set<std::string> const& MocAutoFiles() const
- {
- return this->MocAutoFiles_;
- }
+ // -- Utility
+ std::string AbsoluteBuildPath(std::string const& relativePath) const;
+ std::string AbsoluteIncludePath(std::string const& relativePath) const;
+ template <class JOBTYPE>
+ void CreateParseJobs(SourceFileMapT const& sourceMap);
private:
// -- Utility accessors
- Logger& Log() { return Logger_; }
- FileSystem& FileSys() { return FileSys_; }
+ Logger const& Log() const { return Logger_; }
// -- Abstract processing interface
bool Init(cmMakefile* makefile) override;
+ void InitJobs();
bool Process() override;
// -- Settings file
void SettingsFileRead();
bool SettingsFileWrite();
+ // -- Parse cache
+ void ParseCacheRead();
+ bool ParseCacheWrite();
// -- Thread processing
void Abort(bool error);
// -- Generation
@@ -387,25 +557,18 @@ private:
private:
// -- Utility
Logger Logger_;
- FileSystem FileSys_;
// -- Settings
- BaseSettingsT Base_;
- MocSettingsT Moc_;
- UicSettingsT Uic_;
- // -- Moc meta
- std::mutex MocMetaMutex_;
- std::set<std::string> MocIncludedFiles_;
- IncludesMap MocIncludes_;
- std::set<std::string> MocAutoFiles_;
- std::atomic<bool> MocAutoFileUpdated_ = ATOMIC_VAR_INIT(false);
- // -- Uic meta
- std::mutex UicMetaMutex_;
- IncludesMap UicIncludes_;
+ BaseSettingsT BaseConst_;
+ BaseEvalT BaseEval_;
+ MocSettingsT MocConst_;
+ MocEvalT MocEval_;
+ UicSettingsT UicConst_;
+ UicEvalT UicEval_;
// -- Settings file
std::string SettingsFile_;
std::string SettingsStringMoc_;
std::string SettingsStringUic_;
- // -- Thread pool and job queue
+ // -- Worker thread pool
std::atomic<bool> JobError_ = ATOMIC_VAR_INIT(false);
cmWorkerPool WorkerPool_;
};