cmAddCustomCommandCommand.cxx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "cmAddCustomCommandCommand.h"
  14. #include "cmTarget.h"
  15. // cmAddCustomCommandCommand
  16. bool cmAddCustomCommandCommand::InitialPass(std::vector<std::string> const& args)
  17. {
  18. /* Let's complain at the end of this function about the lack of a particular
  19. arg. For the moment, let's say that COMMAND, and either TARGET or SOURCE
  20. are required.
  21. */
  22. if (args.size() < 4)
  23. {
  24. this->SetError("called with wrong number of arguments.");
  25. return false;
  26. }
  27. std::string source, target, comment, output, main_dependency;
  28. std::vector<std::string> depends, outputs;
  29. // Accumulate one command line at a time.
  30. cmCustomCommandLine currentLine;
  31. // Save all command lines.
  32. cmCustomCommandLines commandLines;
  33. cmTarget::CustomCommandType cctype = cmTarget::POST_BUILD;
  34. enum tdoing {
  35. doing_source,
  36. doing_command,
  37. doing_target,
  38. doing_depends,
  39. doing_main_dependency,
  40. doing_output,
  41. doing_outputs,
  42. doing_comment,
  43. doing_nothing
  44. };
  45. tdoing doing = doing_nothing;
  46. for (unsigned int j = 0; j < args.size(); ++j)
  47. {
  48. std::string const& copy = args[j];
  49. if(copy == "SOURCE")
  50. {
  51. doing = doing_source;
  52. }
  53. else if(copy == "COMMAND")
  54. {
  55. doing = doing_command;
  56. // Save the current command before starting the next command.
  57. if(!currentLine.empty())
  58. {
  59. commandLines.push_back(currentLine);
  60. currentLine.clear();
  61. }
  62. }
  63. else if(copy == "PRE_BUILD")
  64. {
  65. cctype = cmTarget::PRE_BUILD;
  66. }
  67. else if(copy == "PRE_LINK")
  68. {
  69. cctype = cmTarget::PRE_LINK;
  70. }
  71. else if(copy == "POST_BUILD")
  72. {
  73. cctype = cmTarget::POST_BUILD;
  74. }
  75. else if(copy == "TARGET")
  76. {
  77. doing = doing_target;
  78. }
  79. else if(copy == "ARGS")
  80. {
  81. // Ignore this old keyword.
  82. }
  83. else if (copy == "DEPENDS")
  84. {
  85. doing = doing_depends;
  86. }
  87. else if (copy == "OUTPUTS")
  88. {
  89. doing = doing_outputs;
  90. }
  91. else if (copy == "OUTPUT")
  92. {
  93. doing = doing_output;
  94. }
  95. else if (copy == "MAIN_DEPENDENCY")
  96. {
  97. doing = doing_main_dependency;
  98. }
  99. else if (copy == "COMMENT")
  100. {
  101. doing = doing_comment;
  102. }
  103. else
  104. {
  105. std::string filename;
  106. switch (doing)
  107. {
  108. case doing_source:
  109. case doing_output:
  110. case doing_outputs:
  111. if (!cmSystemTools::FileIsFullPath(copy.c_str()))
  112. {
  113. filename = m_Makefile->GetStartDirectory();
  114. filename += "/";
  115. }
  116. filename += copy;
  117. break;
  118. default:
  119. break;
  120. }
  121. switch (doing)
  122. {
  123. case doing_source:
  124. source = filename;
  125. break;
  126. case doing_output:
  127. output = filename;
  128. break;
  129. case doing_main_dependency:
  130. main_dependency = copy;
  131. break;
  132. case doing_command:
  133. currentLine.push_back(copy);
  134. break;
  135. case doing_target:
  136. target = copy;
  137. break;
  138. case doing_depends:
  139. depends.push_back(copy);
  140. break;
  141. case doing_outputs:
  142. outputs.push_back(filename);
  143. break;
  144. case doing_comment:
  145. comment = copy;
  146. break;
  147. default:
  148. this->SetError("Wrong syntax. Unknown type of argument.");
  149. return false;
  150. }
  151. }
  152. }
  153. // Store the last command line finished.
  154. if(!currentLine.empty())
  155. {
  156. commandLines.push_back(currentLine);
  157. currentLine.clear();
  158. }
  159. // At this point we could complain about the lack of arguments. For
  160. // the moment, let's say that COMMAND, TARGET are always required.
  161. if(output.empty() && target.empty())
  162. {
  163. this->SetError("Wrong syntax. A TARGET or OUTPUT must be specified.");
  164. return false;
  165. }
  166. if(source.empty() && !target.empty() && !output.empty())
  167. {
  168. this->SetError("Wrong syntax. A TARGET and OUTPUT can not both be specified.");
  169. return false;
  170. }
  171. std::string::size_type pos = output.find_first_of("#<>");
  172. if(pos != output.npos)
  173. {
  174. cmOStringStream msg;
  175. msg << "called with OUTPUT containing a \"" << output[pos]
  176. << "\". This character is not allowed.";
  177. this->SetError(msg.str().c_str());
  178. return false;
  179. }
  180. // Choose which mode of the command to use.
  181. if(source.empty() && output.empty())
  182. {
  183. // Source is empty, use the target.
  184. std::vector<std::string> no_depends;
  185. m_Makefile->AddCustomCommandToTarget(target.c_str(), no_depends,
  186. commandLines, cctype,
  187. comment.c_str());
  188. }
  189. else if(target.empty())
  190. {
  191. // Target is empty, use the output.
  192. m_Makefile->AddCustomCommandToOutput(output.c_str(), depends,
  193. main_dependency.c_str(),
  194. commandLines, comment.c_str());
  195. }
  196. else
  197. {
  198. // Use the old-style mode for backward compatibility.
  199. m_Makefile->AddCustomCommandOldStyle(target.c_str(), outputs, depends,
  200. source.c_str(), commandLines,
  201. comment.c_str());
  202. }
  203. return true;
  204. }