cmQtAutoGeneratorMocUic.h 11 KB

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