cmQtAutoGenerator.cxx 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmQtAutoGenerator.h"
  4. #include "cmQtAutoGen.h"
  5. #include "cmsys/FStream.hxx"
  6. #include "cmAlgorithms.h"
  7. #include "cmGlobalGenerator.h"
  8. #include "cmMakefile.h"
  9. #include "cmState.h"
  10. #include "cmStateDirectory.h"
  11. #include "cmStateSnapshot.h"
  12. #include "cmSystemTools.h"
  13. #include "cmake.h"
  14. #include <algorithm>
  15. #include <utility>
  16. // -- Class methods
  17. void cmQtAutoGenerator::Logger::RaiseVerbosity(std::string const& value)
  18. {
  19. unsigned long verbosity = 0;
  20. if (cmSystemTools::StringToULong(value.c_str(), &verbosity)) {
  21. if (this->Verbosity_ < verbosity) {
  22. this->Verbosity_ = static_cast<unsigned int>(verbosity);
  23. }
  24. }
  25. }
  26. void cmQtAutoGenerator::Logger::SetColorOutput(bool value)
  27. {
  28. ColorOutput_ = value;
  29. }
  30. std::string cmQtAutoGenerator::Logger::HeadLine(std::string const& title)
  31. {
  32. std::string head = title;
  33. head += '\n';
  34. head.append(head.size() - 1, '-');
  35. head += '\n';
  36. return head;
  37. }
  38. void cmQtAutoGenerator::Logger::Info(GenT genType, std::string const& message)
  39. {
  40. std::string msg = GeneratorName(genType);
  41. msg += ": ";
  42. msg += message;
  43. if (msg.back() != '\n') {
  44. msg.push_back('\n');
  45. }
  46. {
  47. std::lock_guard<std::mutex> lock(Mutex_);
  48. cmSystemTools::Stdout(msg);
  49. }
  50. }
  51. void cmQtAutoGenerator::Logger::Warning(GenT genType,
  52. std::string const& message)
  53. {
  54. std::string msg;
  55. if (message.find('\n') == std::string::npos) {
  56. // Single line message
  57. msg += GeneratorName(genType);
  58. msg += " warning: ";
  59. } else {
  60. // Multi line message
  61. msg += HeadLine(GeneratorName(genType) + " warning");
  62. }
  63. // Message
  64. msg += message;
  65. if (msg.back() != '\n') {
  66. msg.push_back('\n');
  67. }
  68. msg.push_back('\n');
  69. {
  70. std::lock_guard<std::mutex> lock(Mutex_);
  71. cmSystemTools::Stdout(msg);
  72. }
  73. }
  74. void cmQtAutoGenerator::Logger::WarningFile(GenT genType,
  75. std::string const& filename,
  76. std::string const& message)
  77. {
  78. std::string msg = " ";
  79. msg += Quoted(filename);
  80. msg.push_back('\n');
  81. // Message
  82. msg += message;
  83. Warning(genType, msg);
  84. }
  85. void cmQtAutoGenerator::Logger::Error(GenT genType, std::string const& message)
  86. {
  87. std::string msg;
  88. msg += HeadLine(GeneratorName(genType) + " error");
  89. // Message
  90. msg += message;
  91. if (msg.back() != '\n') {
  92. msg.push_back('\n');
  93. }
  94. msg.push_back('\n');
  95. {
  96. std::lock_guard<std::mutex> lock(Mutex_);
  97. cmSystemTools::Stderr(msg);
  98. }
  99. }
  100. void cmQtAutoGenerator::Logger::ErrorFile(GenT genType,
  101. std::string const& filename,
  102. std::string const& message)
  103. {
  104. std::string emsg = " ";
  105. emsg += Quoted(filename);
  106. emsg += '\n';
  107. // Message
  108. emsg += message;
  109. Error(genType, emsg);
  110. }
  111. void cmQtAutoGenerator::Logger::ErrorCommand(
  112. GenT genType, std::string const& message,
  113. std::vector<std::string> const& command, std::string const& output)
  114. {
  115. std::string msg;
  116. msg.push_back('\n');
  117. msg += HeadLine(GeneratorName(genType) + " subprocess error");
  118. msg += message;
  119. if (msg.back() != '\n') {
  120. msg.push_back('\n');
  121. }
  122. msg.push_back('\n');
  123. msg += HeadLine("Command");
  124. msg += QuotedCommand(command);
  125. if (msg.back() != '\n') {
  126. msg.push_back('\n');
  127. }
  128. msg.push_back('\n');
  129. msg += HeadLine("Output");
  130. msg += output;
  131. if (msg.back() != '\n') {
  132. msg.push_back('\n');
  133. }
  134. msg.push_back('\n');
  135. {
  136. std::lock_guard<std::mutex> lock(Mutex_);
  137. cmSystemTools::Stderr(msg);
  138. }
  139. }
  140. std::string cmQtAutoGenerator::FileSystem::GetRealPath(
  141. std::string const& filename)
  142. {
  143. std::lock_guard<std::mutex> lock(Mutex_);
  144. return cmSystemTools::GetRealPath(filename);
  145. }
  146. std::string cmQtAutoGenerator::FileSystem::CollapseFullPath(
  147. std::string const& file, std::string const& dir)
  148. {
  149. std::lock_guard<std::mutex> lock(Mutex_);
  150. return cmSystemTools::CollapseFullPath(file, dir);
  151. }
  152. void cmQtAutoGenerator::FileSystem::SplitPath(
  153. const std::string& p, std::vector<std::string>& components,
  154. bool expand_home_dir)
  155. {
  156. std::lock_guard<std::mutex> lock(Mutex_);
  157. cmSystemTools::SplitPath(p, components, expand_home_dir);
  158. }
  159. std::string cmQtAutoGenerator::FileSystem::JoinPath(
  160. const std::vector<std::string>& components)
  161. {
  162. std::lock_guard<std::mutex> lock(Mutex_);
  163. return cmSystemTools::JoinPath(components);
  164. }
  165. std::string cmQtAutoGenerator::FileSystem::JoinPath(
  166. std::vector<std::string>::const_iterator first,
  167. std::vector<std::string>::const_iterator last)
  168. {
  169. std::lock_guard<std::mutex> lock(Mutex_);
  170. return cmSystemTools::JoinPath(first, last);
  171. }
  172. std::string cmQtAutoGenerator::FileSystem::GetFilenameWithoutLastExtension(
  173. const std::string& filename)
  174. {
  175. std::lock_guard<std::mutex> lock(Mutex_);
  176. return cmSystemTools::GetFilenameWithoutLastExtension(filename);
  177. }
  178. std::string cmQtAutoGenerator::FileSystem::SubDirPrefix(
  179. std::string const& filename)
  180. {
  181. std::lock_guard<std::mutex> lock(Mutex_);
  182. return cmQtAutoGen::SubDirPrefix(filename);
  183. }
  184. void cmQtAutoGenerator::FileSystem::setupFilePathChecksum(
  185. std::string const& currentSrcDir, std::string const& currentBinDir,
  186. std::string const& projectSrcDir, std::string const& projectBinDir)
  187. {
  188. std::lock_guard<std::mutex> lock(Mutex_);
  189. FilePathChecksum_.setupParentDirs(currentSrcDir, currentBinDir,
  190. projectSrcDir, projectBinDir);
  191. }
  192. std::string cmQtAutoGenerator::FileSystem::GetFilePathChecksum(
  193. std::string const& filename)
  194. {
  195. std::lock_guard<std::mutex> lock(Mutex_);
  196. return FilePathChecksum_.getPart(filename);
  197. }
  198. bool cmQtAutoGenerator::FileSystem::FileExists(std::string const& filename)
  199. {
  200. std::lock_guard<std::mutex> lock(Mutex_);
  201. return cmSystemTools::FileExists(filename);
  202. }
  203. bool cmQtAutoGenerator::FileSystem::FileExists(std::string const& filename,
  204. bool isFile)
  205. {
  206. std::lock_guard<std::mutex> lock(Mutex_);
  207. return cmSystemTools::FileExists(filename, isFile);
  208. }
  209. unsigned long cmQtAutoGenerator::FileSystem::FileLength(
  210. std::string const& filename)
  211. {
  212. std::lock_guard<std::mutex> lock(Mutex_);
  213. return cmSystemTools::FileLength(filename);
  214. }
  215. bool cmQtAutoGenerator::FileSystem::FileIsOlderThan(
  216. std::string const& buildFile, std::string const& sourceFile,
  217. std::string* error)
  218. {
  219. bool res(false);
  220. int result = 0;
  221. {
  222. std::lock_guard<std::mutex> lock(Mutex_);
  223. res = cmSystemTools::FileTimeCompare(buildFile, sourceFile, &result);
  224. }
  225. if (res) {
  226. res = (result < 0);
  227. } else {
  228. if (error != nullptr) {
  229. error->append(
  230. "File modification time comparison failed for the files\n ");
  231. error->append(Quoted(buildFile));
  232. error->append("\nand\n ");
  233. error->append(Quoted(sourceFile));
  234. }
  235. }
  236. return res;
  237. }
  238. bool cmQtAutoGenerator::FileSystem::FileRead(std::string& content,
  239. std::string const& filename,
  240. std::string* error)
  241. {
  242. bool success = false;
  243. if (FileExists(filename, true)) {
  244. unsigned long const length = FileLength(filename);
  245. {
  246. std::lock_guard<std::mutex> lock(Mutex_);
  247. cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
  248. if (ifs) {
  249. content.reserve(length);
  250. content.assign(std::istreambuf_iterator<char>{ ifs },
  251. std::istreambuf_iterator<char>{});
  252. if (ifs) {
  253. success = true;
  254. } else {
  255. content.clear();
  256. if (error != nullptr) {
  257. error->append("Reading from the file failed.");
  258. }
  259. }
  260. } else if (error != nullptr) {
  261. error->append("Opening the file for reading failed.");
  262. }
  263. }
  264. } else if (error != nullptr) {
  265. error->append(
  266. "The file does not exist, is not readable or is a directory.");
  267. }
  268. return success;
  269. }
  270. bool cmQtAutoGenerator::FileSystem::FileRead(GenT genType,
  271. std::string& content,
  272. std::string const& filename)
  273. {
  274. std::string error;
  275. if (!FileRead(content, filename, &error)) {
  276. Log()->ErrorFile(genType, filename, error);
  277. return false;
  278. }
  279. return true;
  280. }
  281. bool cmQtAutoGenerator::FileSystem::FileWrite(std::string const& filename,
  282. std::string const& content,
  283. std::string* error)
  284. {
  285. bool success = false;
  286. // Make sure the parent directory exists
  287. if (MakeParentDirectory(filename)) {
  288. std::lock_guard<std::mutex> lock(Mutex_);
  289. cmsys::ofstream outfile;
  290. outfile.open(filename.c_str(),
  291. (std::ios::out | std::ios::binary | std::ios::trunc));
  292. if (outfile) {
  293. outfile << content;
  294. // Check for write errors
  295. if (outfile.good()) {
  296. success = true;
  297. } else {
  298. if (error != nullptr) {
  299. error->assign("File writing failed");
  300. }
  301. }
  302. } else {
  303. if (error != nullptr) {
  304. error->assign("Opening file for writing failed");
  305. }
  306. }
  307. } else {
  308. if (error != nullptr) {
  309. error->assign("Could not create parent directory");
  310. }
  311. }
  312. return success;
  313. }
  314. bool cmQtAutoGenerator::FileSystem::FileWrite(GenT genType,
  315. std::string const& filename,
  316. std::string const& content)
  317. {
  318. std::string error;
  319. if (!FileWrite(filename, content, &error)) {
  320. Log()->ErrorFile(genType, filename, error);
  321. return false;
  322. }
  323. return true;
  324. }
  325. bool cmQtAutoGenerator::FileSystem::FileDiffers(std::string const& filename,
  326. std::string const& content)
  327. {
  328. bool differs = true;
  329. {
  330. std::string oldContents;
  331. if (FileRead(oldContents, filename)) {
  332. differs = (oldContents != content);
  333. }
  334. }
  335. return differs;
  336. }
  337. bool cmQtAutoGenerator::FileSystem::FileRemove(std::string const& filename)
  338. {
  339. std::lock_guard<std::mutex> lock(Mutex_);
  340. return cmSystemTools::RemoveFile(filename);
  341. }
  342. bool cmQtAutoGenerator::FileSystem::Touch(std::string const& filename,
  343. bool create)
  344. {
  345. std::lock_guard<std::mutex> lock(Mutex_);
  346. return cmSystemTools::Touch(filename, create);
  347. }
  348. bool cmQtAutoGenerator::FileSystem::MakeDirectory(std::string const& dirname)
  349. {
  350. std::lock_guard<std::mutex> lock(Mutex_);
  351. return cmSystemTools::MakeDirectory(dirname);
  352. }
  353. bool cmQtAutoGenerator::FileSystem::MakeDirectory(GenT genType,
  354. std::string const& dirname)
  355. {
  356. if (!MakeDirectory(dirname)) {
  357. Log()->ErrorFile(genType, dirname, "Could not create directory");
  358. return false;
  359. }
  360. return true;
  361. }
  362. bool cmQtAutoGenerator::FileSystem::MakeParentDirectory(
  363. std::string const& filename)
  364. {
  365. bool success = true;
  366. std::string const dirName = cmSystemTools::GetFilenamePath(filename);
  367. if (!dirName.empty()) {
  368. success = MakeDirectory(dirName);
  369. }
  370. return success;
  371. }
  372. bool cmQtAutoGenerator::FileSystem::MakeParentDirectory(
  373. GenT genType, std::string const& filename)
  374. {
  375. if (!MakeParentDirectory(filename)) {
  376. Log()->ErrorFile(genType, filename, "Could not create parent directory");
  377. return false;
  378. }
  379. return true;
  380. }
  381. int cmQtAutoGenerator::ReadOnlyProcessT::PipeT::init(uv_loop_t* uv_loop,
  382. ReadOnlyProcessT* process)
  383. {
  384. Process_ = process;
  385. Target_ = nullptr;
  386. return UVPipe_.init(*uv_loop, 0, this);
  387. }
  388. int cmQtAutoGenerator::ReadOnlyProcessT::PipeT::startRead(std::string* target)
  389. {
  390. Target_ = target;
  391. return uv_read_start(uv_stream(), &PipeT::UVAlloc, &PipeT::UVData);
  392. }
  393. void cmQtAutoGenerator::ReadOnlyProcessT::PipeT::reset()
  394. {
  395. Process_ = nullptr;
  396. Target_ = nullptr;
  397. UVPipe_.reset();
  398. Buffer_.clear();
  399. Buffer_.shrink_to_fit();
  400. }
  401. void cmQtAutoGenerator::ReadOnlyProcessT::PipeT::UVAlloc(uv_handle_t* handle,
  402. size_t suggestedSize,
  403. uv_buf_t* buf)
  404. {
  405. auto& pipe = *reinterpret_cast<PipeT*>(handle->data);
  406. pipe.Buffer_.resize(suggestedSize);
  407. buf->base = pipe.Buffer_.data();
  408. buf->len = pipe.Buffer_.size();
  409. }
  410. void cmQtAutoGenerator::ReadOnlyProcessT::PipeT::UVData(uv_stream_t* stream,
  411. ssize_t nread,
  412. const uv_buf_t* buf)
  413. {
  414. auto& pipe = *reinterpret_cast<PipeT*>(stream->data);
  415. if (nread > 0) {
  416. // Append data to merged output
  417. if ((buf->base != nullptr) && (pipe.Target_ != nullptr)) {
  418. pipe.Target_->append(buf->base, nread);
  419. }
  420. } else if (nread < 0) {
  421. // EOF or error
  422. auto* proc = pipe.Process_;
  423. // Check it this an unusual error
  424. if (nread != UV_EOF) {
  425. if (!proc->Result()->error()) {
  426. proc->Result()->ErrorMessage =
  427. "libuv reading from pipe failed with error code ";
  428. proc->Result()->ErrorMessage += std::to_string(nread);
  429. }
  430. }
  431. // Clear libuv pipe handle and try to finish
  432. pipe.reset();
  433. proc->UVTryFinish();
  434. }
  435. }
  436. void cmQtAutoGenerator::ProcessResultT::reset()
  437. {
  438. ExitStatus = 0;
  439. TermSignal = 0;
  440. if (!StdOut.empty()) {
  441. StdOut.clear();
  442. StdOut.shrink_to_fit();
  443. }
  444. if (!StdErr.empty()) {
  445. StdErr.clear();
  446. StdErr.shrink_to_fit();
  447. }
  448. if (!ErrorMessage.empty()) {
  449. ErrorMessage.clear();
  450. ErrorMessage.shrink_to_fit();
  451. }
  452. }
  453. void cmQtAutoGenerator::ReadOnlyProcessT::setup(
  454. ProcessResultT* result, bool mergedOutput,
  455. std::vector<std::string> const& command, std::string const& workingDirectory)
  456. {
  457. Setup_.WorkingDirectory = workingDirectory;
  458. Setup_.Command = command;
  459. Setup_.Result = result;
  460. Setup_.MergedOutput = mergedOutput;
  461. }
  462. bool cmQtAutoGenerator::ReadOnlyProcessT::start(
  463. uv_loop_t* uv_loop, std::function<void()>&& finishedCallback)
  464. {
  465. if (IsStarted() || (Result() == nullptr)) {
  466. return false;
  467. }
  468. // Reset result before the start
  469. Result()->reset();
  470. // Fill command string pointers
  471. if (!Setup().Command.empty()) {
  472. CommandPtr_.reserve(Setup().Command.size() + 1);
  473. for (std::string const& arg : Setup().Command) {
  474. CommandPtr_.push_back(arg.c_str());
  475. }
  476. CommandPtr_.push_back(nullptr);
  477. } else {
  478. Result()->ErrorMessage = "Empty command";
  479. }
  480. if (!Result()->error()) {
  481. if (UVPipeOut_.init(uv_loop, this) != 0) {
  482. Result()->ErrorMessage = "libuv stdout pipe initialization failed";
  483. }
  484. }
  485. if (!Result()->error()) {
  486. if (UVPipeErr_.init(uv_loop, this) != 0) {
  487. Result()->ErrorMessage = "libuv stderr pipe initialization failed";
  488. }
  489. }
  490. if (!Result()->error()) {
  491. // -- Setup process stdio options
  492. // stdin
  493. UVOptionsStdIO_[0].flags = UV_IGNORE;
  494. UVOptionsStdIO_[0].data.stream = nullptr;
  495. // stdout
  496. UVOptionsStdIO_[1].flags =
  497. static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
  498. UVOptionsStdIO_[1].data.stream = UVPipeOut_.uv_stream();
  499. // stderr
  500. UVOptionsStdIO_[2].flags =
  501. static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
  502. UVOptionsStdIO_[2].data.stream = UVPipeErr_.uv_stream();
  503. // -- Setup process options
  504. std::fill_n(reinterpret_cast<char*>(&UVOptions_), sizeof(UVOptions_), 0);
  505. UVOptions_.exit_cb = &ReadOnlyProcessT::UVExit;
  506. UVOptions_.file = CommandPtr_[0];
  507. UVOptions_.args = const_cast<char**>(CommandPtr_.data());
  508. UVOptions_.cwd = Setup_.WorkingDirectory.c_str();
  509. UVOptions_.flags = UV_PROCESS_WINDOWS_HIDE;
  510. UVOptions_.stdio_count = static_cast<int>(UVOptionsStdIO_.size());
  511. UVOptions_.stdio = UVOptionsStdIO_.data();
  512. // -- Spawn process
  513. if (UVProcess_.spawn(*uv_loop, UVOptions_, this) != 0) {
  514. Result()->ErrorMessage = "libuv process spawn failed";
  515. }
  516. }
  517. // -- Start reading from stdio streams
  518. if (!Result()->error()) {
  519. if (UVPipeOut_.startRead(&Result()->StdOut) != 0) {
  520. Result()->ErrorMessage = "libuv start reading from stdout pipe failed";
  521. }
  522. }
  523. if (!Result()->error()) {
  524. if (UVPipeErr_.startRead(Setup_.MergedOutput ? &Result()->StdOut
  525. : &Result()->StdErr) != 0) {
  526. Result()->ErrorMessage = "libuv start reading from stderr pipe failed";
  527. }
  528. }
  529. if (!Result()->error()) {
  530. IsStarted_ = true;
  531. FinishedCallback_ = std::move(finishedCallback);
  532. } else {
  533. // Clear libuv handles and finish
  534. UVProcess_.reset();
  535. UVPipeOut_.reset();
  536. UVPipeErr_.reset();
  537. CommandPtr_.clear();
  538. }
  539. return IsStarted();
  540. }
  541. void cmQtAutoGenerator::ReadOnlyProcessT::UVExit(uv_process_t* handle,
  542. int64_t exitStatus,
  543. int termSignal)
  544. {
  545. auto& proc = *reinterpret_cast<ReadOnlyProcessT*>(handle->data);
  546. if (proc.IsStarted() && !proc.IsFinished()) {
  547. // Set error message on demand
  548. proc.Result()->ExitStatus = exitStatus;
  549. proc.Result()->TermSignal = termSignal;
  550. if (!proc.Result()->error()) {
  551. if (termSignal != 0) {
  552. proc.Result()->ErrorMessage = "Process was terminated by signal ";
  553. proc.Result()->ErrorMessage +=
  554. std::to_string(proc.Result()->TermSignal);
  555. } else if (exitStatus != 0) {
  556. proc.Result()->ErrorMessage = "Process failed with return value ";
  557. proc.Result()->ErrorMessage +=
  558. std::to_string(proc.Result()->ExitStatus);
  559. }
  560. }
  561. // Reset process handle and try to finish
  562. proc.UVProcess_.reset();
  563. proc.UVTryFinish();
  564. }
  565. }
  566. void cmQtAutoGenerator::ReadOnlyProcessT::UVTryFinish()
  567. {
  568. // There still might be data in the pipes after the process has finished.
  569. // Therefore check if the process is finished AND all pipes are closed
  570. // before signaling the worker thread to continue.
  571. if (UVProcess_.get() == nullptr) {
  572. if (UVPipeOut_.uv_pipe() == nullptr) {
  573. if (UVPipeErr_.uv_pipe() == nullptr) {
  574. IsFinished_ = true;
  575. FinishedCallback_();
  576. }
  577. }
  578. }
  579. }
  580. cmQtAutoGenerator::cmQtAutoGenerator()
  581. : FileSys_(&Logger_)
  582. {
  583. // Initialize logger
  584. {
  585. std::string verbose;
  586. if (cmSystemTools::GetEnv("VERBOSE", verbose) && !verbose.empty()) {
  587. unsigned long iVerbose = 0;
  588. if (cmSystemTools::StringToULong(verbose.c_str(), &iVerbose)) {
  589. Logger_.SetVerbosity(static_cast<unsigned int>(iVerbose));
  590. } else {
  591. // Non numeric verbosity
  592. Logger_.SetVerbose(cmSystemTools::IsOn(verbose));
  593. }
  594. }
  595. }
  596. {
  597. std::string colorEnv;
  598. cmSystemTools::GetEnv("COLOR", colorEnv);
  599. if (!colorEnv.empty()) {
  600. Logger_.SetColorOutput(cmSystemTools::IsOn(colorEnv));
  601. } else {
  602. Logger_.SetColorOutput(true);
  603. }
  604. }
  605. // Initialize libuv loop
  606. uv_disable_stdio_inheritance();
  607. #ifdef CMAKE_UV_SIGNAL_HACK
  608. UVHackRAII_ = cm::make_unique<cmUVSignalHackRAII>();
  609. #endif
  610. UVLoop_ = cm::make_unique<uv_loop_t>();
  611. uv_loop_init(UVLoop());
  612. }
  613. cmQtAutoGenerator::~cmQtAutoGenerator()
  614. {
  615. // Close libuv loop
  616. uv_loop_close(UVLoop());
  617. }
  618. bool cmQtAutoGenerator::Run(std::string const& infoFile,
  619. std::string const& config)
  620. {
  621. // Info settings
  622. InfoFile_ = infoFile;
  623. cmSystemTools::ConvertToUnixSlashes(InfoFile_);
  624. InfoDir_ = cmSystemTools::GetFilenamePath(infoFile);
  625. InfoConfig_ = config;
  626. bool success = false;
  627. {
  628. cmake cm(cmake::RoleScript, cmState::Unknown);
  629. cm.SetHomeOutputDirectory(InfoDir());
  630. cm.SetHomeDirectory(InfoDir());
  631. cm.GetCurrentSnapshot().SetDefaultDefinitions();
  632. cmGlobalGenerator gg(&cm);
  633. cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
  634. snapshot.GetDirectory().SetCurrentBinary(InfoDir());
  635. snapshot.GetDirectory().SetCurrentSource(InfoDir());
  636. auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot);
  637. // The OLD/WARN behavior for policy CMP0053 caused a speed regression.
  638. // https://gitlab.kitware.com/cmake/cmake/issues/17570
  639. makefile->SetPolicyVersion("3.9", std::string());
  640. gg.SetCurrentMakefile(makefile.get());
  641. success = this->Init(makefile.get());
  642. }
  643. if (success) {
  644. success = this->Process();
  645. }
  646. return success;
  647. }
  648. std::string cmQtAutoGenerator::SettingsFind(std::string const& content,
  649. const char* key)
  650. {
  651. std::string prefix(key);
  652. prefix += ':';
  653. std::string::size_type pos = content.find(prefix);
  654. if (pos != std::string::npos) {
  655. pos += prefix.size();
  656. if (pos < content.size()) {
  657. std::string::size_type posE = content.find('\n', pos);
  658. if ((posE != std::string::npos) && (posE != pos)) {
  659. return content.substr(pos, posE - pos);
  660. }
  661. }
  662. }
  663. return std::string();
  664. }