cmAddCustomCommandCommand.cxx 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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_output:
  109. case doing_outputs:
  110. if (!cmSystemTools::FileIsFullPath(copy.c_str()))
  111. {
  112. filename = m_Makefile->GetStartDirectory();
  113. filename += "/";
  114. }
  115. filename += copy;
  116. break;
  117. case doing_source:
  118. // We do not want to convert the argument to SOURCE because
  119. // that option is only available for backward compatibility.
  120. // Old-style use of this command may use the SOURCE==TARGET
  121. // trick which we must preserve. If we convert the source
  122. // to a full path then it will no longer equal the target.
  123. default:
  124. break;
  125. }
  126. switch (doing)
  127. {
  128. case doing_source:
  129. source = copy;
  130. break;
  131. case doing_output:
  132. output = filename;
  133. break;
  134. case doing_main_dependency:
  135. main_dependency = copy;
  136. break;
  137. case doing_command:
  138. currentLine.push_back(copy);
  139. break;
  140. case doing_target:
  141. target = copy;
  142. break;
  143. case doing_depends:
  144. depends.push_back(copy);
  145. break;
  146. case doing_outputs:
  147. outputs.push_back(filename);
  148. break;
  149. case doing_comment:
  150. comment = copy;
  151. break;
  152. default:
  153. this->SetError("Wrong syntax. Unknown type of argument.");
  154. return false;
  155. }
  156. }
  157. }
  158. // Store the last command line finished.
  159. if(!currentLine.empty())
  160. {
  161. commandLines.push_back(currentLine);
  162. currentLine.clear();
  163. }
  164. // At this point we could complain about the lack of arguments. For
  165. // the moment, let's say that COMMAND, TARGET are always required.
  166. if(output.empty() && target.empty())
  167. {
  168. this->SetError("Wrong syntax. A TARGET or OUTPUT must be specified.");
  169. return false;
  170. }
  171. if(source.empty() && !target.empty() && !output.empty())
  172. {
  173. this->SetError("Wrong syntax. A TARGET and OUTPUT can not both be specified.");
  174. return false;
  175. }
  176. std::string::size_type pos = output.find_first_of("#<>");
  177. if(pos != output.npos)
  178. {
  179. cmOStringStream msg;
  180. msg << "called with OUTPUT containing a \"" << output[pos]
  181. << "\". This character is not allowed.";
  182. this->SetError(msg.str().c_str());
  183. return false;
  184. }
  185. // Choose which mode of the command to use.
  186. if(source.empty() && output.empty())
  187. {
  188. // Source is empty, use the target.
  189. std::vector<std::string> no_depends;
  190. m_Makefile->AddCustomCommandToTarget(target.c_str(), no_depends,
  191. commandLines, cctype,
  192. comment.c_str());
  193. }
  194. else if(target.empty())
  195. {
  196. // Target is empty, use the output.
  197. m_Makefile->AddCustomCommandToOutput(output.c_str(), depends,
  198. main_dependency.c_str(),
  199. commandLines, comment.c_str());
  200. }
  201. else
  202. {
  203. // Use the old-style mode for backward compatibility.
  204. m_Makefile->AddCustomCommandOldStyle(target.c_str(), outputs, depends,
  205. source.c_str(), commandLines,
  206. comment.c_str());
  207. }
  208. return true;
  209. }