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