cmGlobalCommonGenerator.cxx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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 "cmGlobalCommonGenerator.h"
  4. #include <memory>
  5. #include <utility>
  6. #include <cmext/algorithm>
  7. #include "cmGeneratorExpression.h"
  8. #include "cmGeneratorTarget.h"
  9. #include "cmLocalGenerator.h"
  10. #include "cmMakefile.h"
  11. #include "cmProperty.h"
  12. #include "cmStateDirectory.h"
  13. #include "cmStateSnapshot.h"
  14. #include "cmStateTypes.h"
  15. #include "cmStringAlgorithms.h"
  16. #include "cmSystemTools.h"
  17. #include "cmake.h"
  18. cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm)
  19. : cmGlobalGenerator(cm)
  20. {
  21. }
  22. cmGlobalCommonGenerator::~cmGlobalCommonGenerator() = default;
  23. std::map<std::string, cmGlobalCommonGenerator::DirectoryTarget>
  24. cmGlobalCommonGenerator::ComputeDirectoryTargets() const
  25. {
  26. std::map<std::string, DirectoryTarget> dirTargets;
  27. for (const auto& lg : this->LocalGenerators) {
  28. std::string const& currentBinaryDir(
  29. lg->GetStateSnapshot().GetDirectory().GetCurrentBinary());
  30. DirectoryTarget& dirTarget = dirTargets[currentBinaryDir];
  31. dirTarget.LG = lg.get();
  32. const std::vector<std::string>& configs =
  33. lg->GetMakefile()->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
  34. // The directory-level rule should depend on the target-level rules
  35. // for all targets in the directory.
  36. for (const auto& gt : lg->GetGeneratorTargets()) {
  37. cmStateEnums::TargetType const type = gt->GetType();
  38. if (type == cmStateEnums::GLOBAL_TARGET || !gt->IsInBuildSystem()) {
  39. continue;
  40. }
  41. DirectoryTarget::Target t;
  42. t.GT = gt.get();
  43. const std::string EXCLUDE_FROM_ALL("EXCLUDE_FROM_ALL");
  44. if (cmProp exclude = gt->GetProperty(EXCLUDE_FROM_ALL)) {
  45. for (const std::string& config : configs) {
  46. cmGeneratorExpressionInterpreter genexInterpreter(lg.get(), config,
  47. gt.get());
  48. if (cmIsOn(genexInterpreter.Evaluate(*exclude, EXCLUDE_FROM_ALL))) {
  49. // This target has been explicitly excluded.
  50. t.ExcludedFromAllInConfigs.push_back(config);
  51. }
  52. }
  53. if (t.ExcludedFromAllInConfigs.empty()) {
  54. // This target has been explicitly un-excluded. The directory-level
  55. // rule for every directory between this and the root should depend
  56. // on the target-level rule for this target.
  57. for (cmStateSnapshot dir =
  58. lg->GetStateSnapshot().GetBuildsystemDirectoryParent();
  59. dir.IsValid(); dir = dir.GetBuildsystemDirectoryParent()) {
  60. std::string const& d = dir.GetDirectory().GetCurrentBinary();
  61. dirTargets[d].Targets.emplace_back(t);
  62. }
  63. }
  64. }
  65. dirTarget.Targets.emplace_back(t);
  66. }
  67. // The directory-level rule should depend on the directory-level
  68. // rules of the subdirectories.
  69. for (cmStateSnapshot const& state : lg->GetStateSnapshot().GetChildren()) {
  70. DirectoryTarget::Dir d;
  71. d.Path = state.GetDirectory().GetCurrentBinary();
  72. d.ExcludeFromAll =
  73. state.GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL");
  74. dirTarget.Children.emplace_back(std::move(d));
  75. }
  76. }
  77. return dirTargets;
  78. }
  79. bool cmGlobalCommonGenerator::IsExcludedFromAllInConfig(
  80. const DirectoryTarget::Target& t, const std::string& config)
  81. {
  82. if (this->IsMultiConfig()) {
  83. return cm::contains(t.ExcludedFromAllInConfigs, config);
  84. }
  85. return !t.ExcludedFromAllInConfigs.empty();
  86. }
  87. std::string cmGlobalCommonGenerator::GetEditCacheCommand() const
  88. {
  89. // If generating for an extra IDE, the edit_cache target cannot
  90. // launch a terminal-interactive tool, so always use cmake-gui.
  91. if (!this->GetExtraGeneratorName().empty()) {
  92. return cmSystemTools::GetCMakeGUICommand();
  93. }
  94. // Use an internal cache entry to track the latest dialog used
  95. // to edit the cache, and use that for the edit_cache target.
  96. cmake* cm = this->GetCMakeInstance();
  97. std::string editCacheCommand = cm->GetCMakeEditCommand();
  98. if (!cm->GetCacheDefinition("CMAKE_EDIT_COMMAND") ||
  99. !editCacheCommand.empty()) {
  100. if (this->SupportsDirectConsole() && editCacheCommand.empty()) {
  101. editCacheCommand = cmSystemTools::GetCMakeCursesCommand();
  102. }
  103. if (editCacheCommand.empty()) {
  104. editCacheCommand = cmSystemTools::GetCMakeGUICommand();
  105. }
  106. if (!editCacheCommand.empty()) {
  107. cm->AddCacheEntry("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(),
  108. "Path to cache edit program executable.",
  109. cmStateEnums::INTERNAL);
  110. }
  111. }
  112. cmProp edit_cmd = cm->GetCacheDefinition("CMAKE_EDIT_COMMAND");
  113. return edit_cmd ? *edit_cmd : std::string();
  114. }