|
|
|
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
|
|
file Copyright.txt 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 "cmLocalGenerator.h"
|
|
|
|
#include "cmMakefile.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 (const auto& lg : this->LocalGenerators) {
|
|
|
|
std::string const& currentBinaryDir(
|
|
|
|
lg->GetStateSnapshot().GetDirectory().GetCurrentBinary());
|
|
|
|
DirectoryTarget& dirTarget = dirTargets[currentBinaryDir];
|
|
|
|
dirTarget.LG = lg.get();
|
|
|
|
const std::vector<std::string>& configs =
|
|
|
|
lg->GetMakefile()->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
|
|
|
|
|
|
|
|
// The directory-level rule should depend on the target-level rules
|
|
|
|
// for all targets in the directory.
|
|
|
|
for (const auto& gt : lg->GetGeneratorTargets()) {
|
|
|
|
cmStateEnums::TargetType const type = gt->GetType();
|
|
|
|
if (type == cmStateEnums::GLOBAL_TARGET || !gt->IsInBuildSystem()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
DirectoryTarget::Target t;
|
|
|
|
t.GT = gt.get();
|
|
|
|
const std::string EXCLUDE_FROM_ALL("EXCLUDE_FROM_ALL");
|
|
|
|
if (cmValue exclude = gt->GetProperty(EXCLUDE_FROM_ALL)) {
|
|
|
|
for (const std::string& 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 const& 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(
|
|
|
|
const DirectoryTarget::Target& t, const std::string& 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](const std::string& knownFile) -> bool {
|
|
|
|
return cmSystemTools::SameFile(file, knownFile);
|
|
|
|
})) {
|
|
|
|
cmSystemTools::RemoveFile(file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|