forked from qt-creator/qt-creator
CMakePM: Presets: Add ability to register a Debugger via "vendor" field
This adds "Debugger" as a dependency for the CMake Project Manager. The "vendor" field of a configurePreset can look like: ``` "vendor": { "qt.io/QtCreator/1.0": { "debugger": "C:/Qt/Tools/mingw1120_64/bin/gdb.exe" } } } ``` or with all the DebugItem details as: ``` "vendor": { "qt.io/QtCreator/1.0": { "debugger": { "DisplayName": "GNU gdb 11.2.0 for MinGW 11.2.0 64-bit", "Abis": ["x86-windows-msys-pe-64bit"], "Binary": "C:/Qt/Tools/mingw1120_64/bin/gdb.exe", "EngineType": 1, "Version": "11.2.0" } } } ``` Fixes: QTCREATORBUG-30836 Change-Id: Ia89ff29ce5fad713ee8617477ec798bd86f2f811 Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
@@ -48,7 +48,6 @@ add_subdirectory(autotoolsprojectmanager)
|
||||
add_subdirectory(bazaar)
|
||||
add_subdirectory(beautifier)
|
||||
add_subdirectory(clearcase)
|
||||
add_subdirectory(cmakeprojectmanager)
|
||||
add_subdirectory(cvs)
|
||||
add_subdirectory(designer)
|
||||
add_subdirectory(docker)
|
||||
@@ -80,6 +79,7 @@ if (WITH_QMLDESIGNER)
|
||||
endif()
|
||||
add_subdirectory(python)
|
||||
add_subdirectory(clangformat)
|
||||
add_subdirectory(cmakeprojectmanager)
|
||||
|
||||
# Level 7:
|
||||
add_subdirectory(android)
|
||||
|
@@ -1,7 +1,7 @@
|
||||
add_qtc_plugin(CMakeProjectManager
|
||||
PLUGIN_CLASS CMakeProjectPlugin
|
||||
DEPENDS QmlJS
|
||||
PLUGIN_DEPENDS Core CppEditor ProjectExplorer TextEditor QtSupport
|
||||
PLUGIN_DEPENDS Core CppEditor Debugger ProjectExplorer TextEditor QtSupport
|
||||
SYSTEM_INCLUDES 3dparty/cmake
|
||||
SOURCES
|
||||
builddirparameters.cpp builddirparameters.h
|
||||
|
@@ -12,6 +12,9 @@
|
||||
#include "presetsmacros.h"
|
||||
|
||||
#include <coreplugin/messagemanager.h>
|
||||
#include <debugger/debuggeritem.h>
|
||||
#include <debugger/debuggeritemmanager.h>
|
||||
#include <debugger/debuggerkitaspect.h>
|
||||
|
||||
#include <projectexplorer/buildinfo.h>
|
||||
#include <projectexplorer/kitaspects.h>
|
||||
@@ -30,7 +33,9 @@
|
||||
|
||||
#include <QApplication>
|
||||
#include <QLoggingCategory>
|
||||
#include <QUuid>
|
||||
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace QtSupport;
|
||||
using namespace Utils;
|
||||
@@ -60,6 +65,7 @@ struct DirectoryData
|
||||
FilePath sysroot;
|
||||
QtProjectImporter::QtVersionData qt;
|
||||
QVector<ToolchainDescription> toolchains;
|
||||
QVariant debugger;
|
||||
};
|
||||
|
||||
static FilePaths scanDirectory(const FilePath &path, const QString &prefix)
|
||||
@@ -205,6 +211,48 @@ FilePaths CMakeProjectImporter::presetCandidates()
|
||||
return candidates;
|
||||
}
|
||||
|
||||
static QVariant findOrRegisterDebugger(
|
||||
Environment &env, const std::optional<QVariantMap> &vendor, const QString &presetName)
|
||||
{
|
||||
const QString debuggerKey("debugger");
|
||||
if (!vendor || !vendor.value().contains(debuggerKey))
|
||||
return {};
|
||||
|
||||
const QVariant debuggerVariant = vendor.value().value(debuggerKey);
|
||||
FilePath debuggerPath = FilePath::fromUserInput(debuggerVariant.toString());
|
||||
if (!debuggerPath.isEmpty()) {
|
||||
if (debuggerPath.isRelativePath())
|
||||
debuggerPath = env.searchInPath(debuggerPath.fileName());
|
||||
|
||||
const QString mainName = Tr::tr("CMake Preset (%1) %2 Debugger");
|
||||
DebuggerItem debugger;
|
||||
debugger.setCommand(debuggerPath);
|
||||
debugger.setUnexpandedDisplayName(
|
||||
mainName.arg(presetName).arg(debuggerPath.completeBaseName()));
|
||||
debugger.setAutoDetected(false);
|
||||
QString errorMessage;
|
||||
debugger.reinitializeFromFile(&errorMessage, &env);
|
||||
if (!errorMessage.isEmpty())
|
||||
qCWarning(cmInputLog()) << "Error reinitializing debugger" << debuggerPath.toString()
|
||||
<< "Error:" << errorMessage;
|
||||
|
||||
return DebuggerItemManager::registerDebugger(debugger);
|
||||
} else {
|
||||
auto debuggerMap = debuggerVariant.toMap();
|
||||
if (debuggerMap.isEmpty())
|
||||
return {};
|
||||
|
||||
// Manually create an Id, otrhewise the Kit will not have a debugger set
|
||||
if (!debuggerMap.contains("Id"))
|
||||
debuggerMap.insert("Id", QUuid::createUuid().toString());
|
||||
|
||||
auto store = storeFromMap(debuggerMap);
|
||||
DebuggerItem debugger(store);
|
||||
|
||||
return DebuggerItemManager::registerDebugger(debugger);
|
||||
}
|
||||
}
|
||||
|
||||
Target *CMakeProjectImporter::preferredTarget(const QList<Target *> &possibleTargets)
|
||||
{
|
||||
for (Kit *kit : m_project->oldPresetKits()) {
|
||||
@@ -835,6 +883,8 @@ QList<void *> CMakeProjectImporter::examineDirectory(const FilePath &importPath,
|
||||
|
||||
data->hasQmlDebugging = CMakeBuildConfiguration::hasQmlDebugging(config);
|
||||
|
||||
data->debugger = findOrRegisterDebugger(env, configurePreset.vendor, configurePreset.name);
|
||||
|
||||
QByteArrayList buildConfigurationTypes = {cache.valueOf("CMAKE_BUILD_TYPE")};
|
||||
if (buildConfigurationTypes.front().isEmpty()) {
|
||||
buildConfigurationTypes.clear();
|
||||
@@ -1055,6 +1105,9 @@ Kit *CMakeProjectImporter::createKit(void *directoryData) const
|
||||
if (!data->cmakePreset.isEmpty())
|
||||
ensureBuildDirectory(*data, k);
|
||||
|
||||
if (data->debugger.isValid())
|
||||
DebuggerKitAspect::setDebugger(k, data->debugger);
|
||||
|
||||
qCInfo(cmInputLog) << "Temporary Kit created.";
|
||||
});
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@ QtcPlugin {
|
||||
|
||||
Depends { name: "Core" }
|
||||
Depends { name: "CppEditor" }
|
||||
Depends { name: "Debugger" }
|
||||
Depends { name: "QmlJS" }
|
||||
Depends { name: "ProjectExplorer" }
|
||||
Depends { name: "TextEditor" }
|
||||
|
@@ -148,6 +148,30 @@ std::optional<PresetsDetails::Condition> parseCondition(const QJsonValue &jsonVa
|
||||
return condition;
|
||||
}
|
||||
|
||||
bool parseVendor(const QJsonValue &jsonValue, std::optional<QVariantMap> &vendorSettings)
|
||||
{
|
||||
// The whole section is optional
|
||||
if (jsonValue.isUndefined())
|
||||
return true;
|
||||
if (!jsonValue.isObject())
|
||||
return false;
|
||||
|
||||
const QJsonObject object = jsonValue.toObject();
|
||||
const QJsonValue qtIo = object.value("qt.io/QtCreator/1.0");
|
||||
if (qtIo.isUndefined())
|
||||
return true;
|
||||
if (!qtIo.isObject())
|
||||
return false;
|
||||
|
||||
const QJsonObject qtIoObject = qtIo.toObject();
|
||||
vendorSettings = QVariantMap();
|
||||
for (const QString &settingKey : qtIoObject.keys()) {
|
||||
const QJsonValue settingValue = qtIoObject.value(settingKey);
|
||||
vendorSettings->insert(settingKey, settingValue.toVariant());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parseConfigurePresets(const QJsonValue &jsonValue,
|
||||
QList<PresetsDetails::ConfigurePreset> &configurePresets,
|
||||
const Utils::FilePath &fileDir)
|
||||
@@ -188,6 +212,9 @@ bool parseConfigurePresets(const QJsonValue &jsonValue,
|
||||
if (object.contains("condition"))
|
||||
preset.condition = parseCondition(object.value("condition"));
|
||||
|
||||
if (object.contains("vendor"))
|
||||
parseVendor(object.value("vendor"), preset.vendor);
|
||||
|
||||
if (object.contains("displayName"))
|
||||
preset.displayName = object.value("displayName").toString();
|
||||
if (object.contains("description"))
|
||||
@@ -378,6 +405,9 @@ bool parseBuildPresets(const QJsonValue &jsonValue,
|
||||
if (object.contains("condition"))
|
||||
preset.condition = parseCondition(object.value("condition"));
|
||||
|
||||
if (object.contains("vendor"))
|
||||
parseVendor(object.value("vendor"), preset.vendor);
|
||||
|
||||
if (object.contains("displayName"))
|
||||
preset.displayName = object.value("displayName").toString();
|
||||
if (object.contains("description"))
|
||||
@@ -435,30 +465,6 @@ bool parseBuildPresets(const QJsonValue &jsonValue,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parseVendor(const QJsonValue &jsonValue, std::optional<QVariantMap> &vendorSettings)
|
||||
{
|
||||
// The whole section is optional
|
||||
if (jsonValue.isUndefined())
|
||||
return true;
|
||||
if (!jsonValue.isObject())
|
||||
return false;
|
||||
|
||||
const QJsonObject object = jsonValue.toObject();
|
||||
const QJsonValue qtIo = object.value("qt.io/QtCreator/1.0");
|
||||
if (qtIo.isUndefined())
|
||||
return true;
|
||||
if (!qtIo.isObject())
|
||||
return false;
|
||||
|
||||
const QJsonObject qtIoObject = qtIo.toObject();
|
||||
vendorSettings = QVariantMap();
|
||||
for (const QString &settingKey : qtIoObject.keys()) {
|
||||
const QJsonValue settingValue = qtIoObject.value(settingKey);
|
||||
vendorSettings->insert(settingKey, settingValue.toVariant());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const PresetsData &PresetsParser::presetsData() const
|
||||
{
|
||||
return m_presetsData;
|
||||
@@ -535,10 +541,9 @@ bool PresetsParser::parse(const Utils::FilePath &jsonFile, QString &errorMessage
|
||||
return true;
|
||||
}
|
||||
|
||||
static QHash<QString, QString> merge(const QHash<QString, QString> &first,
|
||||
const QHash<QString, QString> &second)
|
||||
static QVariantMap merge(const QVariantMap &first, const QVariantMap &second)
|
||||
{
|
||||
QHash<QString, QString> result = first;
|
||||
QVariantMap result = first;
|
||||
for (auto it = second.constKeyValueBegin(); it != second.constKeyValueEnd(); ++it) {
|
||||
result[it->first] = it->second;
|
||||
}
|
||||
|
@@ -94,7 +94,7 @@ public:
|
||||
std::optional<bool> hidden = false;
|
||||
std::optional<QStringList> inherits;
|
||||
std::optional<Condition> condition;
|
||||
std::optional<QHash<QString, QString>> vendor;
|
||||
std::optional<QVariantMap> vendor;
|
||||
std::optional<QString> displayName;
|
||||
std::optional<QString> description;
|
||||
std::optional<QString> generator;
|
||||
@@ -120,7 +120,7 @@ public:
|
||||
std::optional<bool> hidden = false;
|
||||
std::optional<QStringList> inherits;
|
||||
std::optional<Condition> condition;
|
||||
std::optional<QHash<QString, QString>> vendor;
|
||||
std::optional<QVariantMap> vendor;
|
||||
std::optional<QString> displayName;
|
||||
std::optional<QString> description;
|
||||
std::optional<Utils::Environment> environment;
|
||||
|
Reference in New Issue
Block a user