cmCustomCommandGenerator.cxx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  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 "cmCustomCommandGenerator.h"
  4. #include "cmCustomCommand.h"
  5. #include "cmCustomCommandLines.h"
  6. #include "cmGeneratorExpression.h"
  7. #include "cmGeneratorTarget.h"
  8. #include "cmLocalGenerator.h"
  9. #include "cmMakefile.h"
  10. #include "cmOutputConverter.h"
  11. #include "cmStateTypes.h"
  12. #include "cmSystemTools.h"
  13. #include "cm_auto_ptr.hxx"
  14. #include "cmConfigure.h"
  15. cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
  16. const std::string& config,
  17. cmLocalGenerator* lg)
  18. : CC(cc)
  19. , Config(config)
  20. , LG(lg)
  21. , OldStyle(cc.GetEscapeOldStyle())
  22. , MakeVars(cc.GetEscapeAllowMakeVars())
  23. , GE(new cmGeneratorExpression(cc.GetBacktrace()))
  24. {
  25. const cmCustomCommandLines& cmdlines = this->CC.GetCommandLines();
  26. for (cmCustomCommandLines::const_iterator cmdline = cmdlines.begin();
  27. cmdline != cmdlines.end(); ++cmdline) {
  28. cmCustomCommandLine argv;
  29. for (cmCustomCommandLine::const_iterator clarg = cmdline->begin();
  30. clarg != cmdline->end(); ++clarg) {
  31. CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = this->GE->Parse(*clarg);
  32. std::string parsed_arg = cge->Evaluate(this->LG, this->Config);
  33. if (this->CC.GetCommandExpandLists()) {
  34. std::vector<std::string> ExpandedArg;
  35. cmSystemTools::ExpandListArgument(parsed_arg, ExpandedArg);
  36. argv.insert(argv.end(), ExpandedArg.begin(), ExpandedArg.end());
  37. } else {
  38. argv.push_back(parsed_arg);
  39. }
  40. }
  41. this->CommandLines.push_back(argv);
  42. }
  43. std::vector<std::string> depends = this->CC.GetDepends();
  44. for (std::vector<std::string>::const_iterator i = depends.begin();
  45. i != depends.end(); ++i) {
  46. CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = this->GE->Parse(*i);
  47. std::vector<std::string> result;
  48. cmSystemTools::ExpandListArgument(cge->Evaluate(this->LG, this->Config),
  49. result);
  50. for (std::vector<std::string>::iterator it = result.begin();
  51. it != result.end(); ++it) {
  52. if (cmSystemTools::FileIsFullPath(it->c_str())) {
  53. *it = cmSystemTools::CollapseFullPath(*it);
  54. }
  55. }
  56. this->Depends.insert(this->Depends.end(), result.begin(), result.end());
  57. }
  58. }
  59. cmCustomCommandGenerator::~cmCustomCommandGenerator()
  60. {
  61. delete this->GE;
  62. }
  63. unsigned int cmCustomCommandGenerator::GetNumberOfCommands() const
  64. {
  65. return static_cast<unsigned int>(this->CC.GetCommandLines().size());
  66. }
  67. const char* cmCustomCommandGenerator::GetCrossCompilingEmulator(
  68. unsigned int c) const
  69. {
  70. if (!this->LG->GetMakefile()->IsOn("CMAKE_CROSSCOMPILING")) {
  71. return nullptr;
  72. }
  73. std::string const& argv0 = this->CommandLines[c][0];
  74. cmGeneratorTarget* target = this->LG->FindGeneratorTargetToUse(argv0);
  75. if (target && target->GetType() == cmStateEnums::EXECUTABLE &&
  76. !target->IsImported()) {
  77. return target->GetProperty("CROSSCOMPILING_EMULATOR");
  78. }
  79. return nullptr;
  80. }
  81. const char* cmCustomCommandGenerator::GetArgv0Location(unsigned int c) const
  82. {
  83. std::string const& argv0 = this->CommandLines[c][0];
  84. cmGeneratorTarget* target = this->LG->FindGeneratorTargetToUse(argv0);
  85. if (target && target->GetType() == cmStateEnums::EXECUTABLE &&
  86. (target->IsImported() ||
  87. target->GetProperty("CROSSCOMPILING_EMULATOR") ||
  88. !this->LG->GetMakefile()->IsOn("CMAKE_CROSSCOMPILING"))) {
  89. return target->GetLocation(this->Config);
  90. }
  91. return nullptr;
  92. }
  93. std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const
  94. {
  95. if (const char* emulator = this->GetCrossCompilingEmulator(c)) {
  96. return std::string(emulator);
  97. }
  98. if (const char* location = this->GetArgv0Location(c)) {
  99. return std::string(location);
  100. }
  101. return this->CommandLines[c][0];
  102. }
  103. std::string escapeForShellOldStyle(const std::string& str)
  104. {
  105. std::string result;
  106. #if defined(_WIN32) && !defined(__CYGWIN__)
  107. // if there are spaces
  108. std::string temp = str;
  109. if (temp.find(" ") != std::string::npos &&
  110. temp.find("\"") == std::string::npos) {
  111. result = "\"";
  112. result += str;
  113. result += "\"";
  114. return result;
  115. }
  116. return str;
  117. #else
  118. for (const char* ch = str.c_str(); *ch != '\0'; ++ch) {
  119. if (*ch == ' ') {
  120. result += '\\';
  121. }
  122. result += *ch;
  123. }
  124. return result;
  125. #endif
  126. }
  127. void cmCustomCommandGenerator::AppendArguments(unsigned int c,
  128. std::string& cmd) const
  129. {
  130. unsigned int offset = 1;
  131. if (this->GetCrossCompilingEmulator(c) != nullptr) {
  132. offset = 0;
  133. }
  134. cmCustomCommandLine const& commandLine = this->CommandLines[c];
  135. for (unsigned int j = offset; j < commandLine.size(); ++j) {
  136. std::string arg;
  137. if (const char* location = j == 0 ? this->GetArgv0Location(c) : nullptr) {
  138. // GetCommand returned the emulator instead of the argv0 location,
  139. // so transform the latter now.
  140. arg = location;
  141. } else {
  142. arg = commandLine[j];
  143. }
  144. cmd += " ";
  145. if (this->OldStyle) {
  146. cmd += escapeForShellOldStyle(arg);
  147. } else {
  148. cmOutputConverter converter(this->LG->GetStateSnapshot());
  149. cmd += converter.EscapeForShell(arg, this->MakeVars);
  150. }
  151. }
  152. }
  153. const char* cmCustomCommandGenerator::GetComment() const
  154. {
  155. return this->CC.GetComment();
  156. }
  157. std::string cmCustomCommandGenerator::GetWorkingDirectory() const
  158. {
  159. return this->CC.GetWorkingDirectory();
  160. }
  161. std::vector<std::string> const& cmCustomCommandGenerator::GetOutputs() const
  162. {
  163. return this->CC.GetOutputs();
  164. }
  165. std::vector<std::string> const& cmCustomCommandGenerator::GetByproducts() const
  166. {
  167. return this->CC.GetByproducts();
  168. }
  169. std::vector<std::string> const& cmCustomCommandGenerator::GetDepends() const
  170. {
  171. return this->Depends;
  172. }