| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| file Copyright.txt or https://cmake.org/licensing for details. */ |
| #ifndef cmQtAutoGeneratorMocUic_h |
| #define cmQtAutoGeneratorMocUic_h |
| |
| #include "cmConfigure.h" // IWYU pragma: keep |
| |
| #include "cmQtAutoGen.h" |
| #include "cmQtAutoGenerator.h" |
| #include "cmUVHandlePtr.h" |
| #include "cm_uv.h" |
| #include "cmsys/RegularExpression.hxx" |
| |
| #include <algorithm> |
| #include <condition_variable> |
| #include <cstddef> |
| #include <deque> |
| #include <map> |
| #include <memory> // IWYU pragma: keep |
| #include <mutex> |
| #include <set> |
| #include <string> |
| #include <thread> |
| #include <vector> |
| |
| class cmMakefile; |
| |
| // @brief AUTOMOC and AUTOUIC generator |
| class cmQtAutoGeneratorMocUic : public cmQtAutoGenerator |
| { |
| CM_DISABLE_COPY(cmQtAutoGeneratorMocUic) |
| public: |
| cmQtAutoGeneratorMocUic(); |
| ~cmQtAutoGeneratorMocUic() override; |
| |
| public: |
| // -- Types |
| class WorkerT; |
| |
| /// @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 const& key, std::string const& exp) |
| : Key(key) |
| , Exp(exp) |
| { |
| } |
| |
| std::string Key; |
| cmsys::RegularExpression Exp; |
| }; |
| |
| /// @brief Common settings |
| /// |
| class BaseSettingsT |
| { |
| CM_DISABLE_COPY(BaseSettingsT) |
| public: |
| // -- Volatile methods |
| BaseSettingsT(FileSystem* fileSystem) |
| : MultiConfig(false) |
| , IncludeProjectDirsBefore(false) |
| , QtVersionMajor(4) |
| , NumThreads(1) |
| , FileSys(fileSystem) |
| { |
| } |
| |
| // -- 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<std::string> HeaderExtensions; |
| // - File system |
| FileSystem* FileSys; |
| }; |
| |
| /// @brief Moc settings |
| /// |
| class MocSettingsT |
| { |
| CM_DISABLE_COPY(MocSettingsT) |
| public: |
| MocSettingsT(FileSystem* fileSys) |
| : FileSys(fileSys) |
| { |
| } |
| |
| // -- 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; |
| std::string Executable; |
| std::string CompFileAbs; |
| std::string PredefsFileRel; |
| std::string PredefsFileAbs; |
| std::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; |
| // - File system |
| FileSystem* FileSys; |
| }; |
| |
| /// @brief Uic settings |
| /// |
| class UicSettingsT |
| { |
| CM_DISABLE_COPY(UicSettingsT) |
| public: |
| UicSettingsT() = default; |
| // -- Const methods |
| bool skipped(std::string const& fileName) const; |
| |
| // -- Attributes |
| bool Enabled = false; |
| bool SettingsChanged = false; |
| std::string Executable; |
| std::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; |
| }; |
| |
| /// @brief Abstract job class for threaded processing |
| /// |
| class JobT |
| { |
| CM_DISABLE_COPY(JobT) |
| public: |
| JobT() = default; |
| virtual ~JobT() = default; |
| // -- Abstract processing interface |
| virtual void Process(WorkerT& wrk) = 0; |
| }; |
| |
| /// @brief Deleter for classes derived from Job |
| /// |
| struct JobDeleterT |
| { |
| void operator()(JobT* job); |
| }; |
| |
| // Job management types |
| typedef std::unique_ptr<JobT, JobDeleterT> JobHandleT; |
| typedef std::deque<JobHandleT> JobQueueT; |
| |
| /// @brief Parse source job |
| /// |
| 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(WorkerT& wrk) override; |
| bool ParseMocSource(WorkerT& wrk, MetaT const& meta); |
| bool ParseMocHeader(WorkerT& wrk, MetaT const& meta); |
| std::string MocStringHeaders(WorkerT& wrk, |
| std::string const& fileBase) const; |
| std::string MocFindIncludedHeader(WorkerT& wrk, |
| std::string const& includerDir, |
| std::string const& includeBase); |
| bool ParseUic(WorkerT& wrk, MetaT const& meta); |
| bool ParseUicInclude(WorkerT& wrk, MetaT const& meta, |
| std::string&& includeString); |
| std::string UicFindIncludedFile(WorkerT& wrk, MetaT const& meta, |
| std::string const& includeString); |
| |
| private: |
| std::string FileName; |
| bool AutoMoc = false; |
| bool AutoUic = false; |
| bool Header = false; |
| }; |
| |
| /// @brief Generate moc_predefs |
| /// |
| class JobMocPredefsT : public JobT |
| { |
| private: |
| void Process(WorkerT& wrk) override; |
| }; |
| |
| /// @brief Moc a file job |
| /// |
| class JobMocT : public JobT |
| { |
| public: |
| JobMocT(std::string&& sourceFile, std::string const& includerFile, |
| std::string&& includeString) |
| : SourceFile(std::move(sourceFile)) |
| , IncluderFile(includerFile) |
| , IncludeString(std::move(includeString)) |
| { |
| } |
| |
| void FindDependencies(WorkerT& wrk, std::string const& content); |
| |
| private: |
| void Process(WorkerT& wrk) override; |
| bool UpdateRequired(WorkerT& wrk); |
| void GenerateMoc(WorkerT& wrk); |
| |
| public: |
| std::string SourceFile; |
| std::string IncluderFile; |
| std::string IncludeString; |
| std::string BuildFile; |
| bool DependsValid = false; |
| std::set<std::string> Depends; |
| }; |
| |
| /// @brief Uic a file job |
| /// |
| class JobUicT : public JobT |
| { |
| public: |
| JobUicT(std::string&& sourceFile, std::string const& includerFile, |
| std::string&& includeString) |
| : SourceFile(std::move(sourceFile)) |
| , IncluderFile(includerFile) |
| , IncludeString(std::move(includeString)) |
| { |
| } |
| |
| private: |
| void Process(WorkerT& wrk) override; |
| bool UpdateRequired(WorkerT& wrk); |
| void GenerateUic(WorkerT& wrk); |
| |
| public: |
| std::string SourceFile; |
| std::string IncluderFile; |
| std::string IncludeString; |
| std::string BuildFile; |
| }; |
| |
| /// @brief Worker Thread |
| /// |
| class WorkerT |
| { |
| CM_DISABLE_COPY(WorkerT) |
| public: |
| WorkerT(cmQtAutoGeneratorMocUic* gen, uv_loop_t* uvLoop); |
| ~WorkerT(); |
| |
| // -- Const accessors |
| cmQtAutoGeneratorMocUic& Gen() const { return *Gen_; } |
| Logger& Log() const { return Gen_->Log(); } |
| FileSystem& FileSys() const { return Gen_->FileSys(); } |
| const BaseSettingsT& Base() const { return Gen_->Base(); } |
| const MocSettingsT& Moc() const { return Gen_->Moc(); } |
| const UicSettingsT& Uic() const { return Gen_->Uic(); } |
| |
| // -- Log info |
| void LogInfo(GeneratorT genType, std::string const& message) const; |
| // -- Log warning |
| void LogWarning(GeneratorT genType, std::string const& message) const; |
| void LogFileWarning(GeneratorT genType, std::string const& filename, |
| std::string const& message) const; |
| // -- Log error |
| void LogError(GeneratorT genType, std::string const& message) const; |
| void LogFileError(GeneratorT genType, std::string const& filename, |
| std::string const& message) const; |
| void LogCommandError(GeneratorT genType, std::string const& message, |
| std::vector<std::string> const& command, |
| std::string const& output) const; |
| |
| // -- External processes |
| /// @brief Verbose logging version |
| bool RunProcess(GeneratorT genType, ProcessResultT& result, |
| std::vector<std::string> const& command); |
| |
| private: |
| /// @brief Thread main loop |
| void Loop(); |
| |
| // -- Libuv callbacks |
| static void UVProcessStart(uv_async_t* handle); |
| void UVProcessFinished(); |
| |
| private: |
| // -- Generator |
| cmQtAutoGeneratorMocUic* Gen_; |
| // -- Job handle |
| JobHandleT JobHandle_; |
| // -- Process management |
| std::mutex ProcessMutex_; |
| cm::uv_async_ptr ProcessRequest_; |
| std::condition_variable ProcessCondition_; |
| std::unique_ptr<ReadOnlyProcessT> Process_; |
| // -- System thread |
| std::thread Thread_; |
| }; |
| |
| /// @brief Processing stage |
| enum class StageT |
| { |
| SETTINGS_READ, |
| CREATE_DIRECTORIES, |
| PARSE_SOURCES, |
| PARSE_HEADERS, |
| MOC_PREDEFS, |
| MOC_PROCESS, |
| MOCS_COMPILATION, |
| UIC_PROCESS, |
| SETTINGS_WRITE, |
| FINISH, |
| END |
| }; |
| |
| // -- Const settings interface |
| const BaseSettingsT& Base() const { return this->Base_; } |
| const MocSettingsT& Moc() const { return this->Moc_; } |
| const UicSettingsT& Uic() const { return this->Uic_; } |
| |
| // -- Worker thread interface |
| void WorkerSwapJob(JobHandleT& jobHandle); |
| // -- Parallel job processing interface |
| void ParallelRegisterJobError(); |
| bool ParallelJobPushMoc(JobHandleT& jobHandle); |
| bool ParallelJobPushUic(JobHandleT& jobHandle); |
| bool ParallelMocIncluded(std::string const& sourceFile); |
| void ParallelMocAutoRegister(std::string const& mocFile); |
| void ParallelMocAutoUpdated(); |
| |
| private: |
| // -- Abstract processing interface |
| bool Init(cmMakefile* makefile) override; |
| bool Process() override; |
| // -- Process stage |
| static void UVPollStage(uv_async_t* handle); |
| void PollStage(); |
| void SetStage(StageT stage); |
| // -- Settings file |
| void SettingsFileRead(); |
| void SettingsFileWrite(); |
| // -- Thread processing |
| bool ThreadsStartJobs(JobQueueT& queue); |
| bool ThreadsJobsDone(); |
| void ThreadsStop(); |
| void RegisterJobError(); |
| // -- Generation |
| void CreateDirectories(); |
| void MocGenerateCompilation(); |
| |
| private: |
| // -- Settings |
| BaseSettingsT Base_; |
| MocSettingsT Moc_; |
| UicSettingsT Uic_; |
| // -- Progress |
| StageT Stage_; |
| // -- Job queues |
| std::mutex JobsMutex_; |
| struct |
| { |
| JobQueueT Sources; |
| JobQueueT Headers; |
| JobQueueT MocPredefs; |
| JobQueueT Moc; |
| JobQueueT Uic; |
| } JobQueues_; |
| JobQueueT JobQueue_; |
| std::size_t volatile JobsRemain_; |
| bool volatile JobError_; |
| bool volatile JobThreadsAbort_; |
| std::condition_variable JobsConditionRead_; |
| // -- Moc meta |
| std::set<std::string> MocIncludedStrings_; |
| std::set<std::string> MocIncludedFiles_; |
| std::set<std::string> MocAutoFiles_; |
| bool volatile MocAutoFileUpdated_; |
| // -- Settings file |
| std::string SettingsFile_; |
| std::string SettingsStringMoc_; |
| std::string SettingsStringUic_; |
| // -- Threads and loops |
| std::vector<std::unique_ptr<WorkerT>> Workers_; |
| }; |
| |
| #endif |