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