cmQtAutoGeneratorMocUic.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #ifndef cmQtAutoGeneratorMocUic_h
  4. #define cmQtAutoGeneratorMocUic_h
  5. #include "cmConfigure.h" // IWYU pragma: keep
  6. #include "cmFilePathChecksum.h"
  7. #include "cmQtAutoGen.h"
  8. #include "cmQtAutoGenerator.h"
  9. #include "cmUVHandlePtr.h"
  10. #include "cm_uv.h"
  11. #include "cmsys/RegularExpression.hxx"
  12. #include <algorithm>
  13. #include <condition_variable>
  14. #include <cstddef>
  15. #include <deque>
  16. #include <map>
  17. #include <memory> // IWYU pragma: keep
  18. #include <mutex>
  19. #include <set>
  20. #include <string>
  21. #include <thread>
  22. #include <vector>
  23. class cmMakefile;
  24. // @brief AUTOMOC and AUTOUIC generator
  25. class cmQtAutoGeneratorMocUic : public cmQtAutoGenerator
  26. {
  27. CM_DISABLE_COPY(cmQtAutoGeneratorMocUic)
  28. public:
  29. cmQtAutoGeneratorMocUic();
  30. ~cmQtAutoGeneratorMocUic() override;
  31. public:
  32. // -- Types
  33. class WorkerT;
  34. /// @brief Search key plus regular expression pair
  35. ///
  36. struct KeyExpT
  37. {
  38. KeyExpT() = default;
  39. KeyExpT(const char* key, const char* exp)
  40. : Key(key)
  41. , Exp(exp)
  42. {
  43. }
  44. KeyExpT(std::string const& key, std::string const& exp)
  45. : Key(key)
  46. , Exp(exp)
  47. {
  48. }
  49. std::string Key;
  50. cmsys::RegularExpression Exp;
  51. };
  52. /// @brief Common settings
  53. ///
  54. class BaseSettingsT
  55. {
  56. CM_DISABLE_COPY(BaseSettingsT)
  57. public:
  58. // -- Volatile methods
  59. BaseSettingsT(FileSystem* fileSystem)
  60. : MultiConfig(false)
  61. , IncludeProjectDirsBefore(false)
  62. , QtVersionMajor(4)
  63. , NumThreads(1)
  64. , FileSys(fileSystem)
  65. {
  66. }
  67. // -- Const methods
  68. std::string AbsoluteBuildPath(std::string const& relativePath) const;
  69. bool FindHeader(std::string& header,
  70. std::string const& testBasePath) const;
  71. // -- Attributes
  72. // - Config
  73. bool MultiConfig;
  74. bool IncludeProjectDirsBefore;
  75. unsigned int QtVersionMajor;
  76. unsigned int NumThreads;
  77. // - Directories
  78. std::string ProjectSourceDir;
  79. std::string ProjectBinaryDir;
  80. std::string CurrentSourceDir;
  81. std::string CurrentBinaryDir;
  82. std::string AutogenBuildDir;
  83. std::string AutogenIncludeDir;
  84. // - Files
  85. cmFilePathChecksum FilePathChecksum;
  86. std::vector<std::string> HeaderExtensions;
  87. // - File system
  88. FileSystem* FileSys;
  89. };
  90. /// @brief Moc settings
  91. ///
  92. class MocSettingsT
  93. {
  94. CM_DISABLE_COPY(MocSettingsT)
  95. public:
  96. MocSettingsT(FileSystem* fileSys)
  97. : FileSys(fileSys)
  98. {
  99. }
  100. // -- Const methods
  101. bool skipped(std::string const& fileName) const;
  102. std::string FindMacro(std::string const& content) const;
  103. std::string MacrosString() const;
  104. std::string FindIncludedFile(std::string const& sourcePath,
  105. std::string const& includeString) const;
  106. void FindDependencies(std::string const& content,
  107. std::set<std::string>& depends) const;
  108. // -- Attributes
  109. bool Enabled = false;
  110. bool SettingsChanged = false;
  111. bool RelaxedMode = false;
  112. std::string Executable;
  113. std::string CompFileAbs;
  114. std::string PredefsFileRel;
  115. std::string PredefsFileAbs;
  116. std::set<std::string> SkipList;
  117. std::vector<std::string> IncludePaths;
  118. std::vector<std::string> Includes;
  119. std::vector<std::string> Definitions;
  120. std::vector<std::string> Options;
  121. std::vector<std::string> AllOptions;
  122. std::vector<std::string> PredefsCmd;
  123. std::vector<KeyExpT> DependFilters;
  124. std::vector<KeyExpT> MacroFilters;
  125. cmsys::RegularExpression RegExpInclude;
  126. // - File system
  127. FileSystem* FileSys;
  128. };
  129. /// @brief Uic settings
  130. ///
  131. class UicSettingsT
  132. {
  133. CM_DISABLE_COPY(UicSettingsT)
  134. public:
  135. UicSettingsT() = default;
  136. // -- Const methods
  137. bool skipped(std::string const& fileName) const;
  138. // -- Attributes
  139. bool Enabled = false;
  140. bool SettingsChanged = false;
  141. std::string Executable;
  142. std::set<std::string> SkipList;
  143. std::vector<std::string> TargetOptions;
  144. std::map<std::string, std::vector<std::string>> Options;
  145. std::vector<std::string> SearchPaths;
  146. cmsys::RegularExpression RegExpInclude;
  147. };
  148. /// @brief Abstract job class for threaded processing
  149. ///
  150. class JobT
  151. {
  152. CM_DISABLE_COPY(JobT)
  153. public:
  154. JobT() = default;
  155. virtual ~JobT() = default;
  156. // -- Abstract processing interface
  157. virtual void Process(WorkerT& wrk) = 0;
  158. };
  159. /// @brief Deleter for classes derived from Job
  160. ///
  161. struct JobDeleterT
  162. {
  163. void operator()(JobT* job);
  164. };
  165. // Job management types
  166. typedef std::unique_ptr<JobT, JobDeleterT> JobHandleT;
  167. typedef std::deque<JobHandleT> JobQueueT;
  168. /// @brief Parse source job
  169. ///
  170. class JobParseT : public JobT
  171. {
  172. public:
  173. JobParseT(std::string&& fileName, bool moc, bool uic, bool header = false)
  174. : FileName(std::move(fileName))
  175. , AutoMoc(moc)
  176. , AutoUic(uic)
  177. , Header(header)
  178. {
  179. }
  180. private:
  181. struct MetaT
  182. {
  183. std::string Content;
  184. std::string FileDir;
  185. std::string FileBase;
  186. };
  187. void Process(WorkerT& wrk) override;
  188. bool ParseMocSource(WorkerT& wrk, MetaT const& meta);
  189. bool ParseMocHeader(WorkerT& wrk, MetaT const& meta);
  190. std::string MocStringHeaders(WorkerT& wrk,
  191. std::string const& fileBase) const;
  192. std::string MocFindIncludedHeader(WorkerT& wrk,
  193. std::string const& includerDir,
  194. std::string const& includeBase);
  195. bool ParseUic(WorkerT& wrk, MetaT const& meta);
  196. bool ParseUicInclude(WorkerT& wrk, MetaT const& meta,
  197. std::string&& includeString);
  198. std::string UicFindIncludedFile(WorkerT& wrk, MetaT const& meta,
  199. std::string const& includeString);
  200. private:
  201. std::string FileName;
  202. bool AutoMoc = false;
  203. bool AutoUic = false;
  204. bool Header = false;
  205. };
  206. /// @brief Generate moc_predefs
  207. ///
  208. class JobMocPredefsT : public JobT
  209. {
  210. private:
  211. void Process(WorkerT& wrk) override;
  212. };
  213. /// @brief Moc a file job
  214. ///
  215. class JobMocT : public JobT
  216. {
  217. public:
  218. JobMocT(std::string&& sourceFile, std::string const& includerFile,
  219. std::string&& includeString)
  220. : SourceFile(std::move(sourceFile))
  221. , IncluderFile(includerFile)
  222. , IncludeString(std::move(includeString))
  223. {
  224. }
  225. void FindDependencies(WorkerT& wrk, std::string const& content);
  226. private:
  227. void Process(WorkerT& wrk) override;
  228. bool UpdateRequired(WorkerT& wrk);
  229. void GenerateMoc(WorkerT& wrk);
  230. public:
  231. std::string SourceFile;
  232. std::string IncluderFile;
  233. std::string IncludeString;
  234. std::string BuildFile;
  235. bool DependsValid = false;
  236. std::set<std::string> Depends;
  237. };
  238. /// @brief Uic a file job
  239. ///
  240. class JobUicT : public JobT
  241. {
  242. public:
  243. JobUicT(std::string&& sourceFile, std::string const& includerFile,
  244. std::string&& includeString)
  245. : SourceFile(std::move(sourceFile))
  246. , IncluderFile(includerFile)
  247. , IncludeString(std::move(includeString))
  248. {
  249. }
  250. private:
  251. void Process(WorkerT& wrk) override;
  252. bool UpdateRequired(WorkerT& wrk);
  253. void GenerateUic(WorkerT& wrk);
  254. public:
  255. std::string SourceFile;
  256. std::string IncluderFile;
  257. std::string IncludeString;
  258. std::string BuildFile;
  259. };
  260. /// @brief Worker Thread
  261. ///
  262. class WorkerT
  263. {
  264. CM_DISABLE_COPY(WorkerT)
  265. public:
  266. WorkerT(cmQtAutoGeneratorMocUic* gen, uv_loop_t* uvLoop);
  267. ~WorkerT();
  268. // -- Const accessors
  269. cmQtAutoGeneratorMocUic& Gen() const { return *Gen_; }
  270. Logger& Log() const { return Gen_->Log(); }
  271. FileSystem& FileSys() const { return Gen_->FileSys(); }
  272. const BaseSettingsT& Base() const { return Gen_->Base(); }
  273. const MocSettingsT& Moc() const { return Gen_->Moc(); }
  274. const UicSettingsT& Uic() const { return Gen_->Uic(); }
  275. // -- Log info
  276. void LogInfo(GeneratorT genType, std::string const& message) const;
  277. // -- Log warning
  278. void LogWarning(GeneratorT genType, std::string const& message) const;
  279. void LogFileWarning(GeneratorT genType, std::string const& filename,
  280. std::string const& message) const;
  281. // -- Log error
  282. void LogError(GeneratorT genType, std::string const& message) const;
  283. void LogFileError(GeneratorT genType, std::string const& filename,
  284. std::string const& message) const;
  285. void LogCommandError(GeneratorT genType, std::string const& message,
  286. std::vector<std::string> const& command,
  287. std::string const& output) const;
  288. // -- External processes
  289. /// @brief Verbose logging version
  290. bool RunProcess(GeneratorT genType, ProcessResultT& result,
  291. std::vector<std::string> const& command);
  292. private:
  293. /// @brief Thread main loop
  294. void Loop();
  295. // -- Libuv callbacks
  296. static void UVProcessStart(uv_async_t* handle);
  297. void UVProcessFinished();
  298. private:
  299. // -- Generator
  300. cmQtAutoGeneratorMocUic* Gen_;
  301. // -- Job handle
  302. JobHandleT JobHandle_;
  303. // -- Process management
  304. std::mutex ProcessMutex_;
  305. cm::uv_async_ptr ProcessRequest_;
  306. std::condition_variable ProcessCondition_;
  307. std::unique_ptr<ReadOnlyProcessT> Process_;
  308. // -- System thread
  309. std::thread Thread_;
  310. };
  311. /// @brief Processing stage
  312. enum class StageT
  313. {
  314. SETTINGS_READ,
  315. CREATE_DIRECTORIES,
  316. PARSE_SOURCES,
  317. PARSE_HEADERS,
  318. MOC_PREDEFS,
  319. MOC_PROCESS,
  320. MOCS_COMPILATION,
  321. UIC_PROCESS,
  322. SETTINGS_WRITE,
  323. FINISH,
  324. END
  325. };
  326. // -- Const settings interface
  327. const BaseSettingsT& Base() const { return this->Base_; }
  328. const MocSettingsT& Moc() const { return this->Moc_; }
  329. const UicSettingsT& Uic() const { return this->Uic_; }
  330. // -- Worker thread interface
  331. void WorkerSwapJob(JobHandleT& jobHandle);
  332. // -- Parallel job processing interface
  333. void ParallelRegisterJobError();
  334. bool ParallelJobPushMoc(JobHandleT& jobHandle);
  335. bool ParallelJobPushUic(JobHandleT& jobHandle);
  336. bool ParallelMocIncluded(std::string const& sourceFile);
  337. void ParallelMocAutoRegister(std::string const& mocFile);
  338. void ParallelMocAutoUpdated();
  339. private:
  340. // -- Abstract processing interface
  341. bool Init(cmMakefile* makefile) override;
  342. bool Process() override;
  343. // -- Process stage
  344. static void UVPollStage(uv_async_t* handle);
  345. void PollStage();
  346. void SetStage(StageT stage);
  347. // -- Settings file
  348. void SettingsFileRead();
  349. void SettingsFileWrite();
  350. // -- Thread processing
  351. bool ThreadsStartJobs(JobQueueT& queue);
  352. bool ThreadsJobsDone();
  353. void ThreadsStop();
  354. void RegisterJobError();
  355. // -- Generation
  356. void CreateDirectories();
  357. void MocGenerateCompilation();
  358. private:
  359. // -- Settings
  360. BaseSettingsT Base_;
  361. MocSettingsT Moc_;
  362. UicSettingsT Uic_;
  363. // -- Progress
  364. StageT Stage_;
  365. // -- Job queues
  366. std::mutex JobsMutex_;
  367. struct
  368. {
  369. JobQueueT Sources;
  370. JobQueueT Headers;
  371. JobQueueT MocPredefs;
  372. JobQueueT Moc;
  373. JobQueueT Uic;
  374. } JobQueues_;
  375. JobQueueT JobQueue_;
  376. std::size_t volatile JobsRemain_;
  377. bool volatile JobError_;
  378. bool volatile JobThreadsAbort_;
  379. std::condition_variable JobsConditionRead_;
  380. // -- Moc meta
  381. std::set<std::string> MocIncludedStrings_;
  382. std::set<std::string> MocIncludedFiles_;
  383. std::set<std::string> MocAutoFiles_;
  384. bool volatile MocAutoFileUpdated_;
  385. // -- Settings file
  386. std::string SettingsFile_;
  387. std::string SettingsStringMoc_;
  388. std::string SettingsStringUic_;
  389. // -- Threads and loops
  390. std::vector<std::unique_ptr<WorkerT>> Workers_;
  391. };
  392. #endif