/* 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 "cmQtAutoGen.h" #include "cmQtAutoGenerator.h" #include "cmWorkerPool.h" #include "cmsys/RegularExpression.hxx" #include #include #include #include // IWYU pragma: keep #include #include #include #include #include #include class cmMakefile; // @brief AUTOMOC and AUTOUIC generator class cmQtAutoMocUic : public cmQtAutoGenerator { public: cmQtAutoMocUic(); ~cmQtAutoMocUic() override; cmQtAutoMocUic(cmQtAutoMocUic const&) = delete; cmQtAutoMocUic& operator=(cmQtAutoMocUic const&) = delete; public: // -- Types typedef std::multimap> IncludesMap; /// @brief 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; }; /// @brief Common settings /// class BaseSettingsT { public: // -- Volatile methods BaseSettingsT(FileSystem* fileSystem) : MultiConfig(false) , IncludeProjectDirsBefore(false) , QtVersionMajor(4) , NumThreads(1) , FileSys(fileSystem) { } 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; // - Directories std::string ProjectSourceDir; std::string ProjectBinaryDir; std::string CurrentSourceDir; std::string CurrentBinaryDir; std::string AutogenBuildDir; std::string AutogenIncludeDir; // - Files std::vector HeaderExtensions; // - File system FileSystem* FileSys; }; /// @brief Moc settings /// class MocSettingsT { public: MocSettingsT(FileSystem* fileSys) : FileSys(fileSys) { } 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& depends) const; // -- Attributes bool Enabled = false; bool SettingsChanged = false; bool RelaxedMode = false; std::string Executable; std::string CompFileAbs; std::string PredefsFileRel; std::string PredefsFileAbs; std::unordered_set SkipList; std::vector IncludePaths; std::vector Includes; std::vector Definitions; std::vector Options; std::vector AllOptions; std::vector PredefsCmd; std::vector DependFilters; std::vector MacroFilters; cmsys::RegularExpression RegExpInclude; // - File system FileSystem* FileSys; }; /// @brief Uic settings /// class UicSettingsT { public: UicSettingsT() = default; 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; std::string Executable; std::unordered_set SkipList; std::vector TargetOptions; std::map> Options; std::vector SearchPaths; cmsys::RegularExpression RegExpInclude; }; /// @brief 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(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(); } // -- 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 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 const& command); }; /// @brief Fence job utility class /// class JobFenceT : public JobT { public: JobFenceT() : JobT(true) { } void Process() override{}; }; /// @brief Generate moc_predefs.h /// class JobMocPredefsT : public JobT { private: void Process() override; }; /// @brief Parses a source file /// 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) { } private: struct MetaT { std::string Content; std::string FileDir; std::string FileBase; }; 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; }; /// @brief Generates additional jobs after all files have been parsed /// class JobPostParseT : public JobFenceT { private: void Process() override; }; /// @brief Generate mocs_compilation.cpp /// class JobMocsCompilationT : public JobFenceT { private: void Process() override; }; /// @brief Moc a file job /// class JobMocT : 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)) { } void FindDependencies(std::string const& content); private: void Process() override; bool UpdateRequired(); void GenerateMoc(); public: std::string SourceFile; std::string IncluderFile; std::string IncludeString; std::string BuildFile; bool DependsValid = false; std::set Depends; }; /// @brief Uic a file job /// class JobUicT : public JobT { 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 /// class JobFinishT : public JobFenceT { private: void Process() override; }; // -- Const settings interface const BaseSettingsT& Base() const { return this->Base_; } const MocSettingsT& Moc() const { return this->Moc_; } const UicSettingsT& Uic() const { return this->Uic_; } // -- 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 const& MocAutoFiles() const { return this->MocAutoFiles_; } private: // -- Utility accessors Logger& Log() { return Logger_; } FileSystem& FileSys() { return FileSys_; } // -- Abstract processing interface bool Init(cmMakefile* makefile) override; bool Process() override; // -- Settings file void SettingsFileRead(); bool SettingsFileWrite(); // -- Thread processing void Abort(bool error); // -- Generation bool CreateDirectories(); private: // -- Utility Logger Logger_; FileSystem FileSys_; // -- Settings BaseSettingsT Base_; MocSettingsT Moc_; UicSettingsT Uic_; // -- Moc meta std::mutex MocMetaMutex_; std::set MocIncludedFiles_; IncludesMap MocIncludes_; std::set MocAutoFiles_; std::atomic MocAutoFileUpdated_ = ATOMIC_VAR_INIT(false); // -- Uic meta std::mutex UicMetaMutex_; IncludesMap UicIncludes_; // -- Settings file std::string SettingsFile_; std::string SettingsStringMoc_; std::string SettingsStringUic_; // -- Thread pool and job queue std::atomic JobError_ = ATOMIC_VAR_INIT(false); cmWorkerPool WorkerPool_; }; #endif