diff options
author | Friedemann Kleint <[email protected]> | 2012-09-05 14:56:08 +0200 |
---|---|---|
committer | Friedemann Kleint <[email protected]> | 2012-09-05 15:49:11 +0200 |
commit | af6bbc442ecb60d2ddcb37752215f6a2e3e5bea4 (patch) | |
tree | 1819ebb9f2fea4bdbb30e96c2783c6508ebc5726 /src/plugins/debugger | |
parent | 824d04252e1c2d461dadc09c657d2c896b0c74ad (diff) |
Add debugger engine type to configuration.
Introduce a struct DebuggerItem as a debugger configuration
item, containing debugger engine type and binary. Store
information as a variant map. Add a combo box.
Remove engine guessing logic. Parts of it are still required
when checking the suggested debugger from the SDK.
Split error checking to be able to do a quick error check
and find only valid profiles in the matchers.
Pass on errors up to RunControl::create().
Change-Id: I08653e2a76ca2c371701082f8173b0b8f8ed462e
Reviewed-by: Tobias Hunger <[email protected]>
Diffstat (limited to 'src/plugins/debugger')
-rw-r--r-- | src/plugins/debugger/debuggerdialogs.cpp | 3 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerkitconfigwidget.cpp | 109 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerkitconfigwidget.h | 20 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerkitinformation.cpp | 215 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerkitinformation.h | 41 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerplugin.cpp | 68 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerrunner.cpp | 87 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerstartparameters.h | 4 | ||||
-rw-r--r-- | src/plugins/debugger/gdb/startgdbserverdialog.cpp | 2 | ||||
-rw-r--r-- | src/plugins/debugger/lldb/lldbenginehost.cpp | 1 |
10 files changed, 370 insertions, 180 deletions
diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp index 893cbb13f09..504dcd338ee 100644 --- a/src/plugins/debugger/debuggerdialogs.cpp +++ b/src/plugins/debugger/debuggerdialogs.cpp @@ -374,8 +374,7 @@ bool StartApplicationDialog::run(QWidget *parent, QSettings *settings, DebuggerS } Kit *kit = dialog.d->kitChooser->currentKit(); - QTC_ASSERT(kit, return false); - fillParameters(sp, kit); + QTC_ASSERT(kit && fillParameters(sp, kit), return false); sp->executable = newParameters.localExecutable; sp->displayName = newParameters.displayName(); diff --git a/src/plugins/debugger/debuggerkitconfigwidget.cpp b/src/plugins/debugger/debuggerkitconfigwidget.cpp index 96cf2b04a75..6ceb478fb2d 100644 --- a/src/plugins/debugger/debuggerkitconfigwidget.cpp +++ b/src/plugins/debugger/debuggerkitconfigwidget.cpp @@ -29,7 +29,6 @@ **************************************************************************/ #include "debuggerkitconfigwidget.h" - #include "debuggerkitinformation.h" #include <projectexplorer/abi.h> @@ -48,6 +47,8 @@ #include <QHBoxLayout> #include <QPushButton> #include <QVBoxLayout> +#include <QLabel> +#include <QComboBox> namespace Debugger { namespace Internal { @@ -55,6 +56,7 @@ namespace Internal { static const char dgbToolsDownloadLink32C[] = "http://www.microsoft.com/whdc/devtools/debugging/installx86.Mspx"; static const char dgbToolsDownloadLink64C[] = "http://www.microsoft.com/whdc/devtools/debugging/install64bit.Mspx"; + // ----------------------------------------------------------------------- // DebuggerKitConfigWidget: // ----------------------------------------------------------------------- @@ -65,34 +67,26 @@ DebuggerKitConfigWidget::DebuggerKitConfigWidget(ProjectExplorer::Kit *k, ProjectExplorer::KitConfigWidget(parent), m_kit(k), m_info(ki), - m_chooser(new Utils::PathChooser) + m_comboBox(new QComboBox(this)), + m_label(new QLabel(this)), + m_chooser(new Utils::PathChooser(this)) { setToolTip(tr("The debugger to use for this kit.")); QVBoxLayout *layout = new QVBoxLayout(this); layout->setMargin(0); - ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(k); - if (tc && tc->targetAbi().os() == ProjectExplorer::Abi::WindowsOS - && tc->targetAbi().osFlavor() != ProjectExplorer::Abi::WindowsMSysFlavor) { - QLabel *msvcDebuggerConfigLabel = new QLabel; -#ifdef Q_OS_WIN - const bool is64bit = Utils::winIs64BitSystem(); -#else - const bool is64bit = false; -#endif - const QString link = is64bit ? QLatin1String(dgbToolsDownloadLink64C) : QLatin1String(dgbToolsDownloadLink32C); - //: Label text for path configuration. %2 is "x-bit version". - msvcDebuggerConfigLabel->setText(tr("<html><body><p>Specify the path to the " - "<a href=\"%1\">Windows Console Debugger executable</a>" - " (%2) here.</p>" - "</body></html>").arg(link, (is64bit ? tr("64-bit version") - : tr("32-bit version")))); - msvcDebuggerConfigLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); - msvcDebuggerConfigLabel->setOpenExternalLinks(true); - layout->addWidget(msvcDebuggerConfigLabel); - + m_comboBox->addItem(DebuggerKitInformation::debuggerEngineName(GdbEngineType), QVariant(int(GdbEngineType))); + if (ProjectExplorer::Abi::hostAbi().os() == ProjectExplorer::Abi::WindowsOS) { + m_comboBox->addItem(DebuggerKitInformation::debuggerEngineName(CdbEngineType), QVariant(int(CdbEngineType))); + } else { + m_comboBox->addItem(DebuggerKitInformation::debuggerEngineName(LldbEngineType), QVariant(int(LldbEngineType))); } + layout->addWidget(m_comboBox); + + m_label->setTextInteractionFlags(Qt::TextBrowserInteraction); + m_label->setOpenExternalLinks(true); + layout->addWidget(m_label); m_chooser->setContentsMargins(0, 0, 0, 0); m_chooser->setExpectedKind(Utils::PathChooser::ExistingCommand); @@ -102,6 +96,8 @@ DebuggerKitConfigWidget::DebuggerKitConfigWidget(ProjectExplorer::Kit *k, discard(); connect(m_chooser, SIGNAL(changed(QString)), this, SIGNAL(dirty())); + connect(m_comboBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(dirty())); + connect(m_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(refreshLabel())); } QString DebuggerKitConfigWidget::displayName() const @@ -111,23 +107,26 @@ QString DebuggerKitConfigWidget::displayName() const void DebuggerKitConfigWidget::makeReadOnly() { + m_comboBox->setEnabled(false); m_chooser->setEnabled(false); } void DebuggerKitConfigWidget::apply() { - Utils::FileName fn = m_chooser->fileName(); - DebuggerKitInformation::setDebuggerCommand(m_kit, fn); + DebuggerKitInformation::setDebuggerItem(m_kit, DebuggerKitInformation::DebuggerItem(engineType(), fileName())); } void DebuggerKitConfigWidget::discard() { - m_chooser->setFileName(DebuggerKitInformation::debuggerCommand(m_kit)); + const DebuggerKitInformation::DebuggerItem item = DebuggerKitInformation::debuggerItem(m_kit); + setEngineType(item.engineType); + setFileName(item.binary); } bool DebuggerKitConfigWidget::isDirty() const { - return m_chooser->fileName() != DebuggerKitInformation::debuggerCommand(m_kit); + const DebuggerKitInformation::DebuggerItem item = DebuggerKitInformation::debuggerItem(m_kit); + return item.engineType != engineType() || item.binary != fileName(); } QWidget *DebuggerKitConfigWidget::buttonWidget() const @@ -137,8 +136,62 @@ QWidget *DebuggerKitConfigWidget::buttonWidget() const void DebuggerKitConfigWidget::autoDetectDebugger() { - QVariant v = m_info->defaultValue(m_kit); - m_chooser->setFileName(Utils::FileName::fromString(v.toString())); + const DebuggerKitInformation::DebuggerItem item = DebuggerKitInformation::autoDetectItem(m_kit); + setEngineType(item.engineType); + setFileName(item.binary); +} + +DebuggerEngineType DebuggerKitConfigWidget::engineType() const +{ + const int index = m_comboBox->currentIndex(); + return static_cast<DebuggerEngineType>(m_comboBox->itemData(index).toInt()); +} + +void DebuggerKitConfigWidget::setEngineType(DebuggerEngineType et) +{ + const int size = m_comboBox->count(); + for (int i = 0; i < size; ++i) { + if (m_comboBox->itemData(i).toInt() == et) { + m_comboBox->setCurrentIndex(i); + refreshLabel(); + break; + } + } +} + +Utils::FileName DebuggerKitConfigWidget::fileName() const +{ + return m_chooser->fileName(); +} + +void DebuggerKitConfigWidget::setFileName(const Utils::FileName &fn) +{ + m_chooser->setFileName(fn); +} + +void DebuggerKitConfigWidget::refreshLabel() +{ + QString text; + switch (engineType()) { + case CdbEngineType: { +#ifdef Q_OS_WIN + const bool is64bit = Utils::winIs64BitSystem(); +#else + const bool is64bit = false; +#endif + const QString link = is64bit ? QLatin1String(dgbToolsDownloadLink64C) : QLatin1String(dgbToolsDownloadLink32C); + const QString versionString = is64bit ? tr("64-bit version") : tr("32-bit version"); + //: Label text for path configuration. %2 is "x-bit version". + text = tr("<html><body><p>Specify the path to the " + "<a href=\"%1\">Windows Console Debugger executable</a>" + " (%2) here.</p>""</body></html>").arg(link, versionString); + } + break; + default: + break; + } + m_label->setText(text); + m_label->setVisible(!text.isEmpty()); } } // namespace Internal diff --git a/src/plugins/debugger/debuggerkitconfigwidget.h b/src/plugins/debugger/debuggerkitconfigwidget.h index b818f3817f4..a54ee648b8c 100644 --- a/src/plugins/debugger/debuggerkitconfigwidget.h +++ b/src/plugins/debugger/debuggerkitconfigwidget.h @@ -33,11 +33,16 @@ #include <projectexplorer/kitconfigwidget.h> -#include <QLabel> -#include <debuggerkitinformation.h> +#include "debuggerconstants.h" + +QT_FORWARD_DECLARE_CLASS(QLabel) +QT_FORWARD_DECLARE_CLASS(QComboBox) namespace ProjectExplorer { class Kit; } -namespace Utils { class PathChooser; } +namespace Utils { +class PathChooser; +class FileName; +} namespace Debugger { class DebuggerKitInformation; @@ -65,12 +70,21 @@ public: bool isDirty() const; QWidget *buttonWidget() const; + DebuggerEngineType engineType() const; + void setEngineType(DebuggerEngineType et); + + Utils::FileName fileName() const; + void setFileName(const Utils::FileName &fn); + private slots: void autoDetectDebugger(); + void refreshLabel(); private: ProjectExplorer::Kit *m_kit; const DebuggerKitInformation *m_info; + QComboBox *m_comboBox; + QLabel *m_label; Utils::PathChooser *m_chooser; }; diff --git a/src/plugins/debugger/debuggerkitinformation.cpp b/src/plugins/debugger/debuggerkitinformation.cpp index 8d7db74f57f..75012379838 100644 --- a/src/plugins/debugger/debuggerkitinformation.cpp +++ b/src/plugins/debugger/debuggerkitinformation.cpp @@ -114,12 +114,32 @@ static QPair<QString, QString> autoDetectCdbDebugger() namespace Debugger { +static DebuggerEngineType engineTypeFromBinary(const QString &binary) +{ + if (binary.contains(QLatin1String("cdb"), Qt::CaseInsensitive)) + return CdbEngineType; + if (binary.contains(QLatin1String("lldb"), Qt::CaseInsensitive)) + return LldbEngineType; + return GdbEngineType; +} + // -------------------------------------------------------------------------- // DebuggerKitInformation: // -------------------------------------------------------------------------- static const char DEBUGGER_INFORMATION[] = "Debugger.Information"; +DebuggerKitInformation::DebuggerItem::DebuggerItem() + : engineType(NoEngineType) +{ +} + +DebuggerKitInformation::DebuggerItem::DebuggerItem(DebuggerEngineType et, const Utils::FileName &fn) + : engineType(et) + , binary(fn) +{ +} + DebuggerKitInformation::DebuggerKitInformation() { setObjectName(QLatin1String("DebuggerKitInformation")); @@ -136,9 +156,10 @@ unsigned int DebuggerKitInformation::priority() const return 28000; } -QVariant DebuggerKitInformation::defaultValue(Kit *k) const +DebuggerKitInformation::DebuggerItem DebuggerKitInformation::autoDetectItem(const Kit *k) { - ToolChain *tc = ToolChainKitInformation::toolChain(k); + DebuggerItem result; + const ToolChain *tc = ToolChainKitInformation::toolChain(k); Abi abi = Abi::hostAbi(); if (tc) abi = tc->targetAbi(); @@ -146,59 +167,100 @@ QVariant DebuggerKitInformation::defaultValue(Kit *k) const // CDB for windows: if (abi.os() == Abi::WindowsOS && abi.osFlavor() != Abi::WindowsMSysFlavor) { QPair<QString, QString> cdbs = autoDetectCdbDebugger(); - return (abi.wordWidth() == 32) ? cdbs.first : cdbs.second; + result.binary = Utils::FileName::fromString(abi.wordWidth() == 32 ? cdbs.first : cdbs.second); + result.engineType = CdbEngineType; + return result; } - // fall back to system GDB: - QString debugger = QLatin1String("gdb"); + // Check suggestions from the SDK. + const Environment env = Environment::systemEnvironment(); if (tc) { - // Check suggestions from the SDK: - const QString path = tc->suggestedDebugger().toString(); + QString path = tc->suggestedDebugger().toString(); if (!path.isEmpty()) { - QFileInfo fi(path); - if (fi.isAbsolute()) - return path; - debugger = path; + const QFileInfo fi(path); + if (!fi.isAbsolute()) + path = env.searchInPath(path); + result.binary = Utils::FileName::fromString(path); + result.engineType = engineTypeFromBinary(path); + return result; } } - Environment env = Environment::systemEnvironment(); - return env.searchInPath(debugger); + // Default to GDB, system GDB + result.engineType = GdbEngineType; + QString gdb; + const QString systemGdb = QLatin1String("gdb"); + // MinGW: Search for the python-enabled gdb first. + if (abi.os() == Abi::WindowsOS && abi.osFlavor() == Abi::WindowsMSysFlavor) + gdb = env.searchInPath(QLatin1String("gdb-i686-pc-mingw32")); + if (gdb.isEmpty()) + gdb = env.searchInPath(systemGdb); + result.binary = Utils::FileName::fromString(env.searchInPath(gdb.isEmpty() ? systemGdb : gdb)); + return result; } -QList<Task> DebuggerKitInformation::validate(Kit *k) const +// Check the configuration errors and return a flag mask. Provide a quick check and +// a verbose one with a list of errors. + +enum DebuggerConfigurationErrors { + NoDebugger = 0x1, + DebuggerNotFound = 0x2, + DebuggerNotExecutable = 0x4, + DebuggerNeedsAbsolutePath = 0x8 +}; + +static unsigned debuggerConfigurationErrors(const ProjectExplorer::Kit *p) { - const Core::Id id(Constants::TASK_CATEGORY_BUILDSYSTEM); - QList<Task> result; - FileName dbg = debuggerCommand(k); - if (dbg.isEmpty()) { - result << Task(Task::Warning, tr("No debugger set up."), FileName(), -1, id); - return result; + unsigned result = 0; + const DebuggerKitInformation::DebuggerItem item = DebuggerKitInformation::debuggerItem(p); + if (item.engineType == NoEngineType || item.binary.isEmpty()) + return NoDebugger; + + const QFileInfo fi = item.binary.toFileInfo(); + if (!fi.exists() || fi.isDir()) { + result |= DebuggerNotFound; + } else if (!fi.isExecutable()) { + result |= DebuggerNotExecutable; } - QFileInfo fi = dbg.toFileInfo(); if (!fi.exists() || fi.isDir()) - result << Task(Task::Error, tr("Debugger not found."), FileName(), -1, id); - else if (!fi.isExecutable()) - result << Task(Task::Error, tr("Debugger not exectutable."), FileName(), -1, id); - - if (ToolChain *tc = ToolChainKitInformation::toolChain(k)) { // We need an absolute path to be able to locate Python on Windows. - const Abi abi = tc->targetAbi(); - if (abi.os() == Abi::WindowsOS && !fi.isAbsolute()) { - result << Task(Task::Error, tr("The debugger location must be given as an " - "absolute path (%1).").arg(dbg.toString()), FileName(), -1, id); - } - // FIXME: Make sure debugger matches toolchain. - // if (isCdb()) { - // if (abi.binaryFormat() != Abi::PEFormat || abi.os() != Abi::WindowsOS) { - // result << Task(Tas->errorDetails.push_back(CdbEngine::tr("The CDB debug engine does not support the %1 ABI."). - // arg(abi.toString())); - // return false; - // } - // } - } + if (item.engineType == GdbEngineType) + if (const ToolChain *tc = ToolChainKitInformation::toolChain(p)) + if (tc->targetAbi().os() == Abi::WindowsOS && !fi.isAbsolute()) + result |= DebuggerNeedsAbsolutePath; + return result; +} + +bool DebuggerKitInformation::isValidDebugger(const ProjectExplorer::Kit *p) +{ + return debuggerConfigurationErrors(p) == 0; +} + +QList<ProjectExplorer::Task> DebuggerKitInformation::validateDebugger(const ProjectExplorer::Kit *p) +{ + const unsigned errors = debuggerConfigurationErrors(p); + const Core::Id id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM); + QList<Task> result; + if (errors & NoDebugger) + result << Task(Task::Warning, tr("No debugger set up."), FileName(), -1, id); + if (errors & DebuggerNotFound) { + const QString path = DebuggerKitInformation::debuggerCommand(p).toUserOutput(); + result << Task(Task::Error, tr("Debugger '%1' not found.").arg(path), + FileName(), -1, id); + } + if (errors & DebuggerNotExecutable) { + const QString path = DebuggerKitInformation::debuggerCommand(p).toUserOutput(); + result << Task(Task::Error, tr("Debugger '%1' not executable.").arg(path), FileName(), -1, id); + } + if (errors & DebuggerNeedsAbsolutePath) { + const QString path = DebuggerKitInformation::debuggerCommand(p).toUserOutput(); + const QString message = + tr("The debugger location must be given as an " + "absolute path (%1).").arg(path); + result << Task(Task::Error, message, FileName(), -1, id); + } return result; } @@ -207,20 +269,81 @@ KitConfigWidget *DebuggerKitInformation::createConfigWidget(Kit *k) const return new Internal::DebuggerKitConfigWidget(k, this); } +QString DebuggerKitInformation::userOutput(const ProjectExplorer::Kit *k) +{ + const DebuggerItem item = DebuggerKitInformation::debuggerItem(k); + return tr("%1 using '%2'").arg(debuggerEngineName(item.engineType), + item.binary.toUserOutput()); +} + KitInformation::ItemList DebuggerKitInformation::toUserOutput(Kit *k) const { - return ItemList() << qMakePair(tr("Debugger"), debuggerCommand(k).toUserOutput()); + return ItemList() << qMakePair(tr("Debugger"), DebuggerKitInformation::userOutput(k)); +} + +static const char engineTypeKeyC[] = "EngineType"; +static const char binaryKeyC[] = "Binary"; + +DebuggerKitInformation::DebuggerItem DebuggerKitInformation::variantToItem(const QVariant &v) +{ + DebuggerItem result; + if (v.type() == QVariant::String) { // Convert legacy config items, remove later. + const QString binary = v.toString(); + result.binary = Utils::FileName::fromString(binary); + result.engineType = engineTypeFromBinary(binary); + return result; + } + QTC_ASSERT(v.type() == QVariant::Map, return result); + const QVariantMap vmap = v.toMap(); + result.binary = Utils::FileName::fromString(vmap.value(QLatin1String(binaryKeyC)).toString()); + result.engineType = static_cast<DebuggerEngineType>(vmap.value(QLatin1String(engineTypeKeyC)).toInt()); + return result; } -FileName DebuggerKitInformation::debuggerCommand(const Kit *k) +QVariant DebuggerKitInformation::itemToVariant(const DebuggerItem &i) { - return FileName::fromString(k ? k->value(Core::Id(DEBUGGER_INFORMATION)).toString() : QString()); + QVariantMap vmap; + vmap.insert(QLatin1String(binaryKeyC), QVariant(i.binary.toUserOutput())); + vmap.insert(QLatin1String(engineTypeKeyC), QVariant(int(i.engineType))); + return QVariant(vmap); } -void DebuggerKitInformation::setDebuggerCommand(Kit *k, const FileName &command) +DebuggerKitInformation::DebuggerItem DebuggerKitInformation::debuggerItem(const ProjectExplorer::Kit *p) { - QTC_ASSERT(k, return); - k->setValue(Core::Id(DEBUGGER_INFORMATION), command.toString()); + return p ? + DebuggerKitInformation::variantToItem(p->value(Core::Id(DEBUGGER_INFORMATION))) : + DebuggerItem(); +} + +void DebuggerKitInformation::setDebuggerItem(ProjectExplorer::Kit *p, const DebuggerItem &item) +{ + QTC_ASSERT(p, return); + p->setValue(Core::Id(DEBUGGER_INFORMATION), itemToVariant(item)); +} + +void DebuggerKitInformation::setDebuggerCommand(ProjectExplorer::Kit *k, const FileName &command) +{ + setDebuggerItem(k, DebuggerItem(engineType(k), command)); +} + +void DebuggerKitInformation::setEngineType(ProjectExplorer::Kit *p, DebuggerEngineType type) +{ + setDebuggerItem(p, DebuggerItem(type, debuggerCommand(p))); +} + +QString DebuggerKitInformation::debuggerEngineName(DebuggerEngineType t) +{ + switch (t) { + case Debugger::GdbEngineType: + return tr("GDB Engine"); + case Debugger::CdbEngineType: + return tr("CDB Engine"); + case Debugger::LldbEngineType: + return tr("LLDB Engine"); + default: + break; + } + return QString(); } } // namespace Debugger diff --git a/src/plugins/debugger/debuggerkitinformation.h b/src/plugins/debugger/debuggerkitinformation.h index e6d9dab6c81..ceb119d08d5 100644 --- a/src/plugins/debugger/debuggerkitinformation.h +++ b/src/plugins/debugger/debuggerkitinformation.h @@ -32,6 +32,7 @@ #define DEBUGGER_DEBUGGERKITINFORMATION_H #include "debugger_global.h" +#include "debuggerconstants.h" #include <projectexplorer/kitinformation.h> @@ -42,22 +43,54 @@ class DEBUGGER_EXPORT DebuggerKitInformation : public ProjectExplorer::KitInform Q_OBJECT public: + class DEBUGGER_EXPORT DebuggerItem { + public: + DebuggerItem(); + DebuggerItem(DebuggerEngineType engineType, const Utils::FileName &fn); + + DebuggerEngineType engineType; + Utils::FileName binary; + }; + DebuggerKitInformation(); Core::Id dataId() const; unsigned int priority() const; // the higher the closer to the top. - QVariant defaultValue(ProjectExplorer::Kit *k) const; + static DebuggerItem autoDetectItem(const ProjectExplorer::Kit *k); + QVariant defaultValue(ProjectExplorer::Kit *k) const + { return DebuggerKitInformation::itemToVariant(DebuggerKitInformation::autoDetectItem(k)); } + + QList<ProjectExplorer::Task> validate(ProjectExplorer::Kit *k) const + { return DebuggerKitInformation::validateDebugger(k); } - QList<ProjectExplorer::Task> validate(ProjectExplorer::Kit *k) const; + static QList<ProjectExplorer::Task> validateDebugger(const ProjectExplorer::Kit *p); + static bool isValidDebugger(const ProjectExplorer::Kit *p); ProjectExplorer::KitConfigWidget *createConfigWidget(ProjectExplorer::Kit *k) const; ItemList toUserOutput(ProjectExplorer::Kit *k) const; + static QString userOutput(const ProjectExplorer::Kit *k); + + static DebuggerItem debuggerItem(const ProjectExplorer::Kit *p); + static void setDebuggerItem(ProjectExplorer::Kit *p, const DebuggerItem &item); + + static Utils::FileName debuggerCommand(const ProjectExplorer::Kit *p) + { return debuggerItem(p).binary; } + + static void setDebuggerCommand(ProjectExplorer::Kit *p, const Utils::FileName &command); + + static DebuggerEngineType engineType(const ProjectExplorer::Kit *p) + { return debuggerItem(p).engineType; } + + static void setEngineType(ProjectExplorer::Kit *p, DebuggerEngineType type); + + static QString debuggerEngineName(DebuggerEngineType t); - static Utils::FileName debuggerCommand(const ProjectExplorer::Kit *k); - static void setDebuggerCommand(ProjectExplorer::Kit *k, const Utils::FileName &command); +private: + static DebuggerItem variantToItem(const QVariant &v); + static QVariant itemToVariant(const DebuggerItem &i); }; } // namespace Debugger diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 27ece76ae16..0df27ac8198 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -567,8 +567,10 @@ public: explicit AbiKitMatcher(const QList<Abi> &abis) : m_abis(abis) {} bool matches(const Kit *p) const { - if (const ToolChain *tc = ToolChainKitInformation::toolChain(p)) - return m_abis.contains(tc->targetAbi()); + if (const ToolChain *tc = ToolChainKitInformation::toolChain(p)) { + return m_abis.contains(tc->targetAbi()) + && DebuggerKitInformation::isValidDebugger(p); + } return false; } @@ -584,7 +586,7 @@ public: { if (const ToolChain *tc = ToolChainKitInformation::toolChain(p)) foreach (const Abi &a, m_abis) - if (a.isCompatibleWith(tc->targetAbi())) + if (a.isCompatibleWith(tc->targetAbi()) && DebuggerKitInformation::isValidDebugger(p)) return true; return false; } @@ -600,18 +602,14 @@ public: bool matches(const Kit *k) const { - const ToolChain *tc = ToolChainKitInformation::toolChain(k); - QTC_ASSERT(tc, return false); - const Abi abi = tc->targetAbi(); - if (abi.architecture() != Abi::X86Architecture - || abi.os() != Abi::WindowsOS - || abi.binaryFormat() != Abi::PEFormat) - return false; - if (abi.osFlavor() == Abi::WindowsMSysFlavor - || abi.osFlavor() == Abi::WindowsCEFlavor) - return false; - if (m_wordWidth && abi.wordWidth() != m_wordWidth) + if (DebuggerKitInformation::engineType(k) != CdbEngineType + || !DebuggerKitInformation::isValidDebugger(k)) { return false; + } + if (m_wordWidth) { + const ToolChain *tc = ToolChainKitInformation::toolChain(k); + return tc && m_wordWidth == tc->targetAbi().wordWidth(); + } return true; } @@ -634,7 +632,7 @@ private: const char m_wordWidth; }; -void fillParameters(DebuggerStartParameters *sp, const Kit *kit /* = 0 */) +bool fillParameters(DebuggerStartParameters *sp, const Kit *kit /* = 0 */, QString *errorMessage /* = 0 */) { if (!kit) { // This code can only be reached when starting via the command line @@ -664,6 +662,27 @@ void fillParameters(DebuggerStartParameters *sp, const Kit *kit /* = 0 */) kit = KitManager::instance()->defaultKit(); } + // Verify that debugger and profile are valid + if (!kit) { + sp->startMode = NoStartMode; + if (errorMessage) + *errorMessage = DebuggerKitInformation::tr("No kit found."); + return false; + } + const QList<ProjectExplorer::Task> tasks = DebuggerKitInformation::validateDebugger(kit); + if (!tasks.isEmpty()) { + sp->startMode = NoStartMode; + if (errorMessage) { + foreach (const ProjectExplorer::Task &t, tasks) { + if (errorMessage->isEmpty()) + errorMessage->append(QLatin1Char('\n')); + errorMessage->append(t.description); + } + } + return false; + } + + sp->cppEngineType = DebuggerKitInformation::engineType(kit); sp->sysRoot = SysRootKitInformation::sysRoot(kit).toString(); sp->debuggerCommand = DebuggerKitInformation::debuggerCommand(kit).toString(); @@ -676,6 +695,7 @@ void fillParameters(DebuggerStartParameters *sp, const Kit *kit /* = 0 */) sp->connParams = device->sshParameters(); sp->remoteChannel = sp->connParams.host + QLatin1Char(':') + QString::number(sp->connParams.port); } + return true; } static TextEditor::ITextEditor *currentTextEditor() @@ -1438,7 +1458,8 @@ bool DebuggerPluginPrivate::parseArgument(QStringList::const_iterator &it, } } } - fillParameters(&sp, kit); + if (fillParameters(&sp, kit, errorMessage)) + return false; if (sp.startMode == StartExternal) { sp.displayName = tr("Executable file \"%1\"").arg(sp.executable); sp.startMessage = tr("Debugging file %1.").arg(sp.executable); @@ -1458,7 +1479,8 @@ bool DebuggerPluginPrivate::parseArgument(QStringList::const_iterator &it, return false; } DebuggerStartParameters sp; - fillParameters(&sp, CdbMatcher::findUniversalCdbKit()); + if (!fillParameters(&sp, CdbMatcher::findUniversalCdbKit(), errorMessage)) + return false; sp.startMode = AttachCrashedExternal; sp.crashParameter = it->section(QLatin1Char(':'), 0, 0); sp.attachPID = it->section(QLatin1Char(':'), 1, 1).toULongLong(); @@ -1596,7 +1618,7 @@ void DebuggerPluginPrivate::attachCore() DebuggerStartParameters sp; QString display = dlg.isLocal() ? dlg.localCoreFile() : dlg.remoteCoreFile(); - fillParameters(&sp, dlg.kit()); + QTC_ASSERT(fillParameters(&sp, dlg.kit()), return); sp.masterEngineType = GdbEngineType; sp.executable = dlg.localExecutableFile(); sp.coreFile = dlg.localCoreFile(); @@ -1612,8 +1634,7 @@ void DebuggerPluginPrivate::startRemoteCdbSession() const QString connectionKey = _("CdbRemoteConnection"); DebuggerStartParameters sp; Kit *kit = CdbMatcher::findUniversalCdbKit(); - QTC_ASSERT(kit, return); - fillParameters(&sp, kit); + QTC_ASSERT(kit && fillParameters(&sp, kit), return); sp.startMode = AttachToRemoteServer; sp.closeMode = KillAtClose; StartRemoteCdbDialog dlg(mainWindow()); @@ -1683,7 +1704,7 @@ void DebuggerPluginPrivate::attachToProcess(bool startServerOnly) if (device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) { DebuggerStartParameters sp; - fillParameters(&sp, kit); + QTC_ASSERT(fillParameters(&sp, kit), return); sp.attachPID = process.pid; sp.displayName = tr("Process %1").arg(process.pid); sp.executable = process.exe; @@ -1708,7 +1729,7 @@ void DebuggerPluginPrivate::attachExternalApplication(ProjectExplorer::RunContro if (const RunConfiguration *runConfiguration = rc->runConfiguration()) if (const Target *target = runConfiguration->target()) kit = target->kit(); - fillParameters(&sp, kit); + QTC_ASSERT(fillParameters(&sp, kit), return); DebuggerRunControlFactory::createAndScheduleRun(sp); } @@ -1731,11 +1752,10 @@ void DebuggerPluginPrivate::attachToQmlPort() return; Kit *kit = dlg.kit(); - QTC_ASSERT(kit, return); + QTC_ASSERT(kit && fillParameters(&sp, kit), return); setConfigValue(_("LastQmlServerPort"), dlg.port()); setConfigValue(_("LastProfile"), kit->id().toString()); - fillParameters(&sp, kit); sp.qmlServerAddress = sp.connParams.host; sp.qmlServerPort = dlg.port(); sp.startMode = AttachToRemoteProcess; diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 476d23e3acc..e0ddc0122a3 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -259,11 +259,6 @@ public: explicit DebuggerRunControlPrivate(DebuggerRunControl *parent, RunConfiguration *runConfiguration); - DebuggerEngineType engineForExecutable(unsigned enabledEngineTypes, - const QString &executable); - DebuggerEngineType engineForMode(unsigned enabledEngineTypes, - DebuggerStartMode mode); - public: DebuggerRunControl *q; DebuggerEngine *m_engine; @@ -476,7 +471,7 @@ QString DebuggerRunControlFactory::displayName() const return DebuggerPlugin::tr("Debug"); } -static DebuggerStartParameters localStartParameters(RunConfiguration *runConfiguration) +static DebuggerStartParameters localStartParameters(RunConfiguration *runConfiguration, QString *errorMessage) { DebuggerStartParameters sp; QTC_ASSERT(runConfiguration, return sp); @@ -486,7 +481,8 @@ static DebuggerStartParameters localStartParameters(RunConfiguration *runConfigu Target *target = runConfiguration->target(); Kit *kit = target ? target->kit() : KitManager::instance()->defaultKit(); - fillParameters(&sp, kit); + if (!fillParameters(&sp, kit, errorMessage)) + return sp; sp.environment = rc->environment(); sp.workingDirectory = rc->workingDirectory(); @@ -547,7 +543,7 @@ RunControl *DebuggerRunControlFactory::create { Q_UNUSED(errorMessage) QTC_ASSERT(mode == DebugRunMode || mode == DebugRunModeWithBreakOnMain, return 0); - DebuggerStartParameters sp = localStartParameters(runConfiguration); + DebuggerStartParameters sp = localStartParameters(runConfiguration, errorMessage); if (sp.startMode == NoStartMode) return 0; if (mode == DebugRunModeWithBreakOnMain) @@ -556,92 +552,43 @@ RunControl *DebuggerRunControlFactory::create return doCreate(sp, runConfiguration, errorMessage); } -static DebuggerEngineType guessUnixCppEngineType(const DebuggerStartParameters &sp) -{ - if (sp.debuggerCommand.contains(QLatin1String("lldb"))) - return LldbEngineType; - return GdbEngineType; -} - -static DebuggerEngineType guessCppEngineTypeForAbi(const DebuggerStartParameters &sp, const Abi &abi) -{ - switch (abi.binaryFormat()) { - case Abi::ElfFormat: - case Abi::MachOFormat: - return guessUnixCppEngineType(sp) ; - case Abi::PEFormat: - if (abi.osFlavor() == Abi::WindowsMSysFlavor) - return guessUnixCppEngineType(sp); - return CdbEngineType; - default: - break; - } - return NoEngineType; -} - -static DebuggerEngineType guessCppEngineType(const DebuggerStartParameters &sp) -{ - if (sp.toolChainAbi.isValid()) { - const DebuggerEngineType et = guessCppEngineTypeForAbi(sp, sp.toolChainAbi); - if (et != NoEngineType) - return et; - } - - #ifdef Q_OS_WIN - // If a file has PDB files, it has been compiled by VS. - if (sp.executable.endsWith(_(".exe"), Qt::CaseInsensitive)) { - QStringList pdbFiles; - QString errorMessage; - if (getPDBFiles(sp.executable, &pdbFiles, &errorMessage) && !pdbFiles.isEmpty()) - return CdbEngineType; - } - #endif - - QList<Abi> abis = Abi::abisOfBinary(FileName::fromString(sp.executable)); - foreach (const Abi &abi, abis) { - DebuggerEngineType et = guessCppEngineTypeForAbi(sp, abi); - if (et != NoEngineType) - return et; - } - - return guessUnixCppEngineType(sp); -} - -static void fixupEngineTypes(DebuggerStartParameters &sp, RunConfiguration *rc) +static bool fixupEngineTypes(DebuggerStartParameters &sp, RunConfiguration *rc, QString *errorMessage) { if (sp.masterEngineType != NoEngineType) - return; + return true; if (sp.executable.endsWith(_(".js"))) { sp.masterEngineType = ScriptEngineType; - return; + return true; } if (sp.executable.endsWith(_(".py"))) { sp.masterEngineType = PdbEngineType; - return; + return true; } if (rc) { DebuggerRunConfigurationAspect *aspect = rc->debuggerAspect(); if (const Target *target = rc->target()) - fillParameters(&sp, target->kit()); + if (!fillParameters(&sp, target->kit(), errorMessage)) + return false; const bool useCppDebugger = aspect->useCppDebugger(); const bool useQmlDebugger = aspect->useQmlDebugger(); if (useQmlDebugger) { if (useCppDebugger) { sp.masterEngineType = QmlCppEngineType; - sp.firstSlaveEngineType = guessCppEngineType(sp); + sp.firstSlaveEngineType = sp.cppEngineType; sp.secondSlaveEngineType = QmlCppEngineType; } else { sp.masterEngineType = QmlEngineType; } } else { - sp.masterEngineType = guessCppEngineType(sp); + sp.masterEngineType = sp.cppEngineType; } - return; + return true; } - sp.masterEngineType = guessCppEngineType(sp); + sp.masterEngineType = sp.cppEngineType; + return true; } DebuggerRunControl *DebuggerRunControlFactory::doCreate @@ -664,10 +611,8 @@ DebuggerRunControl *DebuggerRunControlFactory::doCreate } } - fixupEngineTypes(sp, rc); - if (!sp.masterEngineType) { + if (!fixupEngineTypes(sp, rc, errorMessage)) return 0; - } return new DebuggerRunControl(rc, sp); } diff --git a/src/plugins/debugger/debuggerstartparameters.h b/src/plugins/debugger/debuggerstartparameters.h index 09e0a4f5543..3db9f9b2185 100644 --- a/src/plugins/debugger/debuggerstartparameters.h +++ b/src/plugins/debugger/debuggerstartparameters.h @@ -60,6 +60,7 @@ public: : masterEngineType(NoEngineType), firstSlaveEngineType(NoEngineType), secondSlaveEngineType(NoEngineType), + cppEngineType(NoEngineType), isSnapshot(false), attachPID(-1), useTerminal(false), @@ -81,6 +82,7 @@ public: DebuggerEngineType masterEngineType; DebuggerEngineType firstSlaveEngineType; DebuggerEngineType secondSlaveEngineType; + DebuggerEngineType cppEngineType; QString sysRoot; QString debuggerCommand; ProjectExplorer::Abi toolChainAbi; @@ -140,7 +142,7 @@ public: namespace Internal { -void fillParameters(DebuggerStartParameters *sp, const ProjectExplorer::Kit *kit = 0); +bool fillParameters(DebuggerStartParameters *sp, const ProjectExplorer::Kit *kit = 0, QString *errorMessage = 0); } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/gdb/startgdbserverdialog.cpp b/src/plugins/debugger/gdb/startgdbserverdialog.cpp index 20a08293ced..e32b49282a4 100644 --- a/src/plugins/debugger/gdb/startgdbserverdialog.cpp +++ b/src/plugins/debugger/gdb/startgdbserverdialog.cpp @@ -207,7 +207,7 @@ void GdbServerStarter::attach(int port) } DebuggerStartParameters sp; - fillParameters(&sp, d->kit); + QTC_ASSERT(fillParameters(&sp, d->kit), return); sp.masterEngineType = GdbEngineType; sp.connParams.port = port; sp.displayName = tr("Remote: \"%1:%2\"").arg(sp.connParams.host).arg(port); diff --git a/src/plugins/debugger/lldb/lldbenginehost.cpp b/src/plugins/debugger/lldb/lldbenginehost.cpp index 810ab62de85..486020c66fc 100644 --- a/src/plugins/debugger/lldb/lldbenginehost.cpp +++ b/src/plugins/debugger/lldb/lldbenginehost.cpp @@ -140,6 +140,7 @@ LldbEngineHost::LldbEngineHost(const DebuggerStartParameters &startParameters) :IPCEngineHost(startParameters), m_ssh(0) { showMessage(QLatin1String("setting up coms")); + setObjectName(QLatin1String("LLDBEngine")); if (startParameters.startMode == StartRemoteEngine) { |