cmQtAutoGeneratorCommon.cxx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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 "cmQtAutoGeneratorCommon.h"
  4. #include "cmAlgorithms.h"
  5. #include "cmSystemTools.h"
  6. #include <cmsys/FStream.hxx>
  7. #include <cmsys/RegularExpression.hxx>
  8. #include <sstream>
  9. // - Static functions
  10. static std::string utilStripCR(std::string const& line)
  11. {
  12. // Strip CR characters rcc may have printed (possibly more than one!).
  13. std::string::size_type cr = line.find('\r');
  14. if (cr != line.npos) {
  15. return line.substr(0, cr);
  16. }
  17. return line;
  18. }
  19. /// @brief Reads the resource files list from from a .qrc file - Qt4 version
  20. /// @return True if the .qrc file was successfully parsed
  21. static bool RccListInputsQt4(const std::string& fileName,
  22. std::vector<std::string>& files)
  23. {
  24. // Qrc file directory
  25. std::string qrcDir(cmsys::SystemTools::GetFilenamePath(fileName));
  26. if (!qrcDir.empty()) {
  27. qrcDir += '/';
  28. }
  29. // Read file into string
  30. std::string qrcContents;
  31. {
  32. std::ostringstream stream;
  33. stream << cmsys::ifstream(fileName).rdbuf();
  34. qrcContents = stream.str();
  35. }
  36. cmsys::RegularExpression fileMatchRegex("(<file[^<]+)");
  37. cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)");
  38. size_t offset = 0;
  39. while (fileMatchRegex.find(qrcContents.c_str() + offset)) {
  40. std::string qrcEntry = fileMatchRegex.match(1);
  41. offset += qrcEntry.size();
  42. {
  43. fileReplaceRegex.find(qrcEntry);
  44. std::string tag = fileReplaceRegex.match(1);
  45. qrcEntry = qrcEntry.substr(tag.size());
  46. }
  47. if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) {
  48. qrcEntry = qrcDir + qrcEntry;
  49. }
  50. files.push_back(qrcEntry);
  51. }
  52. return true;
  53. }
  54. /// @brief Reads the resource files list from from a .qrc file - Qt5 version
  55. /// @return True if the .qrc file was successfully parsed
  56. static bool RccListInputsQt5(const std::string& rccCommand,
  57. const std::string& fileName,
  58. std::vector<std::string>& files)
  59. {
  60. if (rccCommand.empty()) {
  61. cmSystemTools::Error("AutoRcc: Error: rcc executable not available\n");
  62. return false;
  63. }
  64. // Read rcc features
  65. bool hasDashDashList = false;
  66. {
  67. std::vector<std::string> command;
  68. command.push_back(rccCommand);
  69. command.push_back("--help");
  70. std::string rccStdOut;
  71. std::string rccStdErr;
  72. int retVal = 0;
  73. bool result =
  74. cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal,
  75. CM_NULLPTR, cmSystemTools::OUTPUT_NONE);
  76. if (result && retVal == 0 &&
  77. rccStdOut.find("--list") != std::string::npos) {
  78. hasDashDashList = true;
  79. }
  80. }
  81. // Run rcc list command
  82. bool result = false;
  83. int retVal = 0;
  84. std::string rccStdOut;
  85. std::string rccStdErr;
  86. {
  87. std::vector<std::string> command;
  88. command.push_back(rccCommand);
  89. command.push_back(hasDashDashList ? "--list" : "-list");
  90. command.push_back(fileName);
  91. result =
  92. cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal,
  93. CM_NULLPTR, cmSystemTools::OUTPUT_NONE);
  94. }
  95. if (!result || retVal) {
  96. std::ostringstream err;
  97. err << "AUTOGEN: error: Rcc list process for " << fileName << " failed:\n"
  98. << rccStdOut << "\n"
  99. << rccStdErr << std::endl;
  100. cmSystemTools::Error(err.str().c_str());
  101. return false;
  102. }
  103. // Parse rcc std output
  104. {
  105. std::istringstream ostr(rccStdOut);
  106. std::string oline;
  107. while (std::getline(ostr, oline)) {
  108. oline = utilStripCR(oline);
  109. if (!oline.empty()) {
  110. files.push_back(oline);
  111. }
  112. }
  113. }
  114. // Parse rcc error output
  115. {
  116. std::istringstream estr(rccStdErr);
  117. std::string eline;
  118. while (std::getline(estr, eline)) {
  119. eline = utilStripCR(eline);
  120. if (cmHasLiteralPrefix(eline, "RCC: Error in")) {
  121. static std::string searchString = "Cannot find file '";
  122. std::string::size_type pos = eline.find(searchString);
  123. if (pos == std::string::npos) {
  124. std::ostringstream err;
  125. err << "AUTOGEN: error: Rcc lists unparsable output " << eline
  126. << std::endl;
  127. cmSystemTools::Error(err.str().c_str());
  128. return false;
  129. }
  130. pos += searchString.length();
  131. std::string::size_type sz = eline.size() - pos - 1;
  132. files.push_back(eline.substr(pos, sz));
  133. }
  134. }
  135. }
  136. return true;
  137. }
  138. // - Class definitions
  139. const char* cmQtAutoGeneratorCommon::listSep = "@list_sep@";
  140. bool cmQtAutoGeneratorCommon::RccListInputs(const std::string& qtMajorVersion,
  141. const std::string& rccCommand,
  142. const std::string& fileName,
  143. std::vector<std::string>& files)
  144. {
  145. if (qtMajorVersion == "4") {
  146. return RccListInputsQt4(fileName, files);
  147. }
  148. return RccListInputsQt5(rccCommand, fileName, files);
  149. }