diff options
author | Tobias Hunger <tobias.hunger@nokia.com> | 2011-02-01 18:36:00 +0100 |
---|---|---|
committer | Tobias Hunger <tobias.hunger@nokia.com> | 2011-02-21 18:33:23 +0100 |
commit | 8d0c47724599ad279a88e3632784be40cc4175da (patch) | |
tree | 7c4408a1d2f14f3ac5d33711fc1241ea8b4821d1 /src/plugins/debugger | |
parent | be31c80b02f752484e76faa215eae616a80e24e3 (diff) | |
download | qt-creator-8d0c47724599ad279a88e3632784be40cc4175da.tar.gz |
ToolChain: Refactor toolchain support
Refactor ToolChains in Qt Creator:
* Allow for several toolchains of the same type
* Be smarter wrt. guessing what kind of output a toolchain
produces. This allows us to eventually handle e.g. embedded
linux setups way better than before.
* Be smarter wrt. guessing what kind of environment a Qt version
needs.
* Improve auto-detection of toolchains a bit
* Decide on which debugger to use based on the kind of output
produced by the compiler.
* Add options page to configure toolchains
* Remove toolchain related options from the Qt version dialog
Reviewed-by: dt
Diffstat (limited to 'src/plugins/debugger')
-rw-r--r-- | src/plugins/debugger/cdb/cdbengine.cpp | 27 | ||||
-rw-r--r-- | src/plugins/debugger/debuggercore.h | 4 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerengine.cpp | 5 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerplugin.cpp | 32 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerrunner.cpp | 80 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerrunner.h | 4 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerstartparameters.h | 5 | ||||
-rw-r--r-- | src/plugins/debugger/gdb/gdbchooserwidget.cpp | 501 | ||||
-rw-r--r-- | src/plugins/debugger/gdb/gdbchooserwidget.h | 83 | ||||
-rw-r--r-- | src/plugins/debugger/gdb/gdbengine.cpp | 23 | ||||
-rw-r--r-- | src/plugins/debugger/gdb/gdboptionspage.cpp | 257 | ||||
-rw-r--r-- | src/plugins/debugger/gdb/gdboptionspage.h | 18 | ||||
-rw-r--r-- | src/plugins/debugger/gdb/remotegdbserveradapter.cpp | 25 | ||||
-rw-r--r-- | src/plugins/debugger/gdb/remotegdbserveradapter.h | 6 |
14 files changed, 341 insertions, 729 deletions
diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 86a11b6290..8dfd96709a 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -309,10 +309,10 @@ static inline bool validMode(DebuggerStartMode sm) return true; } -static inline QString msgCdbDisabled(ToolChainType tc) +static inline QString msgCdbDisabled(const ProjectExplorer::Abi &abi) { return CdbEngine::tr("The CDB debug engine required for %1 is currently disabled."). - arg(ToolChain::toolChainName(tc)); + arg(abi.toString()); } // Accessed by RunControlFactory @@ -322,7 +322,7 @@ DebuggerEngine *createCdbEngine(const DebuggerStartParameters &sp, #ifdef Q_OS_WIN CdbOptionsPage *op = CdbOptionsPage::instance(); if (!op || !op->options()->isValid()) { - *errorMessage = msgCdbDisabled(sp.toolChainType); + *errorMessage = msgCdbDisabled(sp.toolChainAbi); return 0; } if (!validMode(sp.startMode)) { @@ -347,25 +347,18 @@ bool isCdbEngineEnabled() #endif } -ConfigurationCheck checkCdbConfiguration(ToolChainType toolChain) +ConfigurationCheck checkCdbConfiguration(const ProjectExplorer::Abi &abi) { ConfigurationCheck check; - switch (toolChain) { - case ToolChain_MinGW: // Do our best - case ToolChain_MSVC: - case ToolChain_WINCE: - case ToolChain_OTHER: - case ToolChain_UNKNOWN: - case ToolChain_INVALID: + if (abi.binaryFormat() == ProjectExplorer::Abi::Format_PE + && abi.osFlavor() != ProjectExplorer::Abi::Windows_msys) { if (!isCdbEngineEnabled()) { - check.errorMessage = msgCdbDisabled(toolChain); + check.errorMessage = msgCdbDisabled(abi); check.settingsPage = CdbOptionsPage::settingsId(); } - break; - default: - //: %1 is something like "GCCE" or "Intel C++ Compiler (Linux)" (see ToolChain context) - check.errorMessage = CdbEngine::tr("The CDB debug engine does not support the %1 toolchain."). - arg(ToolChain::toolChainName(toolChain)); + } else { + check.errorMessage = CdbEngine::tr("The CDB debug engine does not support the %1 ABI."). + arg(abi.toString()); check.settingsPage = CdbOptionsPage::settingsId(); } return check; diff --git a/src/plugins/debugger/debuggercore.h b/src/plugins/debugger/debuggercore.h index da85e4c4d8..f86d5122c3 100644 --- a/src/plugins/debugger/debuggercore.h +++ b/src/plugins/debugger/debuggercore.h @@ -36,6 +36,8 @@ #include "debuggerconstants.h" +#include <projectexplorer/abi.h> + #include <QtCore/QObject> QT_BEGIN_NAMESPACE @@ -101,7 +103,7 @@ public: virtual bool initialize(const QStringList &arguments, QString *errorMessage) = 0; virtual QWidget *mainWindow() const = 0; virtual bool isDockVisible(const QString &objectName) const = 0; - virtual QString gdbBinaryForToolChain(int toolChain) const = 0; + virtual QString gdbBinaryForAbi(const ProjectExplorer::Abi &abi) const = 0; virtual void showModuleSymbols(const QString &moduleName, const QVector<Symbol> &symbols) = 0; virtual void openMemoryEditor() = 0; diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 7b82b9a4a7..5b1030651c 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -57,9 +57,6 @@ #include <coreplugin/progressmanager/progressmanager.h> #include <coreplugin/progressmanager/futureprogress.h> -#include <projectexplorer/toolchain.h> -#include <projectexplorer/toolchaintype.h> - #include <texteditor/itexteditor.h> #include <texteditor/basetextmark.h> @@ -123,7 +120,7 @@ QDebug operator<<(QDebug str, const DebuggerStartParameters &sp) << " symbolFileName=" << sp.symbolFileName << " useServerStartScript=" << sp.useServerStartScript << " serverStartScript=" << sp.serverStartScript - << " toolchain=" << sp.toolChainType << '\n'; + << " abi=" << sp.toolChainAbi.toString() << '\n'; return str; } diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index caaa78a2df..af0ef86b09 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -97,8 +97,6 @@ #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/session.h> #include <projectexplorer/target.h> -#include <projectexplorer/toolchain.h> -#include <projectexplorer/toolchaintype.h> #include <qt4projectmanager/qt4projectmanagerconstants.h> @@ -904,7 +902,7 @@ public slots: void runControlStarted(DebuggerEngine *engine); void runControlFinished(DebuggerEngine *engine); DebuggerLanguages activeLanguages() const; - QString gdbBinaryForToolChain(int toolChain) const; + QString gdbBinaryForAbi(const ProjectExplorer::Abi &abi) const; void remoteCommand(const QStringList &options, const QStringList &); bool isReverseDebugging() const; @@ -1536,7 +1534,8 @@ void DebuggerPluginPrivate::startExternalApplication() sp.processArgs = dlg.executableArguments(); // Fixme: 1 of 3 testing hacks. if (sp.processArgs.startsWith(__("@tcf@ ")) || sp.processArgs.startsWith(__("@sym@ "))) - sp.toolChainType = ToolChain_RVCT2_ARMV5; + // Set up an ARM Symbian Abi + sp.toolChainAbi = Abi(Abi::ARM, Abi::Symbian, Abi::Symbian_device, Abi::Format_ELF, false); if (dlg.breakAtMain()) { #ifdef Q_OS_WIN @@ -1615,7 +1614,12 @@ void DebuggerPluginPrivate::startRemoteCdbSession() { const QString connectionKey = _("CdbRemoteConnection"); DebuggerStartParameters sp; - sp.toolChainType = ToolChain_MSVC; + Abi hostAbi = Abi::hostAbi(); + sp.toolChainAbi = ProjectExplorer::Abi(hostAbi.architecture(), + ProjectExplorer::Abi::Windows, + ProjectExplorer::Abi::Windows_msvc, + ProjectExplorer::Abi::Format_PE, + true); sp.startMode = AttachToRemote; StartRemoteCdbDialog dlg(mainWindow()); QString previousConnection = configValue(connectionKey).toString(); @@ -1681,7 +1685,7 @@ void DebuggerPluginPrivate::startRemoteApplication() sp.displayName = dlg.localExecutable(); sp.debuggerCommand = dlg.debugger(); // Override toolchain-detection. if (!sp.debuggerCommand.isEmpty()) - sp.toolChainType = ToolChain_INVALID; + sp.toolChainAbi = ProjectExplorer::Abi(); sp.startMode = AttachToRemote; sp.useServerStartScript = dlg.useServerStartScript(); sp.serverStartScript = dlg.serverStartScript(); @@ -2494,10 +2498,9 @@ void DebuggerPluginPrivate::createNewDock(QWidget *widget) void DebuggerPluginPrivate::runControlStarted(DebuggerEngine *engine) { activateDebugMode(); - QString toolChainName = - ToolChain::toolChainName(engine->startParameters().toolChainType); - const QString message = tr("Starting debugger '%1' for tool chain '%2'...") - .arg(engine->objectName()).arg(toolChainName); + const QString message = tr("Starting debugger '%1' for ABI '%2'...") + .arg(engine->objectName()) + .arg(engine->startParameters().toolChainAbi.toString()); showMessage(message, StatusBar); showMessage(m_debuggerSettings->dump(), LogDebug); m_snapshotHandler->appendSnapshot(engine); @@ -2534,9 +2537,9 @@ void DebuggerPluginPrivate::remoteCommand(const QStringList &options, runScheduled(); } -QString DebuggerPluginPrivate::gdbBinaryForToolChain(int toolChain) const +QString DebuggerPluginPrivate::gdbBinaryForAbi(const ProjectExplorer::Abi &abi) const { - return GdbOptionsPage::gdbBinaryToolChainMap.key(toolChain); + return GdbOptionsPage::abiToGdbMap.value(abi.toString()); } DebuggerLanguages DebuggerPluginPrivate::activeLanguages() const @@ -2757,7 +2760,7 @@ void DebuggerPluginPrivate::extensionsInitialized() dock->setProperty(DOCKWIDGET_DEFAULT_AREA, Qt::RightDockWidgetArea); m_debuggerSettings->readSettings(); - GdbOptionsPage::readGdbBinarySettings(); + GdbOptionsPage::readGdbSettings(); // Register factory of DebuggerRunControl. m_debuggerRunControlFactory = new DebuggerRunControlFactory @@ -3158,8 +3161,7 @@ void DebuggerPluginPrivate::aboutToShutdown() this, 0); m_debuggerSettings->writeSettings(); m_mainWindow->writeSettings(); - if (GdbOptionsPage::gdbBinariesChanged) - GdbOptionsPage::writeGdbBinarySettings(); + GdbOptionsPage::writeGdbSettings(); } } // namespace Internal diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 6ad856cff5..512ffb3534 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -49,9 +49,9 @@ # include "peutils.h" #endif +#include <projectexplorer/abi.h> #include <projectexplorer/debugginghelper.h> #include <projectexplorer/project.h> -#include <projectexplorer/toolchain.h> #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/target.h> #include <projectexplorer/buildconfiguration.h> @@ -74,7 +74,7 @@ namespace Debugger { namespace Internal { bool isCdbEngineEnabled(); // Check the configuration page -ConfigurationCheck checkCdbConfiguration(ToolChainType toolChain); +ConfigurationCheck checkCdbConfiguration(const ProjectExplorer::Abi &); DebuggerEngine *createCdbEngine(const DebuggerStartParameters &, DebuggerEngine *masterEngine, QString *error); @@ -88,7 +88,7 @@ DebuggerEngine *createQmlEngine(const DebuggerStartParameters &, DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &); DebuggerEngine *createLldbEngine(const DebuggerStartParameters &); -extern QString msgNoBinaryForToolChain(int tc); +extern QString msgNoBinaryForToolChain(const ProjectExplorer::Abi &abi); static QString msgEngineNotAvailable(const char *engine) { @@ -165,8 +165,13 @@ DebuggerEngineType DebuggerRunControlPrivate::engineForExecutable // We need the CDB debugger in order to be able to debug VS // executables. - ConfigurationCheck check = checkDebugConfiguration(ToolChain_MSVC); - if (!check) { + Abi hostAbi = Abi::hostAbi(); + ConfigurationCheck check = checkDebugConfiguration(Abi(hostAbi.architecture(), + Abi::Windows, + hostAbi.osFlavor(), + Abi::Format_PE, + hostAbi.wordWidth())); + if (!check) { m_errorMessage = check.errorMessage; m_settingsIdHint = check.settingsPage; if (enabledEngineTypes & CdbEngineType) @@ -216,38 +221,18 @@ DebuggerEngineType DebuggerRunControlPrivate::engineForMode // //////////////////////////////////////////////////////////////////////// -static DebuggerEngineType engineForToolChain(ToolChainType toolChainType) +static DebuggerEngineType engineForToolChain(const Abi &toolChain) { - switch (toolChainType) { - case ToolChain_LINUX_ICC: - case ToolChain_MinGW: - case ToolChain_GCC: - case ToolChain_WINSCW: // S60 - case ToolChain_GCCE: - case ToolChain_RVCT2_ARMV5: - case ToolChain_RVCT2_ARMV6: - case ToolChain_RVCT_ARMV5_GNUPOC: - case ToolChain_GCCE_GNUPOC: - case ToolChain_GCC_MAEMO5: - case ToolChain_GCC_HARMATTAN: - case ToolChain_GCC_MEEGO: + if (toolChain.binaryFormat() == Abi::Format_ELF || toolChain.binaryFormat() == Abi::Format_Mach_O + || (toolChain.binaryFormat() == Abi::Format_PE && toolChain.osFlavor() == Abi::Windows_msys)) { #ifdef WITH_LLDB // lldb override if (Core::ICore::instance()->settings()->value("LLDB/enabled").toBool()) return LldbEngineType; #endif return GdbEngineType; - - - case ToolChain_MSVC: - case ToolChain_WINCE: + } else if (toolChain.binaryFormat() == Abi::Format_PE && toolChain.osFlavor() != Abi::Windows_msys) { return CdbEngineType; - - case ToolChain_OTHER: - case ToolChain_UNKNOWN: - case ToolChain_INVALID: - default: - break; } return NoEngineType; } @@ -280,7 +265,7 @@ DebuggerRunControl::DebuggerRunControl(RunConfiguration *runConfiguration, else if (sp.executable.endsWith(_(".py"))) engineType = PdbEngineType; else { - engineType = engineForToolChain(sp.toolChainType); + engineType = engineForToolChain(sp.toolChainAbi); if (engineType == CdbEngineType && !(enabledEngineTypes & CdbEngineType)) { d->m_errorMessage = msgEngineNotAvailable("Cdb Engine"); engineType = NoEngineType; @@ -351,9 +336,8 @@ DebuggerRunControl::DebuggerRunControl(RunConfiguration *runConfiguration, // Could not find anything suitable. debuggingFinished(); // Create Message box with possibility to go to settings. - QString toolChainName = ToolChain::toolChainName(sp.toolChainType); - const QString msg = tr("Cannot debug '%1' (tool chain: '%2'): %3") - .arg(sp.executable, toolChainName, d->m_errorMessage); + const QString msg = tr("Cannot debug '%1' (binary format: '%2'): %3") + .arg(sp.executable, sp.toolChainAbi.toString(), d->m_errorMessage); Core::ICore::instance()->showWarningWithOptions(tr("Warning"), msg, QString(), QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY), d->m_settingsIdHint); @@ -388,37 +372,27 @@ void DebuggerRunControl::setCustomEnvironment(Utils::Environment env) d->m_engine->startParameters().environment = env; } -DEBUGGER_EXPORT ConfigurationCheck checkDebugConfiguration(ToolChainType toolChain) +ConfigurationCheck checkDebugConfiguration(const ProjectExplorer::Abi &abi) { ConfigurationCheck result; if (!(debuggerCore()->activeLanguages() & CppLanguage)) return result; - switch(toolChain) { - case ToolChain_GCC: - case ToolChain_LINUX_ICC: - case ToolChain_MinGW: - case ToolChain_WINCE: // S60 - case ToolChain_WINSCW: - case ToolChain_GCCE: - case ToolChain_RVCT2_ARMV5: - case ToolChain_RVCT2_ARMV6: - if (debuggerCore()->gdbBinaryForToolChain(toolChain).isEmpty()) { - result.errorMessage = msgNoBinaryForToolChain(toolChain); + if (abi.binaryFormat() == Abi::Format_ELF || + abi.binaryFormat() == Abi::Format_Mach_O || + (abi.binaryFormat() == Abi::Format_PE && abi.osFlavor() == Abi::Windows_msys)) { + if (debuggerCore()->gdbBinaryForAbi(abi).isEmpty()) { + result.errorMessage = msgNoBinaryForToolChain(abi); result.errorMessage += QLatin1Char(' ') + msgEngineNotAvailable("Gdb"); result.settingsPage = GdbOptionsPage::settingsId(); } - break; - case ToolChain_MSVC: - result = checkCdbConfiguration(toolChain); + } else if (abi.binaryFormat() == Abi::Format_PE && abi.osFlavor() != Abi::Windows_msys) { + result = checkCdbConfiguration(abi); if (!result) { result.errorMessage += msgEngineNotAvailable("Cdb"); result.settingsPage = QLatin1String("Cdb"); } - break; - default: - break; } if (!result && !result.settingsPage.isEmpty()) @@ -586,7 +560,7 @@ static DebuggerStartParameters localStartParameters(RunConfiguration *runConfigu sp.workingDirectory = rc->workingDirectory(); sp.executable = rc->executable(); sp.processArgs = rc->commandLineArguments(); - sp.toolChainType = rc->toolChainType(); + sp.toolChainAbi = rc->abi(); sp.useTerminal = rc->runMode() == LocalApplicationRunConfiguration::Console; sp.dumperLibrary = rc->dumperLibrary(); sp.dumperLibraryLocations = rc->dumperLibraryLocations(); @@ -644,7 +618,7 @@ DebuggerRunControl *DebuggerRunControlFactory::create { DebuggerStartParameters sp = sp0; sp.enabledEngines = m_enabledEngines; - ConfigurationCheck check = checkDebugConfiguration(sp.toolChainType); + ConfigurationCheck check = checkDebugConfiguration(sp.toolChainAbi); if (!check) { //appendMessage(errorMessage, true); diff --git a/src/plugins/debugger/debuggerrunner.h b/src/plugins/debugger/debuggerrunner.h index 76e1b5cae5..1da943d02a 100644 --- a/src/plugins/debugger/debuggerrunner.h +++ b/src/plugins/debugger/debuggerrunner.h @@ -36,8 +36,8 @@ #include "debugger_global.h" +#include <projectexplorer/abi.h> #include <projectexplorer/runconfiguration.h> -#include <projectexplorer/toolchaintype.h> #include <QtCore/QScopedPointer> @@ -68,7 +68,7 @@ public: QString settingsPage; }; -DEBUGGER_EXPORT ConfigurationCheck checkDebugConfiguration(ProjectExplorer::ToolChainType toolChain); +DEBUGGER_EXPORT ConfigurationCheck checkDebugConfiguration(const ProjectExplorer::Abi &abi); // This is a job description containing all data "local" to the jobs, including // the models of the individual debugger views. diff --git a/src/plugins/debugger/debuggerstartparameters.h b/src/plugins/debugger/debuggerstartparameters.h index 2fe82d4bc0..011042d734 100644 --- a/src/plugins/debugger/debuggerstartparameters.h +++ b/src/plugins/debugger/debuggerstartparameters.h @@ -39,7 +39,7 @@ #include <utils/ssh/sshconnection.h> #include <utils/environment.h> -#include <projectexplorer/toolchaintype.h> +#include <projectexplorer/abi.h> #include <QtCore/QMetaType> @@ -70,7 +70,6 @@ public: qmlServerPort(0), useServerStartScript(false), connParams(Utils::SshConnectionParameters::NoProxy), - toolChainType(ProjectExplorer::ToolChain_UNKNOWN), startMode(NoStartMode), executableUid(0), communicationChannel(CommunicationChannelUsb), @@ -117,7 +116,7 @@ public: Utils::SshConnectionParameters connParams; QString debuggerCommand; - ProjectExplorer::ToolChainType toolChainType; + ProjectExplorer::Abi toolChainAbi; QString qtInstallPath; QString dumperLibrary; diff --git a/src/plugins/debugger/gdb/gdbchooserwidget.cpp b/src/plugins/debugger/gdb/gdbchooserwidget.cpp index 50d84ba036..283f297222 100644 --- a/src/plugins/debugger/gdb/gdbchooserwidget.cpp +++ b/src/plugins/debugger/gdb/gdbchooserwidget.cpp @@ -52,51 +52,15 @@ #include <QtGui/QIcon> #include <QtGui/QGroupBox> #include <QtGui/QCheckBox> -#include <QtCore/QDebug> #include <QtCore/QSet> #include <QtCore/QDir> #include <QtCore/QFileInfo> #include <QtCore/QProcess> -enum { binaryRole = Qt::UserRole + 1, toolChainRole = Qt::UserRole + 2 }; -enum Columns { binaryColumn, toolChainColumn, ColumnCount }; +enum Columns { abiColumn, binaryColumn, ColumnCount }; typedef QList<QStandardItem *> StandardItemList; -Q_DECLARE_METATYPE(QList<int>) - -static QList<int> allGdbToolChains() -{ - QList<int> rc; - rc -#ifdef Q_OS_UNIX - << ProjectExplorer::ToolChain_GCC - << ProjectExplorer::ToolChain_LINUX_ICC -#endif -#ifdef Q_OS_WIN - << ProjectExplorer::ToolChain_MinGW - << ProjectExplorer::ToolChain_WINSCW - << ProjectExplorer::ToolChain_GCCE - << ProjectExplorer::ToolChain_RVCT2_ARMV5 - << ProjectExplorer::ToolChain_RVCT2_ARMV6 -#endif - << ProjectExplorer::ToolChain_GCC_MAEMO5 - << ProjectExplorer::ToolChain_GCC_HARMATTAN - << ProjectExplorer::ToolChain_GCC_MEEGO -#ifdef Q_OS_UNIX - << ProjectExplorer::ToolChain_GCCE_GNUPOC - << ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC -#endif - << ProjectExplorer::ToolChain_OTHER - << ProjectExplorer::ToolChain_UNKNOWN; - return rc; -} - -static inline QString toolChainName(int tc) -{ - return ProjectExplorer::ToolChain::toolChainName(static_cast<ProjectExplorer::ToolChainType>(tc)); -} - namespace Debugger { namespace Internal { @@ -105,6 +69,10 @@ namespace Internal { // Obtain a tooltip for a gdb binary by running --version static inline QString gdbToolTip(const QString &binary) { + if (binary.isEmpty()) + return QString(); + if (!QFileInfo(binary).exists()) + return GdbChooserWidget::tr("File not found."); QProcess process; process.start(binary, QStringList(QLatin1String("--version"))); process.closeWriteChannel(); @@ -122,37 +90,32 @@ static inline QString gdbToolTip(const QString &binary) // Provides a delayed tooltip listing the gdb version as // obtained by running it. Provides conveniences for getting/setting the maps and // for listing the toolchains used and the ones still available. - class GdbBinaryModel : public QStandardItemModel { public: - typedef GdbChooserWidget::BinaryToolChainMap BinaryToolChainMap; - explicit GdbBinaryModel(QObject * parent = 0); - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + bool setData(const QModelIndex &index, const QVariant &value, int role); // get / set data as map. - BinaryToolChainMap gdbBinaries() const; - void setGdbBinaries(const BinaryToolChainMap &m); + QMap<QString, QString> gdbMapping() const; + void setGdbMapping(const QMap<QString, QString> &m); QString binary(int row) const; - QList<int> toolChains(int row) const; + QString abi(int row) const; - QStringList binaries() const; - QList<int> usedToolChains() const; - QSet<int> unusedToolChainSet() const; - QList<int> unusedToolChains() const; + void append(const QString &abi, const QString &binary); - void append(const QString &binary, const QList<int> &toolChains); + bool isDirty() const; + static void setAbiItem(QStandardItem *item, const QString &abi); static void setBinaryItem(QStandardItem *item, const QString &binary); - static void setToolChainItem(QStandardItem *item, const QList<int> &toolChain); }; GdbBinaryModel::GdbBinaryModel(QObject *parent) : QStandardItemModel(0, ColumnCount, parent) { QStringList headers; - headers << GdbChooserWidget::tr("Binary") << GdbChooserWidget::tr("Toolchains"); + headers << GdbChooserWidget::tr("ABI") << GdbChooserWidget::tr("Debugger"); setHorizontalHeaderLabels(headers); } @@ -166,455 +129,119 @@ QVariant GdbBinaryModel::data(const QModelIndex &index, int role) const // Run the gdb and obtain the tooltip const QString tooltip = gdbToolTip(binary(index.row())); // Set on the whole row + item(index.row(), abiColumn)->setToolTip(tooltip); item(index.row(), binaryColumn)->setToolTip(tooltip); - item(index.row(), toolChainColumn)->setToolTip(tooltip); return QVariant(tooltip); } return QStandardItemModel::data(index, role); } -QStringList GdbBinaryModel::binaries() const -{ - QStringList rc; - const int binaryCount = rowCount(); - for (int b = 0; b < binaryCount; b++) - rc.push_back(binary(b)); - return rc; -} - -QList<int> GdbBinaryModel::usedToolChains() const -{ - // Loop over model and collect all toolchains. - QList<int> rc; - const int binaryCount = rowCount(); - for (int b = 0; b < binaryCount; b++) - foreach(int tc, toolChains(b)) - rc.push_back(tc); - return rc; -} - -QSet<int> GdbBinaryModel::unusedToolChainSet() const +bool GdbBinaryModel::setData(const QModelIndex &index, const QVariant &value, int role) { - const QSet<int> used = usedToolChains().toSet(); - QSet<int> all = allGdbToolChains().toSet(); - return all.subtract(used); -} - -QList<int> GdbBinaryModel::unusedToolChains() const -{ - QList<int> unused = unusedToolChainSet().toList(); - qSort(unused); - return unused; + if (index.isValid() && role == Qt::EditRole) { + Q_ASSERT(index.column() == binaryColumn); + item(index.row(), abiColumn)->setToolTip(QString()); + item(index.row(), binaryColumn)->setToolTip(QString()); + item(index.row(), binaryColumn)->setData(true); + QFont f(item(index.row(), binaryColumn)->font()); + f.setBold(true); + item(index.row(), binaryColumn)->setFont(f); + } + return QStandardItemModel::setData(index, value, role); } -GdbBinaryModel::BinaryToolChainMap GdbBinaryModel::gdbBinaries() const +QMap<QString, QString> GdbBinaryModel::gdbMapping() const { - BinaryToolChainMap rc; + QMap<QString, QString> rc; const int binaryCount = rowCount(); - for (int r = 0; r < binaryCount; r++) { - const QString bin = binary(r); - foreach(int tc, toolChains(r)) - rc.insert(bin, tc); - } + for (int r = 0; r < binaryCount; ++r) + rc.insert(abi(r), binary(r)); return rc; } -void GdbBinaryModel::setGdbBinaries(const BinaryToolChainMap &m) +void GdbBinaryModel::setGdbMapping(const QMap<QString, QString> &m) { removeRows(0, rowCount()); - foreach(const QString &binary, m.uniqueKeys()) - append(binary, m.values(binary)); + for (QMap<QString, QString>::const_iterator i = m.constBegin(); i != m.constEnd(); ++i) + append(i.key(), i.value()); } QString GdbBinaryModel::binary(int row) const { - return item(row, binaryColumn)->data(binaryRole).toString(); + return QDir::fromNativeSeparators(item(row, binaryColumn)->data(Qt::DisplayRole).toString()); } -QList<int> GdbBinaryModel::toolChains(int row) const +QString GdbBinaryModel::abi(int row) const { - const QVariant data = item(row, toolChainColumn)->data(toolChainRole); - return qVariantValue<QList<int> >(data); + return item(row, abiColumn)->data(Qt::DisplayRole).toString(); } void GdbBinaryModel::setBinaryItem(QStandardItem *item, const QString &binary) { - const QFileInfo fi(binary); - item->setText(fi.isAbsolute() ? fi.fileName() : QDir::toNativeSeparators(binary)); + item->setText(binary.isEmpty() ? QString() : QDir::toNativeSeparators(binary)); item->setToolTip(QString());; // clean out delayed tooltip - item->setData(QVariant(binary), binaryRole); - item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable); + item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsEditable); + item->setData(false); } -void GdbBinaryModel::setToolChainItem(QStandardItem *item, const QList<int> &toolChains) +void GdbBinaryModel::setAbiItem(QStandardItem *item, const QString &abi) { - // Format comma-separated list - const QString toolChainSeparator = QLatin1String(", "); - QString toolChainDesc; - const int count = toolChains.size(); - for (int i = 0; i < count; i++) { - if (i) - toolChainDesc += toolChainSeparator; - toolChainDesc += toolChainName(toolChains.at(i)); - } - - item->setText(toolChainDesc); - item->setToolTip(QString());; // clean out delayed tooltip - item->setData(qVariantFromValue(toolChains), toolChainRole); + item->setText(abi); + item->setToolTip(QString()); // clean out delayed tooltip item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable); } -void GdbBinaryModel::append(const QString &binary, const QList<int> &toolChains) +void GdbBinaryModel::append(const QString &abi, const QString &binary) { QStandardItem *binaryItem = new QStandardItem; - QStandardItem *toolChainItem = new QStandardItem; + QStandardItem *abiItem = new QStandardItem; + GdbBinaryModel::setAbiItem(abiItem, abi); GdbBinaryModel::setBinaryItem(binaryItem, binary); - GdbBinaryModel::setToolChainItem(toolChainItem, toolChains); + StandardItemList row; - row << binaryItem << toolChainItem; + row << abiItem << binaryItem; appendRow(row); } +bool GdbBinaryModel::isDirty() const +{ + for (int i = 0; i < rowCount(); ++i) { + if (item(i, binaryColumn)->data().toBool()) + return true; + } + return false; +} + // ----------- GdbChooserWidget GdbChooserWidget::GdbChooserWidget(QWidget *parent) : QWidget(parent), m_treeView(new QTreeView), - m_model(new GdbBinaryModel(m_treeView)), - m_addButton(new QToolButton), - m_deleteButton(new QToolButton), - m_dirty(false) + m_model(new GdbBinaryModel(m_treeView)) { - QHBoxLayout *mainHLayout = new QHBoxLayout; - + QVBoxLayout *layout = new QVBoxLayout(this); m_treeView->setRootIsDecorated(false); m_treeView->setModel(m_model); m_treeView->setUniformRowHeights(true); m_treeView->setAllColumnsShowFocus(true); m_treeView->setSelectionMode(QAbstractItemView::SingleSelection); - connect(m_treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), - this, SLOT(slotCurrentChanged(QModelIndex,QModelIndex))); - connect(m_treeView, SIGNAL(doubleClicked(QModelIndex)), - this, SLOT(slotDoubleClicked(QModelIndex))); - mainHLayout->addWidget(m_treeView); - - m_addButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_PLUS))); - connect(m_addButton, SIGNAL(clicked()), this, SLOT(slotAdd())); - - m_deleteButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_MINUS))); - m_deleteButton->setEnabled(false); - connect(m_deleteButton, SIGNAL(clicked()), this, SLOT(slotRemove())); - - QVBoxLayout *vButtonLayout = new QVBoxLayout; - vButtonLayout->addWidget(m_addButton); - vButtonLayout->addWidget(m_deleteButton); - vButtonLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding)); - - mainHLayout->addLayout(vButtonLayout); - setLayout(mainHLayout); -} - -QStandardItem *GdbChooserWidget::currentItem() const -{ - // Return the column-0-item - QModelIndex currentIndex = m_treeView->currentIndex(); - if (!currentIndex.isValid()) - return 0; - if (currentIndex.column() != binaryColumn) - currentIndex = currentIndex.sibling(currentIndex.row(), binaryColumn); - return m_model->itemFromIndex(currentIndex); -} - -void GdbChooserWidget::slotAdd() -{ - // Any toolchains left? - const QList<int> unusedToolChains = m_model->unusedToolChains(); - if (unusedToolChains.isEmpty()) - return; - - // On a binary or no current item: Add binary + toolchain - BinaryToolChainDialog binaryDialog(this); - binaryDialog.setToolChainChoices(unusedToolChains); - if (binaryDialog.exec() != QDialog::Accepted) - return; - // Refuse binaries that already exist - const QString path = binaryDialog.path(); - if (m_model->binaries().contains(path)) { - QMessageBox::warning(this, tr("Duplicate binary"), - tr("The binary '%1' already exists.").arg(path)); - return; - } - // Add binary + toolchain to model - m_model->append(path, binaryDialog.toolChains()); - m_dirty = true; -} - -void GdbChooserWidget::slotRemove() -{ - if (QStandardItem *item = currentItem()) - removeItem(item); -} - -void GdbChooserWidget::removeItem(QStandardItem *item) -{ - m_model->removeRow(item->row()); - m_dirty = true; -} - -void GdbChooserWidget::slotCurrentChanged(const QModelIndex ¤t, const QModelIndex &) -{ - const bool hasItem = current.isValid() && m_model->itemFromIndex(current); - m_deleteButton->setEnabled(hasItem); -} - -void GdbChooserWidget::slotDoubleClicked(const QModelIndex ¤t) -{ - QTC_ASSERT(current.isValid(), return) - // Show dialog to edit. Make all unused toolchains including the ones - // previously assigned to that binary available. - const int row = current.row(); - const QString oldBinary = m_model->binary(row); - const QList<int> oldToolChains = m_model->toolChains(row); - const QSet<int> toolChainChoices = m_model->unusedToolChainSet().unite(oldToolChains.toSet()); - - BinaryToolChainDialog dialog(this); - dialog.setPath(oldBinary); - const BinaryToolChainMap map = gdbBinaries(); - dialog.setToolChainChoices(toolChainChoices.toList(), &map); - dialog.setToolChains(oldToolChains); - if (dialog.exec() != QDialog::Accepted) - return; - // Check if anything changed. - const QString newBinary = dialog.path(); - const QList<int> newToolChains = dialog.toolChains(); - if (newBinary == oldBinary && newToolChains == oldToolChains) - return; - - GdbBinaryModel::setBinaryItem(m_model->item(row, binaryColumn), newBinary); - GdbBinaryModel::setToolChainItem(m_model->item(row, toolChainColumn), newToolChains); - m_dirty = true; + layout->addWidget(m_treeView); } -GdbChooserWidget::BinaryToolChainMap GdbChooserWidget::gdbBinaries() const +QMap<QString, QString> GdbChooserWidget::gdbMapping() const { - return m_model->gdbBinaries(); + return m_model->gdbMapping(); } -void GdbChooserWidget::setGdbBinaries(const BinaryToolChainMap &m) +void GdbChooserWidget::setGdbMapping(const QMap<QString, QString> &m) { - m_model->setGdbBinaries(m); + m_model->setGdbMapping(m); for (int c = 0; c < ColumnCount; c++) m_treeView->resizeColumnToContents(c); - m_dirty = false; } bool GdbChooserWidget::isDirty() const { - return m_dirty; -} - -void GdbChooserWidget::clearDirty() -{ - m_dirty = false; -} - -// -------------- ToolChainSelectorWidget -static const char *toolChainPropertyC = "toolChain"; - -static inline int toolChainOfCheckBox(const QCheckBox *c) -{ - return c->property(toolChainPropertyC).toInt(); -} - -static inline QVBoxLayout *createGroupBox(const QString &title, QVBoxLayout *lt) -{ - QGroupBox *gb = new QGroupBox(title); - QVBoxLayout *gbLayout = new QVBoxLayout; - gb->setLayout(gbLayout); - lt->addWidget(gb); - return gbLayout; -} - -ToolChainSelectorWidget::ToolChainSelectorWidget(QWidget *parent) : - QWidget(parent), m_valid(false) -{ - QVBoxLayout *mainLayout = new QVBoxLayout; - QVBoxLayout *desktopLayout = createGroupBox(tr("Desktop/General"), mainLayout); - QVBoxLayout *symbianLayout = createGroupBox(tr("Symbian"), mainLayout); - QVBoxLayout *maemoLayout = createGroupBox(tr("Maemo"), mainLayout); - - // Group checkboxes into categories - foreach(int tc, allGdbToolChains()) { - switch (tc) { - case ProjectExplorer::ToolChain_GCC: - case ProjectExplorer::ToolChain_LINUX_ICC: - case ProjectExplorer::ToolChain_MinGW: - case ProjectExplorer::ToolChain_OTHER: - case ProjectExplorer::ToolChain_UNKNOWN: - desktopLayout->addWidget(createToolChainCheckBox(tc)); - break; - case ProjectExplorer::ToolChain_MSVC: - case ProjectExplorer::ToolChain_WINCE: - break; - case ProjectExplorer::ToolChain_WINSCW: - case ProjectExplorer::ToolChain_GCCE: - case ProjectExplorer::ToolChain_RVCT2_ARMV5: - case ProjectExplorer::ToolChain_RVCT2_ARMV6: - case ProjectExplorer::ToolChain_GCCE_GNUPOC: - case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC: - symbianLayout->addWidget(createToolChainCheckBox(tc)); - break; - case ProjectExplorer::ToolChain_GCC_MAEMO5: - case ProjectExplorer::ToolChain_GCC_HARMATTAN: - case ProjectExplorer::ToolChain_GCC_MEEGO: - maemoLayout->addWidget(createToolChainCheckBox(tc)); - break; - case ProjectExplorer::ToolChain_INVALID: - break; - } - } - setLayout(mainLayout); -} - -QCheckBox *ToolChainSelectorWidget::createToolChainCheckBox(int tc) -{ - // Add checkbox - QCheckBox *cb = new QCheckBox(toolChainName(tc)); - cb->setProperty(toolChainPropertyC, QVariant(tc)); - connect(cb, SIGNAL(stateChanged(int)), this, SLOT(slotCheckStateChanged(int))); - m_checkBoxes.push_back(cb); - return cb; -} - -static inline QString msgDisabledToolChainToolTip(const QString &binary, int toolChain) -{ - return ToolChainSelectorWidget::tr( - "<html><head/><body><p>Another gdb binary (<i>%1</i>) is currently configured " - "to handle the toolchain <i>%2</i>.</p></body></html>"). - arg(QFileInfo(binary).fileName(), toolChainName(toolChain)); -} - -void ToolChainSelectorWidget::setEnabledToolChains(const QList<int> &enabled, - const BinaryToolChainMap *binaryToolChainMap) -{ - foreach(QCheckBox *cb, m_checkBoxes) { - const int toolChain = toolChainOfCheckBox(cb); - if (enabled.contains(toolChain)) { - cb->setToolTip(QString()); - } else { - // Toolchain is handled by a different binary, hint to user. - cb->setEnabled(false); - const QString binary = binaryToolChainMap ? binaryToolChainMap->key(toolChain) : QString(); - if (!binary.isEmpty()) - cb->setToolTip(msgDisabledToolChainToolTip(binary, toolChain)); - } - } -} - -void ToolChainSelectorWidget::setCheckedToolChains(const QList<int> &checked) -{ - foreach(QCheckBox *cb, m_checkBoxes) - if (checked.contains(toolChainOfCheckBox(cb))) - cb->setChecked(true); - // Trigger 'valid changed' - slotCheckStateChanged(checked.isEmpty() ? Qt::Unchecked : Qt::Checked); -} - -QList<int> ToolChainSelectorWidget::checkedToolChains() const -{ - QList<int> rc; - foreach(const QCheckBox *cb, m_checkBoxes) - if (cb->isChecked()) - rc.push_back(toolChainOfCheckBox(cb)); - return rc; -} - -bool ToolChainSelectorWidget::isValid() const -{ - return m_valid; -} - -void ToolChainSelectorWidget::slotCheckStateChanged(int state) -{ - // Emit signal if valid state changed - const bool newValid = state == Qt::Checked || hasCheckedToolChain(); - if (newValid != m_valid) { - m_valid = newValid; - emit validChanged(m_valid); - } -} - -bool ToolChainSelectorWidget::hasCheckedToolChain() const -{ - foreach(const QCheckBox *cb, m_checkBoxes) - if (cb->isChecked()) - return true; - return false; -} - -// -------------- ToolChainDialog -BinaryToolChainDialog::BinaryToolChainDialog(QWidget *parent) : - QDialog(parent), - m_toolChainSelector(new ToolChainSelectorWidget), - m_mainLayout(new QFormLayout), - m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel)), - m_pathChooser(new Utils::PathChooser) -{ - - setModal(true); - setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); - setWindowTitle(tr("Select binary and toolchains")); - - m_pathChooser->setExpectedKind(Utils::PathChooser::ExistingCommand); - m_pathChooser->setPromptDialogTitle(tr("Gdb binary")); - connect(m_pathChooser, SIGNAL(validChanged()), this, SLOT(slotValidChanged())); - m_mainLayout->addRow(tr("Path:"), m_pathChooser); - - connect(m_toolChainSelector, SIGNAL(validChanged(bool)), this, SLOT(slotValidChanged())); - m_mainLayout->addRow(m_toolChainSelector); - - connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(accept())); - connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject())); - m_mainLayout->addRow(m_buttonBox); - setLayout(m_mainLayout); - - setOkButtonEnabled(false); - m_pathChooser->setFocus(); -} - -void BinaryToolChainDialog::setToolChainChoices(const QList<int> &tcs, - const BinaryToolChainMap *binaryToolChainMap) -{ - m_toolChainSelector->setEnabledToolChains(tcs, binaryToolChainMap); -} - -void BinaryToolChainDialog::setToolChains(const QList<int> &tcs) -{ - m_toolChainSelector->setCheckedToolChains(tcs); -} - -QList<int> BinaryToolChainDialog::toolChains() const -{ - return m_toolChainSelector->checkedToolChains(); -} - -void BinaryToolChainDialog::setOkButtonEnabled(bool v) -{ - m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(v); -} - -void BinaryToolChainDialog::setPath(const QString &p) -{ - m_pathChooser->setPath(p); -} - -QString BinaryToolChainDialog::path() const -{ - return m_pathChooser->rawPath(); -} - -void BinaryToolChainDialog::slotValidChanged() -{ - setOkButtonEnabled(m_pathChooser->isValid() && m_toolChainSelector->isValid()); + return m_model->isDirty(); } } // namespace Internal diff --git a/src/plugins/debugger/gdb/gdbchooserwidget.h b/src/plugins/debugger/gdb/gdbchooserwidget.h index da62e60dda..45f20eacb5 100644 --- a/src/plugins/debugger/gdb/gdbchooserwidget.h +++ b/src/plugins/debugger/gdb/gdbchooserwidget.h @@ -67,96 +67,17 @@ class GdbChooserWidget : public QWidget public: explicit GdbChooserWidget(QWidget *parent = 0); - typedef QMultiMap<QString, int> BinaryToolChainMap; - - BinaryToolChainMap gdbBinaries() const; - void setGdbBinaries(const BinaryToolChainMap &m); + QMap<QString, QString> gdbMapping() const; + void setGdbMapping(const QMap<QString, QString> &m); bool isDirty() const; -public slots: - void clearDirty(); - -private slots: - void slotAdd(); - void slotRemove(); - void slotCurrentChanged(const QModelIndex ¤t, const QModelIndex & previous); - void slotDoubleClicked(const QModelIndex ¤t); - private: void removeItem(QStandardItem *item); QToolButton *createAddToolMenuButton(); - QStandardItem *currentItem() const; QTreeView *m_treeView; GdbBinaryModel *m_model; - QToolButton *m_addButton; - QToolButton *m_deleteButton; - bool m_dirty; -}; - -// Present toolchains with checkboxes grouped in QGroupBox panes -// and provide valid-handling. Unavailabe toolchains can be grayed -// out using setEnabledToolChains(). -class ToolChainSelectorWidget : public QWidget { - Q_OBJECT -public: - typedef GdbChooserWidget::BinaryToolChainMap BinaryToolChainMap; - - explicit ToolChainSelectorWidget(QWidget *parent = 0); - - void setEnabledToolChains(const QList<int> &enabled, - // Optionally used for generating a tooltip for the disabled check boxes - const BinaryToolChainMap *binaryToolChainMap = 0); - - void setCheckedToolChains(const QList<int> &); - QList<int> checkedToolChains() const; - - bool isValid() const; - -signals: - void validChanged(bool); - -private slots: - void slotCheckStateChanged(int); - -private: - bool hasCheckedToolChain() const; - QCheckBox *createToolChainCheckBox(int tc); - - QList<QCheckBox*> m_checkBoxes; - bool m_valid; -}; - -// Internal helper dialog for selecting a binary and its -// associated toolchains. -class BinaryToolChainDialog : public QDialog { - Q_OBJECT -public: - typedef GdbChooserWidget::BinaryToolChainMap BinaryToolChainMap; - - explicit BinaryToolChainDialog(QWidget *parent); - - void setToolChainChoices(const QList<int> &, - // Optionally used for generating a tooltip for the disabled check boxes - const BinaryToolChainMap *binaryToolChainMap = 0); - - void setToolChains(const QList<int> &); - QList<int> toolChains() const; - - void setPath(const QString &); - QString path() const; - -private slots: - void slotValidChanged(); - -private: - void setOkButtonEnabled(bool e); - - ToolChainSelectorWidget *m_toolChainSelector; - QFormLayout *m_mainLayout; - QDialogButtonBox *m_buttonBox; - Utils::PathChooser *m_pathChooser; }; } // namespace Internal diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index dce1d60f1b..c9030ece63 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1795,36 +1795,29 @@ int GdbEngine::currentFrame() const return stackHandler()->currentIndex(); } -QString msgNoBinaryForToolChain(int tc) +QString msgNoBinaryForToolChain(const ProjectExplorer::Abi &tc) { using namespace ProjectExplorer; - return GdbEngine::tr("There is no gdb binary available for '%1'.") - .arg(ToolChain::toolChainName(ToolChainType(tc))); + return GdbEngine::tr("There is no gdb binary available for binaries in format '%1'") + .arg(tc.toString()); } AbstractGdbAdapter *GdbEngine::createAdapter() { const DebuggerStartParameters &sp = startParameters(); - switch (sp.toolChainType) { - case ProjectExplorer::ToolChain_WINSCW: // S60 - case ProjectExplorer::ToolChain_GCCE: - case ProjectExplorer::ToolChain_RVCT2_ARMV5: - case ProjectExplorer::ToolChain_RVCT2_ARMV6: - case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC: - case ProjectExplorer::ToolChain_GCCE_GNUPOC: + if (sp.toolChainAbi.os() == ProjectExplorer::Abi::Symbian) { + // FIXME: 1 of 3 testing hacks. if (sp.debugClient == DebuggerStartParameters::DebugClientCoda) return new CodaGdbAdapter(this); else return new TrkGdbAdapter(this); - default: - break; } switch (sp.startMode) { case AttachCore: return new CoreGdbAdapter(this); case AttachToRemote: - return new RemoteGdbServerAdapter(this, sp.toolChainType); + return new RemoteGdbServerAdapter(this, sp.toolChainAbi); case StartRemoteGdb: return new RemotePlainGdbAdapter(this); case AttachExternal: @@ -4220,12 +4213,12 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const DebuggerStartParameters &sp = startParameters(); m_gdb = QString::fromLocal8Bit(qgetenv("QTC_DEBUGGER_PATH")); if (m_gdb.isEmpty() && sp.startMode != StartRemoteGdb) - m_gdb = debuggerCore()->gdbBinaryForToolChain(sp.toolChainType); + m_gdb = debuggerCore()->gdbBinaryForAbi(startParameters().toolChainAbi); if (m_gdb.isEmpty()) m_gdb = gdb; if (m_gdb.isEmpty()) { handleAdapterStartFailed( - msgNoBinaryForToolChain(sp.toolChainType), + msgNoBinaryForToolChain(sp.toolChainAbi), GdbOptionsPage::settingsId()); return false; } diff --git a/src/plugins/debugger/gdb/gdboptionspage.cpp b/src/plugins/debugger/gdb/gdboptionspage.cpp index 46f69c72f8..8f64c46f9f 100644 --- a/src/plugins/debugger/gdb/gdboptionspage.cpp +++ b/src/plugins/debugger/gdb/gdboptionspage.cpp @@ -37,8 +37,8 @@ #include <coreplugin/icore.h> #include <projectexplorer/projectexplorer.h> -#include <projectexplorer/toolchain.h> -#include <projectexplorer/toolchaintype.h> +#include <projectexplorer/toolchainmanager.h> +#include <projectexplorer/abi.h> #include <QtCore/QCoreApplication> #include <QtCore/QTextStream> @@ -47,22 +47,37 @@ namespace Debugger { namespace Internal { -const char gdbBinariesSettingsGroupC[] = "GdbBinaries"; -const char debugModeGdbBinaryKeyC[] = "GdbBinary"; +static const char *GDB_MAPPING_ARRAY = "GdbMapping"; +static const char *GDB_ABI_KEY = "Abi"; +static const char *GDB_BINARY_KEY = "Binary"; -GdbOptionsPage::GdbBinaryToolChainMap GdbOptionsPage::gdbBinaryToolChainMap; -bool GdbOptionsPage::gdbBinariesChanged = true; +GdbOptionsPage::GdbBinaryToolChainMap GdbOptionsPage::abiToGdbMap; +bool GdbOptionsPage::gdbMappingChanged = true; -void GdbOptionsPage::readGdbBinarySettings() /* static */ +void GdbOptionsPage::readGdbSettings() /* static */ { + // FIXME: Convert old settings! using namespace ProjectExplorer; QSettings *settings = Core::ICore::instance()->settings(); - // Convert gdb binaries from flat settings list (see writeSettings) - // into map ("binary1=gdb,1,2", "binary2=symbian_gdb,3,4"). - gdbBinaryToolChainMap.clear(); + + abiToGdbMap.clear(); + + int size = settings->beginReadArray(GDB_MAPPING_ARRAY); + for (int i = 0; i < size; ++i) { + settings->setArrayIndex(i); + ProjectExplorer::Abi abi(settings->value(GDB_ABI_KEY).toString()); + if (!abi.isValid()) + continue; + QString binary = settings->value(GDB_BINARY_KEY).toString(); + if (binary.isEmpty()) + continue; + abiToGdbMap.insert(abi.toString(), binary); + } + settings->endArray(); + + // Map old settings (pre 2.2): const QChar separator = QLatin1Char(','); - const QString keyRoot = QLatin1String(gdbBinariesSettingsGroupC) + QLatin1Char('/') + - QLatin1String(debugModeGdbBinaryKeyC); + const QString keyRoot = QLatin1String("GdbBinaries/GdbBinaries"); for (int i = 1; ; i++) { const QString value = settings->value(keyRoot + QString::number(i)).toString(); if (value.isEmpty()) @@ -71,81 +86,116 @@ void GdbOptionsPage::readGdbBinarySettings() /* static */ QStringList tokens = value.split(separator); if (tokens.size() < 2) break; + const QString binary = tokens.front(); // Skip non-existent absolute binaries allowing for upgrades by the installer. // Force a rewrite of the settings file. const QFileInfo binaryInfo(binary); if (binaryInfo.isAbsolute() && !binaryInfo.isExecutable()) { - gdbBinariesChanged = true; const QString msg = QString::fromLatin1("Warning: The gdb binary '%1' does not exist, skipping.\n").arg(binary); qWarning("%s", qPrintable(msg)); continue; } + // Create entries for all toolchains. tokens.pop_front(); foreach (const QString &t, tokens) { // Paranoia: Check if the there is already a binary configured for the toolchain. - const int toolChain = t.toInt(); - const QString predefinedGdb = gdbBinaryToolChainMap.key(toolChain); - if (predefinedGdb.isEmpty()) { - gdbBinaryToolChainMap.insert(binary, toolChain); - } else { - const QString toolChainName = - ProjectExplorer::ToolChain::toolChainName(ToolChainType(toolChain)); - const QString msg = - QString::fromLatin1("An inconsistency has been encountered in the Ini-file '%1':\n" - "Skipping gdb binary '%2' for toolchain '%3' as '%4' is already configured for it."). - arg(settings->fileName(), binary, toolChainName, predefinedGdb); - qWarning("%s", qPrintable(msg)); + QString abi; + switch (t.toInt()) + { + case 0: // GCC + case 1: // Linux ICC +#ifndef Q_OS_WIN + abi = ProjectExplorer::Abi::hostAbi().toString(); +#endif + break; + case 2: // MinGW + case 3: // MSVC + case 4: // WINCE +#ifdef Q_OS_WIN + abi = ProjectExplorer::Abi::hostAbi().toString(); +#endif + break; + case 5: // WINSCW + abi = ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Symbian, + ProjectExplorer::Abi::Symbian_emulator, + ProjectExplorer::Abi::Format_ELF, + 32).toString(); + break; + case 6: // GCCE + case 7: // RVCT 2, ARM v5 + case 8: // RVCT 2, ARM v6 + case 11: // RVCT GNUPOC + case 12: // RVCT 4, ARM v5 + case 13: // RVCT 4, ARM v6 + abi = ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Symbian, + ProjectExplorer::Abi::Symbian_device, + ProjectExplorer::Abi::Format_ELF, + 32).toString(); + break; + case 9: // GCC Maemo5 + abi = ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Linux, + ProjectExplorer::Abi::Linux_maemo, + ProjectExplorer::Abi::Format_ELF, + 32).toString(); + + break; + case 14: // GCC Harmattan + abi = ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Linux, + ProjectExplorer::Abi::Linux_harmattan, + ProjectExplorer::Abi::Format_ELF, + 32).toString(); + break; + case 15: // GCC Meego + abi = ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Linux, + ProjectExplorer::Abi::Linux_meego, + ProjectExplorer::Abi::Format_ELF, + 32).toString(); + break; + default: + break; } + if (abi.isEmpty() || abiToGdbMap.contains(abi)) + continue; + + abiToGdbMap.insert(abi, binary); } } - // Linux defaults -#ifdef Q_OS_UNIX - if (gdbBinaryToolChainMap.isEmpty()) { - const QString gdb = QLatin1String("gdb"); - gdbBinaryToolChainMap.insert(gdb, ToolChain_GCC); - gdbBinaryToolChainMap.insert(gdb, ToolChain_LINUX_ICC); - gdbBinaryToolChainMap.insert(gdb, ToolChain_OTHER); - gdbBinaryToolChainMap.insert(gdb, ToolChain_UNKNOWN); - } -#endif + + gdbMappingChanged = false; } -void GdbOptionsPage::writeGdbBinarySettings() /* static */ +void GdbOptionsPage::writeGdbSettings() /* static */ { + // FIXME: This should actually get called in response to ICore::saveSettingsRequested() + if (!gdbMappingChanged) + return; + QSettings *settings = Core::ICore::instance()->settings(); - // Convert gdb binaries map into a flat settings list of - // ("binary1=gdb,1,2", "binary2=symbian_gdb,3,4"). It needs to be ASCII for installers - QString lastBinary; - QStringList settingsList; - const QChar separator = QLatin1Char(','); - const GdbBinaryToolChainMap::const_iterator cend = gdbBinaryToolChainMap.constEnd(); - for (GdbBinaryToolChainMap::const_iterator it = gdbBinaryToolChainMap.constBegin(); it != cend; ++it) { - if (it.key() != lastBinary) { - lastBinary = it.key(); // Start new entry with first toolchain - settingsList.push_back(lastBinary); - } - settingsList.back().append(separator); // Append toolchain to last binary - settingsList.back().append(QString::number(it.value())); + + settings->beginWriteArray(GDB_MAPPING_ARRAY); + + int index = 0; + for (QMap<QString, QString>::const_iterator i = abiToGdbMap.constBegin(); + i != abiToGdbMap.constEnd(); ++i) { + if (i.value().isEmpty()) + continue; + + settings->setArrayIndex(index); + ++index; + + settings->setValue(GDB_ABI_KEY, i.key()); + settings->setValue(GDB_BINARY_KEY, i.value()); } - // Terminate settings list by an empty element such that consecutive keys resulting - // from ini-file merging are suppressed while reading. - settingsList.push_back(QString()); - // Write out list - settings->beginGroup(QLatin1String(gdbBinariesSettingsGroupC)); - settings->remove(QString()); // remove all keys in group. - const int count = settingsList.size(); - const QString keyRoot = QLatin1String(debugModeGdbBinaryKeyC); - for (int i = 0; i < count; i++) - settings->setValue(keyRoot + QString::number(i + 1), settingsList.at(i)); - settings->endGroup(); + settings->endArray(); + + gdbMappingChanged = false; } GdbOptionsPage::GdbOptionsPage() : m_ui(0) -{ -} +{ } QString GdbOptionsPage::settingsId() { @@ -174,10 +224,41 @@ QIcon GdbOptionsPage::categoryIcon() const QWidget *GdbOptionsPage::createPage(QWidget *parent) { + // Fix up abi mapping now that the ToolChainManager is available: + connect(ProjectExplorer::ToolChainManager::instance(), SIGNAL(toolChainAdded(ProjectExplorer::ToolChain*)), + this, SLOT(handleToolChainAdditions(ProjectExplorer::ToolChain*))); + connect(ProjectExplorer::ToolChainManager::instance(), SIGNAL(toolChainRemoved(ProjectExplorer::ToolChain*)), + this, SLOT(handleToolChainRemovals(ProjectExplorer::ToolChain*))); + + // Update mapping now that toolchains are available + QList<ProjectExplorer::ToolChain *> tcs = + ProjectExplorer::ToolChainManager::instance()->toolChains(); + + QStringList abiList; + foreach (ProjectExplorer::ToolChain *tc, tcs) { + const QString abi = tc->targetAbi().toString(); + if (!abiList.contains(abi)) + abiList.append(abi); + if (!abiToGdbMap.contains(abi)) + handleToolChainAdditions(tc); + } + + QStringList toRemove; + for (QMap<QString, QString>::const_iterator i = abiToGdbMap.constBegin(); + i != abiToGdbMap.constEnd(); ++i) { + if (!abiList.contains(i.key())) + toRemove.append(i.key()); + } + + foreach (const QString &key, toRemove) + abiToGdbMap.remove(key); + + // Actual page setup: QWidget *w = new QWidget(parent); m_ui = new Ui::GdbOptionsPage; m_ui->setupUi(w); - m_ui->gdbChooserWidget->setGdbBinaries(gdbBinaryToolChainMap); + m_ui->gdbChooserWidget->setGdbMapping(abiToGdbMap); + m_ui->scriptFileChooser->setExpectedKind(Utils::PathChooser::File); m_ui->scriptFileChooser->setPromptDialogTitle(tr("Choose Location of Startup Script File")); @@ -201,18 +282,7 @@ QWidget *GdbOptionsPage::createPage(QWidget *parent) m_ui->checkBoxEnableReverseDebugging); m_group.insert(debuggerCore()->action(GdbWatchdogTimeout), 0); -#if 1 m_ui->groupBoxPluginDebugging->hide(); -#else // The related code (handleAqcuiredInferior()) is disabled as well. - m_group.insert(debuggerCore()->action(AllPluginBreakpoints), - m_ui->radioButtonAllPluginBreakpoints); - m_group.insert(debuggerCore()->action(SelectedPluginBreakpoints), - m_ui->radioButtonSelectedPluginBreakpoints); - m_group.insert(debuggerCore()->action(NoPluginBreakpoints), - m_ui->radioButtonNoPluginBreakpoints); - m_group.insert(debuggerCore()->action(SelectedPluginBreakpointsPattern), - m_ui->lineEditSelectedPluginBreakpointsPattern); -#endif m_ui->lineEditSelectedPluginBreakpointsPattern-> setEnabled(debuggerCore()->action(SelectedPluginBreakpoints)->value().toBool()); @@ -246,11 +316,12 @@ void GdbOptionsPage::apply() { if (!m_ui) // page never shown return; + m_group.apply(Core::ICore::instance()->settings()); if (m_ui->gdbChooserWidget->isDirty()) { - gdbBinariesChanged = true; - gdbBinaryToolChainMap = m_ui->gdbChooserWidget->gdbBinaries(); - m_ui->gdbChooserWidget->clearDirty(); + abiToGdbMap = m_ui->gdbChooserWidget->gdbMapping(); + m_ui->gdbChooserWidget->setGdbMapping(abiToGdbMap); + gdbMappingChanged = true; } } @@ -268,5 +339,37 @@ bool GdbOptionsPage::matches(const QString &s) const return m_searchKeywords.contains(s, Qt::CaseInsensitive); } +void GdbOptionsPage::handleToolChainAdditions(ProjectExplorer::ToolChain *tc) +{ + ProjectExplorer::Abi tcAbi = tc->targetAbi(); + + if (tcAbi.binaryFormat() != ProjectExplorer::Abi::Format_ELF + && tcAbi.binaryFormat() != ProjectExplorer::Abi::Format_Mach_O + && !( tcAbi.os() == ProjectExplorer::Abi::Windows + && tcAbi.osFlavor() == ProjectExplorer::Abi::Windows_msys )) + return; + if (abiToGdbMap.contains(tcAbi.toString())) + return; + + QString binary; +#ifdef Q_OS_UNIX + ProjectExplorer::Abi hostAbi = ProjectExplorer::Abi::hostAbi(); + if (hostAbi == tcAbi) + binary = QLatin1String("gdb"); +#endif + abiToGdbMap.insert(tc->targetAbi().toString(), binary); +} + +void GdbOptionsPage::handleToolChainRemovals(ProjectExplorer::ToolChain *tc) +{ + QList<ProjectExplorer::ToolChain *> tcs = ProjectExplorer::ToolChainManager::instance()->toolChains(); + foreach (ProjectExplorer::ToolChain *current, tcs) { + if (current->targetAbi() == tc->targetAbi()) + return; + } + + abiToGdbMap.remove(tc->targetAbi().toString()); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/gdb/gdboptionspage.h b/src/plugins/debugger/gdb/gdboptionspage.h index faf28cdcc3..3a7c9a2c74 100644 --- a/src/plugins/debugger/gdb/gdboptionspage.h +++ b/src/plugins/debugger/gdb/gdboptionspage.h @@ -39,6 +39,10 @@ #include <coreplugin/dialogs/ioptionspage.h> #include <utils/savedaction.h> +namespace ProjectExplorer { +class ToolChain; +} // namespace ProjectExplorer + namespace Debugger { namespace Internal { @@ -61,11 +65,15 @@ public: static QString settingsId(); - typedef QMultiMap<QString, int> GdbBinaryToolChainMap; - static GdbBinaryToolChainMap gdbBinaryToolChainMap; - static bool gdbBinariesChanged; - static void readGdbBinarySettings(); - static void writeGdbBinarySettings(); + typedef QMap<QString, QString> GdbBinaryToolChainMap; + static GdbBinaryToolChainMap abiToGdbMap; + static bool gdbMappingChanged; + static void readGdbSettings(); + static void writeGdbSettings(); + +private slots: + static void handleToolChainAdditions(ProjectExplorer::ToolChain *); + static void handleToolChainRemovals(ProjectExplorer::ToolChain *); private: Ui::GdbOptionsPage *m_ui; diff --git a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp index 13b8a208f5..fcef41aca1 100644 --- a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp +++ b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp @@ -41,7 +41,7 @@ #include <utils/qtcassert.h> #include <utils/fancymainwindow.h> -#include <projectexplorer/toolchaintype.h> +#include <projectexplorer/abi.h> #include <QtCore/QFileInfo> #include <QtGui/QMessageBox> @@ -59,9 +59,11 @@ namespace Internal { // /////////////////////////////////////////////////////////////////////// -RemoteGdbServerAdapter::RemoteGdbServerAdapter(GdbEngine *engine, int toolChainType, QObject *parent) : +RemoteGdbServerAdapter::RemoteGdbServerAdapter(GdbEngine *engine, + const ProjectExplorer::Abi &abi, + QObject *parent) : AbstractGdbAdapter(engine, parent), - m_toolChainType(toolChainType) + m_abi(abi) { connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)), SLOT(uploadProcError(QProcess::ProcessError))); @@ -75,21 +77,10 @@ RemoteGdbServerAdapter::RemoteGdbServerAdapter(GdbEngine *engine, int toolChainT AbstractGdbAdapter::DumperHandling RemoteGdbServerAdapter::dumperHandling() const { - switch (m_toolChainType) { - case ProjectExplorer::ToolChain_MinGW: - case ProjectExplorer::ToolChain_MSVC: - case ProjectExplorer::ToolChain_WINCE: - case ProjectExplorer::ToolChain_WINSCW: - case ProjectExplorer::ToolChain_GCCE: - case ProjectExplorer::ToolChain_RVCT2_ARMV5: - case ProjectExplorer::ToolChain_RVCT2_ARMV6: - case ProjectExplorer::ToolChain_GCC_MAEMO5: - case ProjectExplorer::ToolChain_GCC_HARMATTAN: - case ProjectExplorer::ToolChain_GCC_MEEGO: + if (m_abi.os() == ProjectExplorer::Abi::Symbian + || m_abi.os() == ProjectExplorer::Abi::Windows + || m_abi.binaryFormat() == ProjectExplorer::Abi::Format_ELF) return DumperLoadedByGdb; - default: - break; - } return DumperLoadedByGdbPreload; } diff --git a/src/plugins/debugger/gdb/remotegdbserveradapter.h b/src/plugins/debugger/gdb/remotegdbserveradapter.h index 342def5eb5..9c27b2ec44 100644 --- a/src/plugins/debugger/gdb/remotegdbserveradapter.h +++ b/src/plugins/debugger/gdb/remotegdbserveradapter.h @@ -37,6 +37,8 @@ #include "abstractgdbadapter.h" #include "localgdbprocess.h" +#include <projectexplorer/abi.h> + namespace Debugger { namespace Internal { @@ -51,7 +53,7 @@ class RemoteGdbServerAdapter : public AbstractGdbAdapter Q_OBJECT public: - RemoteGdbServerAdapter(GdbEngine *engine, int toolChainType, QObject *parent = 0); + RemoteGdbServerAdapter(GdbEngine *engine, const ProjectExplorer::Abi &abi, QObject *parent = 0); private: DumperHandling dumperHandling() const; @@ -93,7 +95,7 @@ private: void handleTargetRemote(const GdbResponse &response); void handleInterruptInferior(const GdbResponse &response); - const int m_toolChainType; + const ProjectExplorer::Abi m_abi; QProcess m_uploadProc; LocalGdbProcess m_gdbProc; |