cmNinjaUtilityTargetGenerator.cxx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2011 Peter Collingbourne <[email protected]>
  4. Copyright 2011 Nicolas Despres <[email protected]>
  5. Distributed under the OSI-approved BSD License (the "License");
  6. see accompanying file Copyright.txt for details.
  7. This software is distributed WITHOUT ANY WARRANTY; without even the
  8. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. See the License for more information.
  10. ============================================================================*/
  11. #include "cmNinjaUtilityTargetGenerator.h"
  12. #include "cmCustomCommand.h"
  13. #include "cmGeneratedFileStream.h"
  14. #include "cmGlobalNinjaGenerator.h"
  15. #include "cmMakefile.h"
  16. #include "cmSourceFile.h"
  17. #include "cmTarget.h"
  18. #include "cmCustomCommandGenerator.h"
  19. cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator(
  20. cmGeneratorTarget *target)
  21. : cmNinjaTargetGenerator(target) {}
  22. cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() {}
  23. void cmNinjaUtilityTargetGenerator::Generate()
  24. {
  25. std::string utilCommandName = cmake::GetCMakeFilesDirectoryPostSlash();
  26. utilCommandName += this->GetTargetName() + ".util";
  27. std::vector<std::string> commands;
  28. cmNinjaDeps deps, outputs, util_outputs(1, utilCommandName);
  29. const std::vector<cmCustomCommand> *cmdLists[2] = {
  30. &this->GetTarget()->GetPreBuildCommands(),
  31. &this->GetTarget()->GetPostBuildCommands()
  32. };
  33. bool uses_terminal = false;
  34. for (unsigned i = 0; i != 2; ++i) {
  35. for (std::vector<cmCustomCommand>::const_iterator
  36. ci = cmdLists[i]->begin(); ci != cmdLists[i]->end(); ++ci) {
  37. cmCustomCommandGenerator ccg(*ci, this->GetConfigName(),
  38. this->GetLocalGenerator());
  39. this->GetLocalGenerator()->AppendCustomCommandDeps(ccg, deps);
  40. this->GetLocalGenerator()->AppendCustomCommandLines(ccg, commands);
  41. std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
  42. std::transform(ccByproducts.begin(), ccByproducts.end(),
  43. std::back_inserter(util_outputs), MapToNinjaPath());
  44. if (ci->GetUsesTerminal())
  45. uses_terminal = true;
  46. }
  47. }
  48. std::vector<cmSourceFile*> sources;
  49. std::string config = this->GetMakefile()
  50. ->GetSafeDefinition("CMAKE_BUILD_TYPE");
  51. this->GetTarget()->GetSourceFiles(sources, config);
  52. for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
  53. source != sources.end(); ++source)
  54. {
  55. if(cmCustomCommand* cc = (*source)->GetCustomCommand())
  56. {
  57. cmCustomCommandGenerator ccg(*cc, this->GetConfigName(),
  58. this->GetLocalGenerator());
  59. this->GetLocalGenerator()->AddCustomCommandTarget(cc, this->GetTarget());
  60. // Depend on all custom command outputs.
  61. const std::vector<std::string>& ccOutputs = ccg.GetOutputs();
  62. const std::vector<std::string>& ccByproducts = ccg.GetByproducts();
  63. std::transform(ccOutputs.begin(), ccOutputs.end(),
  64. std::back_inserter(deps), MapToNinjaPath());
  65. std::transform(ccByproducts.begin(), ccByproducts.end(),
  66. std::back_inserter(deps), MapToNinjaPath());
  67. }
  68. }
  69. this->GetLocalGenerator()->AppendTargetOutputs(this->GetTarget(), outputs);
  70. this->GetLocalGenerator()->AppendTargetDepends(this->GetTarget(), deps);
  71. if (commands.empty()) {
  72. this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(),
  73. "Utility command for "
  74. + this->GetTargetName(),
  75. outputs,
  76. deps);
  77. } else {
  78. std::string command =
  79. this->GetLocalGenerator()->BuildCommandLine(commands);
  80. const char *echoStr = this->GetTarget()->GetProperty("EchoString");
  81. std::string desc;
  82. if (echoStr)
  83. desc = echoStr;
  84. else
  85. desc = "Running utility command for " + this->GetTargetName();
  86. // TODO: fix problematic global targets. For now, search and replace the
  87. // makefile vars.
  88. cmSystemTools::ReplaceString(
  89. command,
  90. "$(CMAKE_SOURCE_DIR)",
  91. this->GetLocalGenerator()->ConvertToOutputFormat(
  92. this->GetTarget()->GetMakefile()->GetHomeDirectory(),
  93. cmLocalGenerator::SHELL).c_str());
  94. cmSystemTools::ReplaceString(
  95. command,
  96. "$(CMAKE_BINARY_DIR)",
  97. this->GetLocalGenerator()->ConvertToOutputFormat(
  98. this->GetTarget()->GetMakefile()->GetHomeOutputDirectory(),
  99. cmLocalGenerator::SHELL).c_str());
  100. cmSystemTools::ReplaceString(command, "$(ARGS)", "");
  101. if (command.find('$') != std::string::npos)
  102. return;
  103. for (cmNinjaDeps::const_iterator
  104. oi = util_outputs.begin(), oe = util_outputs.end();
  105. oi != oe; ++oi)
  106. {
  107. this->GetGlobalGenerator()->SeenCustomCommandOutput(*oi);
  108. }
  109. this->GetGlobalGenerator()->WriteCustomCommandBuild(
  110. command,
  111. desc,
  112. "Utility command for " + this->GetTargetName(),
  113. uses_terminal,
  114. util_outputs,
  115. deps);
  116. this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(),
  117. "",
  118. outputs,
  119. cmNinjaDeps(1, utilCommandName)
  120. );
  121. }
  122. this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
  123. this->GetTarget());
  124. }