diff options
author | hjk <hjk121@nokiamail.com> | 2013-10-17 12:48:16 +0200 |
---|---|---|
committer | hjk <hjk121@nokiamail.com> | 2013-10-17 16:30:15 +0200 |
commit | 16cf6177d8639e722f6419ece6bbc39bf6d8e373 (patch) | |
tree | fc00bfe9c56a18c33af5e5a24ebfeca85bf670fc /src/plugins/debugger | |
parent | ed9752bc0a78dd840a1f110823e0239976ede463 (diff) | |
download | qt-creator-16cf6177d8639e722f6419ece6bbc39bf6d8e373.tar.gz |
Debugger: Rework detection of SDK-specified "auto" debuggers
Change-Id: I173752a41da7b34d64cb7e3e423992be464fc73b
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
Diffstat (limited to 'src/plugins/debugger')
-rw-r--r-- | src/plugins/debugger/debuggerkitconfigwidget.cpp | 313 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerkitinformation.cpp | 36 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerkitinformation.h | 8 |
3 files changed, 181 insertions, 176 deletions
diff --git a/src/plugins/debugger/debuggerkitconfigwidget.cpp b/src/plugins/debugger/debuggerkitconfigwidget.cpp index c2955fa798..fead22df0a 100644 --- a/src/plugins/debugger/debuggerkitconfigwidget.cpp +++ b/src/plugins/debugger/debuggerkitconfigwidget.cpp @@ -86,20 +86,104 @@ DebuggerKitInformation::DebuggerKitInformation() QVariant DebuggerKitInformation::defaultValue(Kit *k) const { -// This is only called from Kit::Kit() -// if (isValidDebugger(k)) { -// DebuggerItem *item = DebuggerItemManager::debuggerFromKit(k); -// QTC_ASSERT(item, return QVariant()); -// return item->id; -// } - ToolChain *tc = ToolChainKitInformation::toolChain(k); - return DebuggerItemManager::defaultDebugger(tc); + QTC_ASSERT(tc, return QVariant()); + + const Abi toolChainAbi = tc->targetAbi(); + foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) + foreach (const Abi targetAbi, item.abis()) + if (targetAbi.isCompatibleWith(toolChainAbi)) + return item.id(); + + return QVariant(); } void DebuggerKitInformation::setup(Kit *k) { - k->setValue(DebuggerKitInformation::id(), defaultValue(k)); + // Get one of the available debugger matching the kit's toolchain. + const ToolChain *tc = ToolChainKitInformation::toolChain(k); + const Abi toolChainAbi = tc ? tc->targetAbi() : Abi::hostAbi(); + + // This can be anything (Id, binary path, "auto") + const QVariant rawId = k->value(DebuggerKitInformation::id()); + + enum { + NotDetected, DetectedAutomatically, DetectedByFile, DetectedById + } detection = NotDetected; + DebuggerEngineType autoEngine = NoEngineType; + FileName fileName; + + // With 3.0 we have: + // <value type="QString" key="Debugger.Information">{75ecf347-f221-44c3-b613-ea1d29929cd4}</value> + // Before we had: + // <valuemap type="QVariantMap" key="Debugger.Information"> + // <value type="QString" key="Binary">/data/dev/debugger/gdb-git/gdb/gdb</value> + // <value type="int" key="EngineType">1</value> + // </valuemap> + // Or for force auto-detected CDB + // <valuemap type="QVariantMap" key="Debugger.Information"> + // <value type="QString" key="Binary">auto</value> + // <value type="int" key="EngineType">4</value> + // </valuemap> + + if (rawId.type() == QVariant::String) { + detection = DetectedById; + } else { + QMap<QString, QVariant> map = rawId.toMap(); + QString binary = map.value(QLatin1String("Binary")).toString(); + if (binary == QLatin1String("auto")) { + detection = DetectedAutomatically; + autoEngine = DebuggerEngineType(map.value(QLatin1String("EngineType")).toInt()); + } else { + detection = DetectedByFile; + fileName = FileName::fromUserInput(binary); + } + } + + QTC_CHECK(detection != NotDetected); + + const DebuggerItem *bestItem = 0; + DebuggerItem::MatchLevel bestLevel = DebuggerItem::DoesNotMatch; + foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) { + const DebuggerItem *goodItem = 0; + if (detection == DetectedById && item.id() == rawId) + goodItem = &item; + if (detection == DetectedByFile && item.command() == fileName) + goodItem = &item; + if (detection == DetectedAutomatically && item.engineType() == autoEngine) + goodItem = &item; + + if (goodItem) { + DebuggerItem::MatchLevel level = goodItem->matchTarget(toolChainAbi); + if (level > bestLevel) { + bestLevel = level; + bestItem = goodItem; + } + } + } + + // If we have an existing debugger with matching id _and_ + // matching target ABI we are fine. + if (bestItem) { + k->setValue(DebuggerKitInformation::id(), bestItem->id()); + return; + } + + // We didn't find an existing debugger that matched by whatever + // data we found in the kit (i.e. no id, filename, "auto") + // (or what we found did not match ABI-wise) + // Let's try to pick one with matching ABI. + QVariant bestId; + bestLevel = DebuggerItem::DoesNotMatch; + foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) { + DebuggerItem::MatchLevel level = item.matchTarget(toolChainAbi); + if (level > bestLevel) { + bestLevel = level; + bestId = item.id(); + } + } + + k->setValue(DebuggerKitInformation::id(), bestId); } // Check the configuration errors and return a flag mask. Provide a quick check and @@ -145,57 +229,9 @@ static unsigned debuggerConfigurationErrors(const Kit *k) const DebuggerItem *DebuggerKitInformation::debugger(const Kit *kit) { - if (!kit) - return 0; - + QTC_ASSERT(kit, return 0); const QVariant id = kit->value(DebuggerKitInformation::id()); - - enum Detection { NotDetected, DetectedAutomatically, DetectedByFile, DetectedById }; - Detection detection = NotDetected; - - DebuggerEngineType autoEngine = NoEngineType; - - FileName fileName; - - // With 3.0 we have: - // <value type="QString" key="Debugger.Information">{75ecf347-f221-44c3-b613-ea1d29929cd4}</value> - // Before we had: - // <valuemap type="QVariantMap" key="Debugger.Information"> - // <value type="QString" key="Binary">/data/dev/debugger/gdb-git/gdb/gdb</value> - // <value type="int" key="EngineType">1</value> - // </valuemap> - // Or for force auto-detected CDB - // <valuemap type="QVariantMap" key="Debugger.Information"> - // <value type="QString" key="Binary">auto</value> - // <value type="int" key="EngineType">4</value> - // </valuemap> - - if (id.type() == QVariant::String) { - detection = DetectedById; - } else { - QMap<QString, QVariant> map = id.toMap(); - QString binary = map.value(QLatin1String("Binary")).toString(); - if (binary == QLatin1String("auto")) { - detection = DetectedAutomatically; - autoEngine = DebuggerEngineType(map.value(QLatin1String("EngineType")).toInt()); - } else { - detection = DetectedByFile; - fileName = FileName::fromUserInput(binary); - } - } - - QTC_CHECK(detection != NotDetected); - - foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) { - if (detection == DetectedById && item.id() == id) - return &item; - if (detection == DetectedByFile && item.command() == fileName) - return &item; - if (detection == DetectedAutomatically && item.engineType() == autoEngine) - return &item; - } - - return 0; + return DebuggerItemManager::findById(id); } bool DebuggerKitInformation::isValidDebugger(const Kit *k) @@ -297,32 +333,39 @@ static FileName userSettingsFileName() return FileName::fromString(settingsLocation.absolutePath() + QLatin1String(DEBUGGER_FILENAME)); } -static QList<DebuggerItem> readDebuggers(const FileName &fileName) +static void readDebuggers(const FileName &fileName, bool isSystem) { - QList<DebuggerItem> result; - PersistentSettingsReader reader; if (!reader.load(fileName)) - return result; + return; QVariantMap data = reader.restoreValues(); // Check version int version = data.value(QLatin1String(DEBUGGER_FILE_VERSION_KEY), 0).toInt(); if (version < 1) - return result; + return; int count = data.value(QLatin1String(DEBUGGER_COUNT_KEY), 0).toInt(); for (int i = 0; i < count; ++i) { const QString key = QString::fromLatin1(DEBUGGER_DATA_KEY) + QString::number(i); if (!data.contains(key)) - break; + continue; const QVariantMap dbMap = data.value(key).toMap(); DebuggerItem item; item.fromMap(dbMap); - result.append(item); + if (isSystem) { + item.setAutoDetected(true); + // SDK debuggers are always considered to be up-to-date, so no need to recheck them. + } else { + // User settings. + if (item.isAutoDetected() && !item.isValid()) { + qWarning() << QString::fromLatin1("DebuggerItem \"%1\" (%2) dropped since it is not valid") + .arg(item.command().toString()).arg(item.id().toString()); + continue; + } + } + DebuggerItemManager::registerDebugger(item); } - - return result; } QList<DebuggerItem> DebuggerItemManager::m_debuggers; @@ -361,7 +404,7 @@ DebuggerItemModel *DebuggerItemManager::model() return m_model; } -void DebuggerItemManager::autoDetectCdbDebugger() +void DebuggerItemManager::autoDetectCdbDebuggers() { QList<FileName> cdbs; @@ -419,16 +462,34 @@ void DebuggerItemManager::autoDetectCdbDebugger() } } -void DebuggerItemManager::autoDetectDebuggers() +void DebuggerItemManager::autoDetectGdbOrLldbDebuggers() { - autoDetectCdbDebugger(); - QStringList filters; filters.append(QLatin1String("gdb-i686-pc-mingw32")); filters.append(QLatin1String("gdb")); filters.append(QLatin1String("lldb")); filters.append(QLatin1String("lldb-*")); +// DebuggerItem result; +// result.setAutoDetected(true); +// result.setDisplayName(tr("Auto-detected for Tool Chain %1").arg(tc->displayName())); + /* + // Check suggestions from the SDK. + Environment env = Environment::systemEnvironment(); + if (tc) { + tc->addToEnvironment(env); // Find MinGW gdb in toolchain environment. + QString path = tc->suggestedDebugger().toString(); + if (!path.isEmpty()) { + const QFileInfo fi(path); + if (!fi.isAbsolute()) + path = env.searchInPath(path); + result.command = FileName::fromString(path); + result.engineType = engineTypeFromBinary(path); + return maybeAddDebugger(result, false); + } + } + */ + QFileInfoList suspects; QStringList path = Environment::systemEnvironment().path(); @@ -512,46 +573,16 @@ const DebuggerItem *DebuggerItemManager::findById(const QVariant &id) void DebuggerItemManager::restoreDebuggers() { - QList<DebuggerItem> dbsToCheck; - // Read debuggers from SDK QFileInfo systemSettingsFile(Core::ICore::settings(QSettings::SystemScope)->fileName()); - QList<DebuggerItem> dbsToRegister = - readDebuggers(FileName::fromString(systemSettingsFile.absolutePath() + QLatin1String(DEBUGGER_FILENAME))); - - // These are autodetected. - for (int i = 0, n = dbsToRegister.size(); i != n; ++i) - dbsToRegister[i].setAutoDetected(true); - - // SDK debuggers are always considered to be up-to-date, so no need to recheck them. + readDebuggers(FileName::fromString(systemSettingsFile.absolutePath() + QLatin1String(DEBUGGER_FILENAME)), true); // Read all debuggers from user file. - foreach (const DebuggerItem &item, readDebuggers(userSettingsFileName())) { - if (item.isAutoDetected()) - dbsToCheck.append(item); - else - dbsToRegister.append(item); - } - - // Keep debuggers that were not rediscovered but are still executable and delete the rest - foreach (const DebuggerItem &item, dbsToCheck) { - if (!item.isValid()) { - qWarning() << QString::fromLatin1("DebuggerItem \"%1\" (%2) dropped since it is not valid") - .arg(item.command().toString()).arg(item.id().toString()); - } else { - dbsToRegister.append(item); - } - } - - for (int i = 0, n = dbsToRegister.size(); i != n; ++i) { - DebuggerItem item = dbsToRegister.at(i); - if (findByCommand(item.command())) - continue; - addDebugger(item); - } + readDebuggers(userSettingsFileName(), false); // Auto detect current. - autoDetectDebuggers(); + autoDetectCdbDebuggers(); + autoDetectGdbOrLldbDebuggers(); // Add debuggers from pre-3.x profiles.xml readLegacyDebuggers(); @@ -639,72 +670,6 @@ void DebuggerItemManager::setItemData(const QVariant &id, const QString &display } } -QVariant DebuggerItemManager::defaultDebugger(ToolChain *tc) -{ - QTC_ASSERT(tc, return QVariant()); - - DebuggerItem result; - result.setAutoDetected(true); - result.setDisplayName(tr("Auto-detected for Tool Chain %1").arg(tc->displayName())); - - Abi abi = Abi::hostAbi(); - if (tc) - abi = tc->targetAbi(); - -// if (abis.first().wordWidth() == 32) -// result.first = cdb.toString(); -// else if (abis.first().wordWidth() == 64) -// result.second = cdb.toString(); -// // prefer 64bit debugger, even for 32bit binaries: -// if (!result.second.isEmpty()) -// result.first = result.second; - - - foreach (const DebuggerItem &item, m_debuggers) - foreach (const Abi targetAbi, item.abis()) - if (targetAbi.isCompatibleWith(abi)) - return item.id(); - - return QVariant(); - - /* - // CDB for windows: - if (abi.os() == Abi::WindowsOS && abi.osFlavor() != Abi::WindowsMSysFlavor) { - QPair<QString, QString> cdbs = autoDetectCdbDebugger(); - result.command = FileName::fromString(abi.wordWidth() == 32 ? cdbs.first : cdbs.second); - result.engineType = CdbEngineType; - return maybeAddDebugger(result, false); - } - - // Check suggestions from the SDK. - Environment env = Environment::systemEnvironment(); - if (tc) { - tc->addToEnvironment(env); // Find MinGW gdb in toolchain environment. - QString path = tc->suggestedDebugger().toString(); - if (!path.isEmpty()) { - const QFileInfo fi(path); - if (!fi.isAbsolute()) - path = env.searchInPath(path); - result.command = FileName::fromString(path); - result.engineType = engineTypeFromBinary(path); - return maybeAddDebugger(result, false); - } - } - - // 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.command = FileName::fromString(env.searchInPath(gdb.isEmpty() ? systemGdb : gdb)); - return maybeAddDebugger(result, false); - */ -} - namespace Internal { static QList<QStandardItem *> describeItem(const DebuggerItem &item) @@ -946,7 +911,9 @@ void DebuggerKitConfigWidget::manageDebuggers() void DebuggerKitConfigWidget::currentDebuggerChanged(int) { - m_kit->setValue(DebuggerKitInformation::id(), m_comboBox->itemData(m_comboBox->currentIndex())); + int currentIndex = m_comboBox->currentIndex(); + QVariant id = m_comboBox->itemData(currentIndex); + m_kit->setValue(DebuggerKitInformation::id(), id); } void DebuggerKitConfigWidget::onDebuggerAdded(const QVariant &id, const QString &displayName) diff --git a/src/plugins/debugger/debuggerkitinformation.cpp b/src/plugins/debugger/debuggerkitinformation.cpp index c57dde729b..2bd4492dec 100644 --- a/src/plugins/debugger/debuggerkitinformation.cpp +++ b/src/plugins/debugger/debuggerkitinformation.cpp @@ -185,6 +185,42 @@ void DebuggerItem::setAbi(const Abi &abi) m_abis.append(abi); } +static DebuggerItem::MatchLevel matchSingle(const Abi &debuggerAbi, const Abi &targetAbi) +{ + if (debuggerAbi.architecture() != targetAbi.architecture()) + return DebuggerItem::DoesNotMatch; + + if (debuggerAbi.os() != targetAbi.os()) + return DebuggerItem::DoesNotMatch; + + if (debuggerAbi.binaryFormat() != targetAbi.binaryFormat()) + return DebuggerItem::DoesNotMatch; + + if (debuggerAbi.wordWidth() != targetAbi.wordWidth()) + return DebuggerItem::DoesNotMatch; + + if (debuggerAbi.os() == Abi::WindowsOS) { + if (debuggerAbi.osFlavor() == Abi::WindowsMSysFlavor && targetAbi.osFlavor() != Abi::WindowsMSysFlavor) + return DebuggerItem::DoesNotMatch; + if (debuggerAbi.osFlavor() != Abi::WindowsMSysFlavor && targetAbi.osFlavor() == Abi::WindowsMSysFlavor) + return DebuggerItem::DoesNotMatch; + return DebuggerItem::MatchesSomewhat; + } + + return DebuggerItem::MatchesPerfectly; +} + +DebuggerItem::MatchLevel DebuggerItem::matchTarget(const Abi &targetAbi) const +{ + MatchLevel bestMatch = DoesNotMatch; + foreach (const Abi &debuggerAbi, m_abis) { + MatchLevel currentMatch = matchSingle(debuggerAbi, targetAbi); + if (currentMatch > bestMatch) + bestMatch = currentMatch; + } + return bestMatch; +} + bool Debugger::DebuggerItem::isValid() const { return m_engineType != NoEngineType; diff --git a/src/plugins/debugger/debuggerkitinformation.h b/src/plugins/debugger/debuggerkitinformation.h index e0b66fc08a..92e8d935fd 100644 --- a/src/plugins/debugger/debuggerkitinformation.h +++ b/src/plugins/debugger/debuggerkitinformation.h @@ -77,6 +77,9 @@ public: void setAbis(const QList<ProjectExplorer::Abi> &abis); void setAbi(const ProjectExplorer::Abi &abi); + enum MatchLevel { DoesNotMatch, MatchesSomewhat, MatchesPerfectly }; + MatchLevel matchTarget(const ProjectExplorer::Abi &targetAbi) const; + QStringList abiNames() const; private: @@ -113,7 +116,6 @@ public: static const DebuggerItem *findByCommand(const Utils::FileName &command); static const DebuggerItem *findById(const QVariant &id); - static QVariant defaultDebugger(ProjectExplorer::ToolChain *tc); static void restoreDebuggers(); static QString uniqueDisplayName(const QString &base); static void setItemData(const QVariant &id, const QString& displayName, const Utils::FileName &fileName); @@ -126,8 +128,8 @@ public slots: private: explicit DebuggerItemManager(QObject *parent = 0); - static void autoDetectDebuggers(); - static void autoDetectCdbDebugger(); + static void autoDetectGdbOrLldbDebuggers(); + static void autoDetectCdbDebuggers(); static void readLegacyDebuggers(); static Utils::PersistentSettingsWriter *m_writer; |