diff options
Diffstat (limited to 'Source/cmQtAutoMocUic.h')
-rw-r--r-- | Source/cmQtAutoMocUic.h | 576 |
1 files changed, 576 insertions, 0 deletions
diff --git a/Source/cmQtAutoMocUic.h b/Source/cmQtAutoMocUic.h new file mode 100644 index 000000000..81546cc18 --- /dev/null +++ b/Source/cmQtAutoMocUic.h @@ -0,0 +1,576 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmQtAutoMocUic_h +#define cmQtAutoMocUic_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cmFileTime.h" +#include "cmQtAutoGen.h" +#include "cmQtAutoGenerator.h" +#include "cmWorkerPool.h" +#include "cmsys/RegularExpression.hxx" + +#include <atomic> +#include <cstddef> +#include <map> +#include <memory> // IWYU pragma: keep +#include <set> +#include <string> +#include <unordered_map> +#include <unordered_set> +#include <utility> +#include <vector> + +class cmMakefile; + +/** \class cmQtAutoMocUic + * \brief AUTOMOC and AUTOUIC generator + */ +class cmQtAutoMocUic : public cmQtAutoGenerator +{ +public: + cmQtAutoMocUic(); + ~cmQtAutoMocUic() override; + + cmQtAutoMocUic(cmQtAutoMocUic const&) = delete; + cmQtAutoMocUic& operator=(cmQtAutoMocUic const&) = delete; + +public: + // -- Types + + /** + * Search key plus regular expression pair + */ + struct KeyExpT + { + KeyExpT() = default; + + KeyExpT(const char* key, const char* exp) + : Key(key) + , Exp(exp) + { + } + + KeyExpT(std::string key, std::string const& exp) + : Key(std::move(key)) + , Exp(exp) + { + } + + std::string Key; + cmsys::RegularExpression Exp; + }; + + /** + * 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: + 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; + + // -- Attributes + // - Config + bool MultiConfig = false; + bool IncludeProjectDirsBefore = false; + unsigned int QtVersionMajor = 4; + // - Directories + std::string ProjectSourceDir; + std::string ProjectBinaryDir; + std::string CurrentSourceDir; + std::string CurrentBinaryDir; + std::string AutogenBuildDir; + std::string AutogenIncludeDir; + // - Files + std::string CMakeExecutable; + cmFileTime CMakeExecutableTime; + std::string ParseCacheFile; + std::vector<std::string> HeaderExtensions; + }; + + /** + * 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: + // -- Constructors + MocSettingsT(); + ~MocSettingsT(); + + MocSettingsT(MocSettingsT const&) = delete; + MocSettingsT& operator=(MocSettingsT const&) = delete; + + // -- Const methods + bool skipped(std::string const& fileName) const; + std::string MacrosString() const; + + // -- Attributes + bool Enabled = false; + bool SettingsChanged = false; + bool RelaxedMode = false; + cmFileTime ExecutableTime; + std::string Executable; + std::string CompFileAbs; + std::string PredefsFileRel; + std::string PredefsFileAbs; + std::unordered_set<std::string> SkipList; + std::vector<std::string> IncludePaths; + std::vector<std::string> Includes; + std::vector<std::string> Definitions; + std::vector<std::string> Options; + std::vector<std::string> AllOptions; + std::vector<std::string> PredefsCmd; + std::vector<KeyExpT> DependFilters; + std::vector<KeyExpT> MacroFilters; + cmsys::RegularExpression RegExpInclude; + }; + + /** + * 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(); + ~UicSettingsT(); + + UicSettingsT(UicSettingsT const&) = delete; + UicSettingsT& operator=(UicSettingsT const&) = delete; + + // -- Const methods + bool skipped(std::string const& fileName) const; + + // -- Attributes + bool Enabled = false; + bool SettingsChanged = false; + cmFileTime ExecutableTime; + std::string Executable; + std::unordered_set<std::string> SkipList; + std::vector<std::string> TargetOptions; + std::map<std::string, std::vector<std::string>> Options; + std::vector<std::string> SearchPaths; + cmsys::RegularExpression RegExpInclude; + }; + + /** + * Uic shared variables + */ + class UicEvalT + { + public: + SourceFileMapT UiFiles; + MappingMapT Includes; + }; + + /** + * Abstract job class for concurrent job processing + */ + class JobT : public cmWorkerPool::JobT + { + protected: + /** + * @brief Protected default constructor + */ + JobT(bool fence = false) + : cmWorkerPool::JobT(fence) + { + } + + //! Get the generator. Only valid during Process() call! + cmQtAutoMocUic* Gen() const + { + return static_cast<cmQtAutoMocUic*>(UserData()); + }; + + // -- 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; + void LogFileError(GenT genType, std::string const& filename, + std::string const& message) const; + void LogCommandError(GenT genType, std::string const& message, + std::vector<std::string> const& command, + std::string const& output) const; + + /** + * @brief Run an external process. Use only during Process() call! + */ + bool RunProcess(GenT genType, cmWorkerPool::ProcessResultT& result, + std::vector<std::string> const& command, + std::string* infoMessage = nullptr); + }; + + /** + * Fence job utility class + */ + class JobFenceT : public JobT + { + public: + JobFenceT() + : JobT(true) + { + } + void Process() override{}; + }; + + /** + * Generate moc_predefs.h + */ + class JobMocPredefsT : public JobFenceT + { + void Process() override; + bool Update(std::string* reason) const; + }; + + /** + * File parse job base class + */ + class JobParseT : public JobT + { + public: + JobParseT(SourceFileHandleT fileHandle) + : FileHandle(std::move(fileHandle)) + { + } + + 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; + }; + + /** + * Source file parse job + */ + class JobParseSourceT : public JobParseT + { + public: + using JobParseT::JobParseT; + void Process() override; + }; + + /** + * Evaluate parsed files + */ + class JobEvaluateT : public JobFenceT + { + 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 const& 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); + }; + + /** + * Generates moc/uic jobs + */ + class JobGenerateT : public JobFenceT + { + 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; + }; + + /** + * File compiling base job + */ + class JobCompileT : public JobT + { + public: + JobCompileT(MappingHandleT uicMapping, std::unique_ptr<std::string> reason) + : Mapping(std::move(uicMapping)) + , Reason(std::move(reason)) + { + } + + protected: + MappingHandleT Mapping; + std::unique_ptr<std::string> Reason; + }; + + /** + * moc compiles a file + */ + class JobMocT : public JobCompileT + { + public: + using JobCompileT::JobCompileT; + void Process() override; + }; + + /** + * uic compiles a file + */ + class JobUicT : public JobCompileT + { + public: + using JobCompileT::JobCompileT; + void Process() override; + }; + + /// @brief Generate mocs_compilation.cpp + /// + class JobMocsCompilationT : public JobFenceT + { + private: + void Process() override; + }; + + /// @brief The last job + /// + class JobFinishT : public JobFenceT + { + private: + void Process() override; + }; + + // -- Const settings interface + 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); } + + // -- 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 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 + bool CreateDirectories(); + +private: + // -- Utility + Logger Logger_; + // -- Settings + BaseSettingsT BaseConst_; + BaseEvalT BaseEval_; + MocSettingsT MocConst_; + MocEvalT MocEval_; + UicSettingsT UicConst_; + UicEvalT UicEval_; + // -- Settings file + std::string SettingsFile_; + std::string SettingsStringMoc_; + std::string SettingsStringUic_; + // -- Worker thread pool + std::atomic<bool> JobError_ = ATOMIC_VAR_INIT(false); + cmWorkerPool WorkerPool_; +}; + +#endif |