Coverage Report

Created: 2026-07-14 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmGlobalCommonGenerator.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
#include "cmGlobalCommonGenerator.h"
4
5
#include <algorithm>
6
#include <memory>
7
#include <utility>
8
9
#include <cmext/algorithm>
10
11
#include <cmsys/Glob.hxx>
12
13
#include "cmGeneratorExpression.h"
14
#include "cmGeneratorTarget.h"
15
#include "cmLocalCommonGenerator.h"
16
#include "cmLocalGenerator.h"
17
#include "cmStateDirectory.h"
18
#include "cmStateSnapshot.h"
19
#include "cmStateTypes.h"
20
#include "cmStringAlgorithms.h"
21
#include "cmSystemTools.h"
22
#include "cmTargetTypes.h"
23
#include "cmValue.h"
24
#include "cmake.h"
25
26
cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm)
27
0
  : cmGlobalGenerator(cm)
28
0
{
29
0
}
30
31
0
cmGlobalCommonGenerator::~cmGlobalCommonGenerator() = default;
32
33
std::map<std::string, cmGlobalCommonGenerator::DirectoryTarget>
34
cmGlobalCommonGenerator::ComputeDirectoryTargets() const
35
0
{
36
0
  std::map<std::string, DirectoryTarget> dirTargets;
37
0
  for (auto const& lg : this->LocalGenerators) {
38
0
    std::string currentBinaryDir =
39
0
      lg->GetStateSnapshot().GetDirectory().GetCurrentBinary();
40
0
    DirectoryTarget& dirTarget = dirTargets[currentBinaryDir];
41
0
    dirTarget.LG = lg.get();
42
0
    std::vector<std::string> const& configs =
43
0
      static_cast<cmLocalCommonGenerator const*>(lg.get())->GetConfigNames();
44
45
    // The directory-level rule should depend on the target-level rules
46
    // for all targets in the directory.
47
0
    for (auto const& gt : lg->GetGeneratorTargets()) {
48
0
      cm::TargetType const type = gt->GetType();
49
0
      if (type == cm::TargetType::GLOBAL_TARGET || !gt->IsInBuildSystem()) {
50
0
        continue;
51
0
      }
52
0
      DirectoryTarget::Target t;
53
0
      t.GT = gt.get();
54
0
      std::string const EXCLUDE_FROM_ALL("EXCLUDE_FROM_ALL");
55
0
      if (cmValue exclude = gt->GetProperty(EXCLUDE_FROM_ALL)) {
56
0
        for (std::string const& config : configs) {
57
0
          cmGeneratorExpressionInterpreter genexInterpreter(lg.get(), config,
58
0
                                                            gt.get());
59
0
          if (cmIsOn(genexInterpreter.Evaluate(*exclude, EXCLUDE_FROM_ALL))) {
60
            // This target has been explicitly excluded.
61
0
            t.ExcludedFromAllInConfigs.push_back(config);
62
0
          }
63
0
        }
64
65
0
        if (t.ExcludedFromAllInConfigs.empty()) {
66
          // This target has been explicitly un-excluded.  The directory-level
67
          // rule for every directory between this and the root should depend
68
          // on the target-level rule for this target.
69
0
          for (cmStateSnapshot dir =
70
0
                 lg->GetStateSnapshot().GetBuildsystemDirectoryParent();
71
0
               dir.IsValid(); dir = dir.GetBuildsystemDirectoryParent()) {
72
0
            std::string d = dir.GetDirectory().GetCurrentBinary();
73
0
            dirTargets[d].Targets.emplace_back(t);
74
0
          }
75
0
        }
76
0
      }
77
0
      dirTarget.Targets.emplace_back(t);
78
0
    }
79
80
    // The directory-level rule should depend on the directory-level
81
    // rules of the subdirectories.
82
0
    for (cmStateSnapshot const& state : lg->GetStateSnapshot().GetChildren()) {
83
0
      DirectoryTarget::Dir d;
84
0
      d.Path = state.GetDirectory().GetCurrentBinary();
85
0
      d.ExcludeFromAll =
86
0
        state.GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL");
87
0
      dirTarget.Children.emplace_back(std::move(d));
88
0
    }
89
0
  }
90
91
0
  return dirTargets;
92
0
}
93
94
bool cmGlobalCommonGenerator::IsExcludedFromAllInConfig(
95
  DirectoryTarget::Target const& t, std::string const& config)
96
0
{
97
0
  if (this->IsMultiConfig()) {
98
0
    return cm::contains(t.ExcludedFromAllInConfigs, config);
99
0
  }
100
0
  return !t.ExcludedFromAllInConfigs.empty();
101
0
}
102
103
std::string cmGlobalCommonGenerator::GetEditCacheCommand() const
104
0
{
105
  // If generating for an extra IDE, the edit_cache target cannot
106
  // launch a terminal-interactive tool, so always use cmake-gui.
107
0
  if (!this->GetExtraGeneratorName().empty()) {
108
0
    return cmSystemTools::GetCMakeGUICommand();
109
0
  }
110
111
  // Use an internal cache entry to track the latest dialog used
112
  // to edit the cache, and use that for the edit_cache target.
113
0
  cmake* cm = this->GetCMakeInstance();
114
0
  std::string editCacheCommand = cm->GetCMakeEditCommand();
115
0
  if (!cm->GetCacheDefinition("CMAKE_EDIT_COMMAND") ||
116
0
      !editCacheCommand.empty()) {
117
0
    if (this->SupportsDirectConsole() && editCacheCommand.empty()) {
118
0
      editCacheCommand = cmSystemTools::GetCMakeCursesCommand();
119
0
    }
120
0
    if (editCacheCommand.empty()) {
121
0
      editCacheCommand = cmSystemTools::GetCMakeGUICommand();
122
0
    }
123
0
    if (!editCacheCommand.empty()) {
124
0
      cm->AddCacheEntry("CMAKE_EDIT_COMMAND", editCacheCommand,
125
0
                        "Path to cache edit program executable.",
126
0
                        cmStateEnums::INTERNAL);
127
0
    }
128
0
  }
129
0
  cmValue edit_cmd = cm->GetCacheDefinition("CMAKE_EDIT_COMMAND");
130
0
  return edit_cmd ? *edit_cmd : std::string();
131
0
}
132
133
void cmGlobalCommonGenerator::RemoveUnknownClangTidyExportFixesFiles() const
134
0
{
135
0
  for (auto const& dir : this->ClangTidyExportFixesDirs) {
136
0
    cmsys::Glob g;
137
0
    g.SetRecurse(true);
138
0
    g.SetListDirs(false);
139
0
    g.FindFiles(cmStrCat(dir, "/*.yaml"));
140
0
    for (auto const& file : g.GetFiles()) {
141
0
      if (!this->ClangTidyExportFixesFiles.count(file) &&
142
0
          !std::any_of(this->ClangTidyExportFixesFiles.begin(),
143
0
                       this->ClangTidyExportFixesFiles.end(),
144
0
                       [&file](std::string const& knownFile) -> bool {
145
0
                         return cmSystemTools::SameFile(file, knownFile);
146
0
                       })) {
147
0
        cmSystemTools::RemoveFile(file);
148
0
      }
149
0
    }
150
0
  }
151
0
}