Files
CMake/Source/cmDebuggerVariablesHelper.cxx
Marc Chevrier dee8799d16 FileSet management: Introduce dedicated classes for generation
To manage the generation step, introduce cmGeneratorFileSet and
cmGeneratorFileSets classes.
These reorganizations of the code are done in preparation of the
implementation of SOURCES file set type as well as user's file set types.

Issues: #27550, #27383
2026-02-19 17:35:56 +01:00

639 lines
24 KiB
C++

/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmDebuggerVariablesHelper.h"
#include <algorithm>
#include <cstddef>
#include <functional>
#include <iomanip>
#include <iterator>
#include <map>
#include <sstream>
#include "cm_codecvt_Encoding.hxx"
#include "cmDebuggerStackFrame.h"
#include "cmDebuggerVariables.h"
#include "cmFileSet.h"
#include "cmFileSetMetadata.h"
#include "cmGlobalGenerator.h"
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmPropertyMap.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
#include "cmTest.h"
#include "cmValue.h"
#include "cmake.h"
namespace cmDebugger {
std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::Create(
std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
std::string const& name, bool supportsVariableType,
cmPolicies::PolicyMap const& policyMap)
{
static std::map<cmPolicies::PolicyStatus, std::string> policyStatusString = {
{ cmPolicies::PolicyStatus::OLD, "OLD" },
{ cmPolicies::PolicyStatus::WARN, "WARN" },
{ cmPolicies::PolicyStatus::NEW, "NEW" },
};
return std::make_shared<cmDebuggerVariables>(
variablesManager, name, supportsVariableType, [=]() {
std::vector<cmDebuggerVariableEntry> ret;
ret.reserve(cmPolicies::CMPCOUNT);
for (int i = 0; i < cmPolicies::CMPCOUNT; ++i) {
if (policyMap.IsDefined(static_cast<cmPolicies::PolicyID>(i))) {
auto status = policyMap.Get(static_cast<cmPolicies::PolicyID>(i));
std::ostringstream ss;
ss << "CMP" << std::setfill('0') << std::setw(4) << i;
ret.emplace_back(ss.str(), policyStatusString[status]);
}
}
return ret;
});
}
std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
std::string const& name, bool supportsVariableType,
std::vector<std::pair<std::string, std::string>> const& list)
{
if (list.empty()) {
return {};
}
auto listVariables = std::make_shared<cmDebuggerVariables>(
variablesManager, name, supportsVariableType, [=]() {
std::vector<cmDebuggerVariableEntry> ret;
ret.reserve(list.size());
for (auto const& kv : list) {
ret.emplace_back(kv.first, kv.second);
}
return ret;
});
listVariables->SetValue(std::to_string(list.size()));
return listVariables;
}
std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
std::string const& name, bool supportsVariableType, cmBTStringRange entries)
{
if (entries.empty()) {
return {};
}
auto sourceEntries = std::make_shared<cmDebuggerVariables>(
variablesManager, name, supportsVariableType);
for (auto const& entry : entries) {
auto arrayVariables = std::make_shared<cmDebuggerVariables>(
variablesManager, entry.Value, supportsVariableType, [=]() {
cmList items{ entry.Value };
std::vector<cmDebuggerVariableEntry> ret;
ret.reserve(items.size());
int i = 0;
for (std::string const& item : items) {
ret.emplace_back(cmStrCat('[', i++, ']'), item);
}
return ret;
});
arrayVariables->SetEnableSorting(false);
sourceEntries->AddSubVariables(arrayVariables);
}
sourceEntries->SetValue(std::to_string(entries.size()));
return sourceEntries;
}
std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
std::string const& name, bool supportsVariableType,
std::set<std::string> const& values)
{
if (values.empty()) {
return {};
}
auto arrayVariables = std::make_shared<cmDebuggerVariables>(
variablesManager, name, supportsVariableType, [=]() {
std::vector<cmDebuggerVariableEntry> ret;
ret.reserve(values.size());
int i = 0;
for (std::string const& value : values) {
ret.emplace_back(cmStrCat('[', i++, ']'), value);
}
return ret;
});
arrayVariables->SetValue(std::to_string(values.size()));
arrayVariables->SetEnableSorting(false);
return arrayVariables;
}
std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
std::string const& name, bool supportsVariableType,
std::vector<std::string> const& values)
{
if (values.empty()) {
return {};
}
auto arrayVariables = std::make_shared<cmDebuggerVariables>(
variablesManager, name, supportsVariableType, [=]() {
std::vector<cmDebuggerVariableEntry> ret;
ret.reserve(values.size());
int i = 0;
for (std::string const& value : values) {
ret.emplace_back(cmStrCat('[', i++, ']'), value);
}
return ret;
});
arrayVariables->SetValue(std::to_string(values.size()));
arrayVariables->SetEnableSorting(false);
return arrayVariables;
}
std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
std::string const& name, bool supportsVariableType,
std::vector<BT<std::string>> const& list)
{
if (list.empty()) {
return {};
}
auto variables = std::make_shared<cmDebuggerVariables>(
variablesManager, name, supportsVariableType, [=]() {
std::vector<cmDebuggerVariableEntry> ret;
ret.reserve(list.size());
int i = 0;
for (auto const& item : list) {
ret.emplace_back(cmStrCat('[', i++, ']'), item.Value);
}
return ret;
});
variables->SetValue(std::to_string(list.size()));
variables->SetEnableSorting(false);
return variables;
}
std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
std::string const& name, bool supportsVariableType, cmFileSet* fileSet)
{
if (!fileSet) {
return {};
}
static auto visibilityString =
[](cm::FileSetMetadata::Visibility visibility) {
switch (visibility) {
case cm::FileSetMetadata::Visibility::Private:
return "Private";
case cm::FileSetMetadata::Visibility::Public:
return "Public";
case cm::FileSetMetadata::Visibility::Interface:
return "Interface";
default:
return "Unknown";
}
};
auto variables = std::make_shared<cmDebuggerVariables>(
variablesManager, name, supportsVariableType, [=]() {
std::vector<cmDebuggerVariableEntry> ret{
{ "Name", fileSet->GetName() },
{ "Type", fileSet->GetType() },
{ "Visibility", visibilityString(fileSet->GetVisibility()) },
};
return ret;
});
variables->AddSubVariables(CreateIfAny(variablesManager, "Directories",
supportsVariableType,
fileSet->GetDirectoryEntries()));
variables->AddSubVariables(CreateIfAny(variablesManager, "Files",
supportsVariableType,
fileSet->GetFileEntries()));
return variables;
}
std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
std::string const& name, bool supportsVariableType,
std::vector<cmFileSet*> const& fileSets)
{
if (fileSets.empty()) {
return {};
}
auto fileSetsVariables = std::make_shared<cmDebuggerVariables>(
variablesManager, name, supportsVariableType);
for (auto const& fileSet : fileSets) {
fileSetsVariables->AddSubVariables(CreateIfAny(
variablesManager, fileSet->GetName(), supportsVariableType, fileSet));
}
return fileSetsVariables;
}
std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
std::string const& name, bool supportsVariableType,
std::vector<cmTarget*> const& targets)
{
if (targets.empty()) {
return {};
}
auto targetsVariables = std::make_shared<cmDebuggerVariables>(
variablesManager, name, supportsVariableType);
for (auto const& target : targets) {
auto targetVariables = std::make_shared<cmDebuggerVariables>(
variablesManager, target->GetName(), supportsVariableType, [=]() {
std::vector<cmDebuggerVariableEntry> ret = {
{ "InstallPath", target->GetInstallPath() },
{ "IsAIX", target->IsAIX() },
{ "IsAndroidGuiExecutable", target->IsAndroidGuiExecutable() },
{ "IsAppBundleOnApple", target->IsAppBundleOnApple() },
{ "IsDLLPlatform", target->IsDLLPlatform() },
{ "IsExecutableWithExports", target->IsExecutableWithExports() },
{ "IsFrameworkOnApple", target->IsFrameworkOnApple() },
{ "IsImported", target->IsImported() },
{ "IsImportedGloballyVisible", target->IsImportedGloballyVisible() },
{ "IsPerConfig", target->IsPerConfig() },
{ "Name", target->GetName() },
{ "RuntimeInstallPath", target->GetRuntimeInstallPath() },
{ "Type", cmState::GetTargetTypeName(target->GetType()) },
};
return ret;
});
targetVariables->SetValue(cmState::GetTargetTypeName(target->GetType()));
targetVariables->AddSubVariables(Create(variablesManager, "PolicyMap",
supportsVariableType,
target->GetPolicyMap()));
targetVariables->AddSubVariables(
CreateIfAny(variablesManager, "Properties", supportsVariableType,
target->GetProperties().GetList()));
targetVariables->AddSubVariables(
CreateIfAny(variablesManager, "IncludeDirectories", supportsVariableType,
target->GetIncludeDirectoriesEntries()));
targetVariables->AddSubVariables(CreateIfAny(variablesManager, "Sources",
supportsVariableType,
target->GetSourceEntries()));
targetVariables->AddSubVariables(
CreateIfAny(variablesManager, "CompileDefinitions", supportsVariableType,
target->GetCompileDefinitionsEntries()));
targetVariables->AddSubVariables(
CreateIfAny(variablesManager, "CompileFeatures", supportsVariableType,
target->GetCompileFeaturesEntries()));
targetVariables->AddSubVariables(
CreateIfAny(variablesManager, "CompileOptions", supportsVariableType,
target->GetCompileOptionsEntries()));
targetVariables->AddSubVariables(CreateIfAny(
variablesManager, "CxxModuleSets", supportsVariableType,
target->GetFileSetsEntries(cm::FileSetMetadata::CXX_MODULES)));
targetVariables->AddSubVariables(
CreateIfAny(variablesManager, "HeaderSets", supportsVariableType,
target->GetFileSetsEntries(cm::FileSetMetadata::HEADERS)));
targetVariables->AddSubVariables(CreateIfAny(
variablesManager, "InterfaceHeaderSets", supportsVariableType,
target->GetInterfaceFileSetsEntries(cm::FileSetMetadata::HEADERS)));
targetVariables->AddSubVariables(
CreateIfAny(variablesManager, "LinkDirectories", supportsVariableType,
target->GetLinkDirectoriesEntries()));
targetVariables->AddSubVariables(CreateIfAny(
variablesManager, "LinkImplementations", supportsVariableType,
target->GetLinkImplementationEntries()));
targetVariables->AddSubVariables(CreateIfAny(
variablesManager, "LinkInterfaceDirects", supportsVariableType,
target->GetLinkInterfaceDirectEntries()));
targetVariables->AddSubVariables(CreateIfAny(
variablesManager, "LinkInterfaceDirectExcludes", supportsVariableType,
target->GetLinkInterfaceDirectExcludeEntries()));
targetVariables->AddSubVariables(
CreateIfAny(variablesManager, "LinkInterfaces", supportsVariableType,
target->GetLinkInterfaceEntries()));
targetVariables->AddSubVariables(
CreateIfAny(variablesManager, "LinkOptions", supportsVariableType,
target->GetLinkOptionsEntries()));
targetVariables->AddSubVariables(CreateIfAny(
variablesManager, "SystemIncludeDirectories", supportsVariableType,
target->GetSystemIncludeDirectories()));
targetVariables->AddSubVariables(CreateIfAny(variablesManager, "Makefile",
supportsVariableType,
target->GetMakefile()));
targetVariables->AddSubVariables(
CreateIfAny(variablesManager, "GlobalGenerator", supportsVariableType,
target->GetGlobalGenerator()));
std::vector<cmFileSet*> allFileSets;
auto allFileSetNames = target->GetAllFileSetNames();
allFileSets.reserve(allFileSetNames.size());
for (auto const& fileSetName : allFileSetNames) {
allFileSets.emplace_back(target->GetFileSet(fileSetName));
}
targetVariables->AddSubVariables(CreateIfAny(
variablesManager, "AllFileSets", supportsVariableType, allFileSets));
std::vector<cmFileSet*> allInterfaceFileSets;
auto allInterfaceFileSetNames = target->GetAllInterfaceFileSets();
allInterfaceFileSets.reserve(allInterfaceFileSetNames.size());
for (auto const& interfaceFileSetName : allInterfaceFileSetNames) {
allInterfaceFileSets.emplace_back(
target->GetFileSet(interfaceFileSetName));
}
targetVariables->AddSubVariables(
CreateIfAny(variablesManager, "AllInterfaceFileSets",
supportsVariableType, allInterfaceFileSets));
targetVariables->SetIgnoreEmptyStringEntries(true);
targetsVariables->AddSubVariables(targetVariables);
}
targetsVariables->SetValue(std::to_string(targets.size()));
return targetsVariables;
}
std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::Create(
std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
std::string const& name, bool supportsVariableType,
std::shared_ptr<cmDebuggerStackFrame> const& frame)
{
auto variables = std::make_shared<cmDebuggerVariables>(
variablesManager, name, supportsVariableType, [=]() {
return std::vector<cmDebuggerVariableEntry>{ { "CurrentLine",
frame->GetLine() } };
});
auto closureKeys = frame->GetMakefile()->GetStateSnapshot().ClosureKeys();
auto locals = std::make_shared<cmDebuggerVariables>(
variablesManager, "Locals", supportsVariableType, [=]() {
std::vector<cmDebuggerVariableEntry> ret;
ret.reserve(closureKeys.size());
for (auto const& key : closureKeys) {
ret.emplace_back(
key, frame->GetMakefile()->GetStateSnapshot().GetDefinition(key));
}
return ret;
});
locals->SetValue(std::to_string(closureKeys.size()));
variables->AddSubVariables(locals);
std::function<bool(std::string const&)> isDirectory =
[](std::string const& key) {
size_t pos1 = key.rfind("_DIR");
size_t pos2 = key.rfind("_DIRECTORY");
return !((pos1 == std::string::npos || pos1 != key.size() - 4) &&
(pos2 == std::string::npos || pos2 != key.size() - 10));
};
auto directorySize =
std::count_if(closureKeys.begin(), closureKeys.end(), isDirectory);
auto directories = std::make_shared<cmDebuggerVariables>(
variablesManager, "Directories", supportsVariableType, [=]() {
std::vector<cmDebuggerVariableEntry> ret;
ret.reserve(directorySize);
for (auto const& key : closureKeys) {
if (isDirectory(key)) {
ret.emplace_back(
key, frame->GetMakefile()->GetStateSnapshot().GetDefinition(key));
}
}
return ret;
});
directories->SetValue(std::to_string(directorySize));
variables->AddSubVariables(directories);
auto cacheVariables = std::make_shared<cmDebuggerVariables>(
variablesManager, "CacheVariables", supportsVariableType);
auto* state = frame->GetMakefile()->GetCMakeInstance()->GetState();
auto keys = state->GetCacheEntryKeys();
for (auto const& key : keys) {
auto entry = std::make_shared<cmDebuggerVariables>(
variablesManager,
cmStrCat(key, ':',
cmState::CacheEntryTypeToString(state->GetCacheEntryType(key))),
supportsVariableType, [=]() {
std::vector<cmDebuggerVariableEntry> ret;
auto properties = state->GetCacheEntryPropertyList(key);
ret.reserve(properties.size() + 2);
for (auto const& propertyName : properties) {
ret.emplace_back(propertyName,
state->GetCacheEntryProperty(key, propertyName));
}
ret.emplace_back(
"TYPE",
cmState::CacheEntryTypeToString(state->GetCacheEntryType(key)));
ret.emplace_back("VALUE", state->GetCacheEntryValue(key));
return ret;
});
entry->SetValue(state->GetCacheEntryValue(key));
cacheVariables->AddSubVariables(entry);
}
cacheVariables->SetValue(std::to_string(keys.size()));
variables->AddSubVariables(cacheVariables);
auto targetVariables =
CreateIfAny(variablesManager, "Targets", supportsVariableType,
frame->GetMakefile()->GetOrderedTargets());
variables->AddSubVariables(targetVariables);
std::vector<cmTest*> tests;
frame->GetMakefile()->GetTests(
frame->GetMakefile()->GetDefaultConfiguration(), tests);
variables->AddSubVariables(
CreateIfAny(variablesManager, "Tests", supportsVariableType, tests));
return variables;
}
std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
std::string const& name, bool supportsVariableType, cmTest* test)
{
if (!test) {
return {};
}
auto variables = std::make_shared<cmDebuggerVariables>(
variablesManager, name, supportsVariableType, [=]() {
std::vector<cmDebuggerVariableEntry> ret{
{ "CommandExpandLists", test->GetCommandExpandLists() },
{ "Name", test->GetName() },
{ "OldStyle", test->GetOldStyle() },
};
return ret;
});
variables->AddSubVariables(CreateIfAny(
variablesManager, "Command", supportsVariableType, test->GetCommand()));
variables->AddSubVariables(CreateIfAny(variablesManager, "Properties",
supportsVariableType,
test->GetProperties().GetList()));
return variables;
}
std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
std::string const& name, bool supportsVariableType,
std::vector<cmTest*> const& tests)
{
if (tests.empty()) {
return {};
}
auto variables = std::make_shared<cmDebuggerVariables>(
variablesManager, name, supportsVariableType);
for (auto const& test : tests) {
variables->AddSubVariables(CreateIfAny(variablesManager, test->GetName(),
supportsVariableType, test));
}
variables->SetValue(std::to_string(tests.size()));
return variables;
}
std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
std::string const& name, bool supportsVariableType, cmMakefile* mf)
{
if (!mf) {
return {};
}
auto AppleSDKTypeString = [&](cmMakefile::AppleSDK sdk) {
switch (sdk) {
case cmMakefile::AppleSDK::MacOS:
return "MacOS";
case cmMakefile::AppleSDK::IPhoneOS:
return "IPhoneOS";
case cmMakefile::AppleSDK::IPhoneSimulator:
return "IPhoneSimulator";
case cmMakefile::AppleSDK::AppleTVOS:
return "AppleTVOS";
case cmMakefile::AppleSDK::AppleTVSimulator:
return "AppleTVSimulator";
default:
return "Unknown";
}
};
auto variables = std::make_shared<cmDebuggerVariables>(
variablesManager, name, supportsVariableType, [=]() {
std::vector<cmDebuggerVariableEntry> ret = {
{ "DefineFlags", mf->GetDefineFlags() },
{ "DirectoryId", mf->GetDirectoryId().String },
{ "IsRootMakefile", mf->IsRootMakefile() },
{ "HomeDirectory", mf->GetHomeDirectory() },
{ "HomeOutputDirectory", mf->GetHomeOutputDirectory() },
{ "CurrentSourceDirectory", mf->GetCurrentSourceDirectory() },
{ "CurrentBinaryDirectory", mf->GetCurrentBinaryDirectory() },
{ "PlatformIs32Bit", mf->PlatformIs32Bit() },
{ "PlatformIs64Bit", mf->PlatformIs64Bit() },
{ "PlatformIsx32", mf->PlatformIsx32() },
{ "AppleSDKType", AppleSDKTypeString(mf->GetAppleSDKType()) },
{ "PlatformIsAppleEmbedded", mf->PlatformIsAppleEmbedded() }
};
return ret;
});
variables->AddSubVariables(CreateIfAny(
variablesManager, "ListFiles", supportsVariableType, mf->GetListFiles()));
variables->AddSubVariables(CreateIfAny(variablesManager, "OutputFiles",
supportsVariableType,
mf->GetOutputFiles()));
variables->SetIgnoreEmptyStringEntries(true);
variables->SetValue(mf->GetDirectoryId().String);
return variables;
}
std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
std::string const& name, bool supportsVariableType, cmGlobalGenerator* gen)
{
if (!gen) {
return {};
}
auto makeFileEncodingString = [](codecvt_Encoding encoding) {
switch (encoding) {
case codecvt_Encoding::None:
return "None";
case codecvt_Encoding::UTF8:
return "UTF8";
case codecvt_Encoding::UTF8_WITH_BOM:
return "UTF8_WITH_BOM";
case codecvt_Encoding::ANSI:
return "ANSI";
case codecvt_Encoding::ConsoleOutput:
return "ConsoleOutput";
default:
return "Unknown";
}
};
auto variables = std::make_shared<cmDebuggerVariables>(
variablesManager, name, supportsVariableType, [=]() {
std::vector<cmDebuggerVariableEntry> ret = {
{ "AllTargetName", gen->GetAllTargetName() },
{ "CleanTargetName", gen->GetCleanTargetName() },
{ "EditCacheCommand", gen->GetEditCacheCommand() },
{ "EditCacheTargetName", gen->GetEditCacheTargetName() },
{ "ExtraGeneratorName", gen->GetExtraGeneratorName() },
{ "ForceUnixPaths", gen->GetForceUnixPaths() },
{ "InstallLocalTargetName", gen->GetInstallLocalTargetName() },
{ "InstallStripTargetName", gen->GetInstallStripTargetName() },
{ "InstallTargetName", gen->GetInstallTargetName() },
{ "IsMultiConfig", gen->IsMultiConfig() },
{ "Name", gen->GetName() },
{ "MakefileEncoding",
makeFileEncodingString(gen->GetMakefileEncoding()) },
{ "PackageSourceTargetName", gen->GetPackageSourceTargetName() },
{ "PackageTargetName", gen->GetPackageTargetName() },
{ "PreinstallTargetName", gen->GetPreinstallTargetName() },
{ "NeedSymbolicMark", gen->GetNeedSymbolicMark() },
{ "RebuildCacheTargetName", gen->GetRebuildCacheTargetName() },
{ "TestTargetName", gen->GetTestTargetName() },
{ "UseLinkScript", gen->GetUseLinkScript() },
};
return ret;
});
if (auto const* ic = gen->GetInstallComponents()) {
variables->AddSubVariables(CreateIfAny(
variablesManager, "InstallComponents", supportsVariableType, *ic));
}
variables->SetIgnoreEmptyStringEntries(true);
variables->SetValue(gen->GetName());
return variables;
}
} // namespace cmDebugger