2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2018 The Qt Company Ltd.
|
2022-12-21 10:12:09 +01:00
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
2018-03-07 17:34:09 +01:00
|
|
|
|
|
|
|
|
#include "toolchainsettingsaccessor.h"
|
|
|
|
|
|
2023-04-17 10:12:53 +02:00
|
|
|
#include "devicesupport/devicemanager.h"
|
2022-06-22 15:43:33 +02:00
|
|
|
#include "projectexplorerconstants.h"
|
2023-01-13 12:38:22 +01:00
|
|
|
#include "projectexplorertr.h"
|
2018-03-07 17:34:09 +01:00
|
|
|
#include "toolchain.h"
|
|
|
|
|
|
|
|
|
|
#include <coreplugin/icore.h>
|
|
|
|
|
|
|
|
|
|
#include <utils/algorithm.h>
|
|
|
|
|
|
2022-10-12 14:00:32 +02:00
|
|
|
#include <QElapsedTimer>
|
2023-06-21 15:12:46 +02:00
|
|
|
#include <QGuiApplication>
|
2022-10-12 14:00:32 +02:00
|
|
|
#include <QLoggingCategory>
|
|
|
|
|
|
2018-03-07 17:34:09 +01:00
|
|
|
using namespace Utils;
|
|
|
|
|
|
|
|
|
|
namespace ProjectExplorer {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2022-10-12 14:00:32 +02:00
|
|
|
static Q_LOGGING_CATEGORY(Log, "qtc.projectexplorer.toolchain.autodetection", QtWarningMsg)
|
|
|
|
|
|
2018-03-07 17:34:09 +01:00
|
|
|
// --------------------------------------------------------------------
|
|
|
|
|
// ToolChainSettingsUpgraders:
|
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
class ToolChainSettingsUpgraderV0 : public Utils::VersionUpgrader
|
|
|
|
|
{
|
|
|
|
|
// Necessary to make Version 1 supported.
|
|
|
|
|
public:
|
|
|
|
|
ToolChainSettingsUpgraderV0() : Utils::VersionUpgrader(0, "4.6") { }
|
|
|
|
|
|
|
|
|
|
// NOOP
|
|
|
|
|
QVariantMap upgrade(const QVariantMap &data) final { return data; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
|
// Helpers:
|
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
|
|
2022-06-22 15:43:33 +02:00
|
|
|
const char TOOLCHAIN_DATA_KEY[] = "ToolChain.";
|
|
|
|
|
const char TOOLCHAIN_COUNT_KEY[] = "ToolChain.Count";
|
|
|
|
|
const char TOOLCHAIN_FILENAME[] = "toolchains.xml";
|
2018-03-07 17:34:09 +01:00
|
|
|
|
|
|
|
|
struct ToolChainOperations
|
|
|
|
|
{
|
2022-01-14 17:29:02 +01:00
|
|
|
Toolchains toDemote;
|
|
|
|
|
Toolchains toRegister;
|
|
|
|
|
Toolchains toDelete;
|
2018-03-07 17:34:09 +01:00
|
|
|
};
|
|
|
|
|
|
2022-01-14 17:29:02 +01:00
|
|
|
static Toolchains autoDetectToolChains(const ToolchainDetector &detector)
|
2018-03-07 17:34:09 +01:00
|
|
|
{
|
2022-01-14 17:29:02 +01:00
|
|
|
Toolchains result;
|
2022-10-12 14:00:32 +02:00
|
|
|
for (ToolChainFactory *f : ToolChainFactory::allToolChainFactories()) {
|
|
|
|
|
QElapsedTimer et;
|
|
|
|
|
et.start();
|
2022-01-14 17:29:02 +01:00
|
|
|
result.append(f->autoDetect(detector));
|
2022-10-12 14:00:32 +02:00
|
|
|
qCDebug(Log) << f->displayName() << "auto detection took: " << et.elapsed() << "ms";
|
|
|
|
|
}
|
2018-03-07 17:34:09 +01:00
|
|
|
|
|
|
|
|
// Remove invalid toolchains that might have sneaked in.
|
|
|
|
|
return Utils::filtered(result, [](const ToolChain *tc) { return tc->isValid(); });
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-14 17:29:02 +01:00
|
|
|
static Toolchains makeUniqueByEqual(const Toolchains &a)
|
2018-03-07 17:34:09 +01:00
|
|
|
{
|
2022-01-14 17:29:02 +01:00
|
|
|
Toolchains result;
|
2022-05-04 11:50:41 +02:00
|
|
|
for (ToolChain *tc : a) {
|
2018-03-07 17:34:09 +01:00
|
|
|
if (!Utils::contains(result, [tc](ToolChain *rtc) { return *tc == *rtc; }))
|
|
|
|
|
result.append(tc);
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-14 17:29:02 +01:00
|
|
|
static Toolchains makeUniqueByPointerEqual(const Toolchains &a)
|
2018-03-07 17:34:09 +01:00
|
|
|
{
|
2019-07-03 18:34:30 +02:00
|
|
|
return Utils::toList(Utils::toSet(a));
|
2018-03-07 17:34:09 +01:00
|
|
|
}
|
|
|
|
|
|
2022-01-14 17:29:02 +01:00
|
|
|
static Toolchains subtractById(const Toolchains &a, const Toolchains &b)
|
2018-03-07 17:34:09 +01:00
|
|
|
{
|
|
|
|
|
return Utils::filtered(a, [&b](ToolChain *atc) {
|
|
|
|
|
return !Utils::anyOf(b, Utils::equal(&ToolChain::id, atc->id()));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-14 17:29:02 +01:00
|
|
|
static bool containsByEqual(const Toolchains &a, const ToolChain *atc)
|
2018-03-07 17:34:09 +01:00
|
|
|
{
|
|
|
|
|
return Utils::anyOf(a, [atc](ToolChain *btc) { return *atc == *btc; });
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-14 17:29:02 +01:00
|
|
|
static Toolchains subtractByEqual(const Toolchains &a, const Toolchains &b)
|
2018-03-07 17:34:09 +01:00
|
|
|
{
|
|
|
|
|
return Utils::filtered(a, [&b](ToolChain *atc) {
|
|
|
|
|
return !Utils::anyOf(b, [atc](ToolChain *btc) { return *atc == *btc; });
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-14 17:29:02 +01:00
|
|
|
static Toolchains subtractByPointerEqual(const Toolchains &a, const Toolchains &b)
|
2018-03-07 17:34:09 +01:00
|
|
|
{
|
|
|
|
|
return Utils::filtered(a, [&b](ToolChain *atc) { return !b.contains(atc); });
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-14 17:29:02 +01:00
|
|
|
static Toolchains stabilizeOrder(const Toolchains &toRegister,
|
|
|
|
|
const Toolchains &userFileTcs)
|
2018-03-07 17:34:09 +01:00
|
|
|
{
|
|
|
|
|
// Keep the toolchains in their position in the user toolchain file to minimize diff!
|
2022-01-14 17:29:02 +01:00
|
|
|
Toolchains result;
|
2018-03-07 17:34:09 +01:00
|
|
|
result.reserve(toRegister.size());
|
2022-01-14 17:29:02 +01:00
|
|
|
Toolchains toHandle = toRegister;
|
2018-03-07 17:34:09 +01:00
|
|
|
|
|
|
|
|
for (int i = 0; i < userFileTcs.count(); ++i) {
|
|
|
|
|
const QByteArray userId = userFileTcs.at(i)->id();
|
|
|
|
|
const int handlePos = Utils::indexOf(toHandle,
|
|
|
|
|
[&userId](const ToolChain *htc) { return htc->id() == userId; });
|
|
|
|
|
if (handlePos < 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
result.append(toHandle.at(handlePos));
|
|
|
|
|
toHandle.removeAt(handlePos);
|
|
|
|
|
}
|
|
|
|
|
result.append(toHandle);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-14 17:29:02 +01:00
|
|
|
static ToolChainOperations mergeToolChainLists(const Toolchains &systemFileTcs,
|
|
|
|
|
const Toolchains &userFileTcs,
|
|
|
|
|
const Toolchains &autodetectedTcs)
|
2018-03-07 17:34:09 +01:00
|
|
|
{
|
2022-01-14 17:29:02 +01:00
|
|
|
const Toolchains uniqueUserFileTcs = makeUniqueByEqual(userFileTcs);
|
|
|
|
|
Toolchains manualUserFileTcs;
|
|
|
|
|
Toolchains autodetectedUserFileTcs;
|
2018-03-07 17:34:09 +01:00
|
|
|
std::tie(autodetectedUserFileTcs, manualUserFileTcs)
|
|
|
|
|
= Utils::partition(uniqueUserFileTcs, &ToolChain::isAutoDetected);
|
2022-01-14 17:29:02 +01:00
|
|
|
const Toolchains autodetectedUserTcs = subtractById(autodetectedUserFileTcs, systemFileTcs);
|
2018-03-07 17:34:09 +01:00
|
|
|
|
|
|
|
|
// Calculate a set of Tcs that were detected before (and saved to userFile) and that
|
|
|
|
|
// got re-detected again. Take the userTcs (to keep Ids) over the same in autodetectedTcs.
|
2022-01-14 17:29:02 +01:00
|
|
|
Toolchains redetectedUserTcs;
|
|
|
|
|
Toolchains notRedetectedUserTcs;
|
2018-03-07 17:34:09 +01:00
|
|
|
std::tie(redetectedUserTcs, notRedetectedUserTcs)
|
|
|
|
|
= Utils::partition(autodetectedUserTcs,
|
|
|
|
|
[&autodetectedTcs](ToolChain *tc) { return containsByEqual(autodetectedTcs, tc); });
|
|
|
|
|
|
|
|
|
|
// Remove redetected tcs from autodetectedTcs:
|
2022-01-14 17:29:02 +01:00
|
|
|
const Toolchains newlyAutodetectedTcs
|
2018-03-07 17:34:09 +01:00
|
|
|
= subtractByEqual(autodetectedTcs, redetectedUserTcs);
|
|
|
|
|
|
2022-01-14 17:29:02 +01:00
|
|
|
const Toolchains notRedetectedButValidUserTcs
|
2018-03-07 17:34:09 +01:00
|
|
|
= Utils::filtered(notRedetectedUserTcs, &ToolChain::isValid);
|
|
|
|
|
|
|
|
|
|
ToolChainOperations result;
|
|
|
|
|
result.toDemote = notRedetectedButValidUserTcs;
|
2019-04-02 15:08:28 +02:00
|
|
|
result.toRegister = stabilizeOrder(systemFileTcs + manualUserFileTcs + result.toDemote // manual TCs
|
2018-03-07 17:34:09 +01:00
|
|
|
+ redetectedUserTcs + newlyAutodetectedTcs, // auto TCs
|
|
|
|
|
userFileTcs);
|
|
|
|
|
|
|
|
|
|
result.toDelete = makeUniqueByPointerEqual(subtractByPointerEqual(systemFileTcs + userFileTcs + autodetectedTcs,
|
|
|
|
|
result.toRegister));
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
|
// ToolChainSettingsAccessor:
|
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
|
|
2023-04-18 14:36:46 +02:00
|
|
|
ToolChainSettingsAccessor::ToolChainSettingsAccessor()
|
2018-03-07 17:34:09 +01:00
|
|
|
{
|
2023-04-18 14:36:46 +02:00
|
|
|
setDocType("QtCreatorToolChains");
|
2023-06-21 15:12:46 +02:00
|
|
|
setApplicationDisplayName(QGuiApplication::applicationDisplayName());
|
2021-04-26 15:46:09 +02:00
|
|
|
setBaseFilePath(Core::ICore::userResourcePath(TOOLCHAIN_FILENAME));
|
2018-03-07 17:34:09 +01:00
|
|
|
|
|
|
|
|
addVersionUpgrader(std::make_unique<ToolChainSettingsUpgraderV0>());
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-14 17:29:02 +01:00
|
|
|
Toolchains ToolChainSettingsAccessor::restoreToolChains(QWidget *parent) const
|
2018-03-07 17:34:09 +01:00
|
|
|
{
|
|
|
|
|
// read all tool chains from SDK
|
2022-01-14 17:29:02 +01:00
|
|
|
const Toolchains systemFileTcs = toolChains(
|
2021-04-26 15:46:09 +02:00
|
|
|
restoreSettings(Core::ICore::installerResourcePath(TOOLCHAIN_FILENAME), parent));
|
2019-04-08 17:36:39 +02:00
|
|
|
for (ToolChain * const systemTc : systemFileTcs)
|
|
|
|
|
systemTc->setDetection(ToolChain::AutoDetectionFromSdk);
|
2018-03-07 17:34:09 +01:00
|
|
|
|
|
|
|
|
// read all tool chains from user file.
|
2022-01-14 17:29:02 +01:00
|
|
|
const Toolchains userFileTcs = toolChains(restoreSettings(parent));
|
2018-03-07 17:34:09 +01:00
|
|
|
|
|
|
|
|
// Autodetect: Pass autodetected toolchains from user file so the information can be reused:
|
2022-01-14 17:29:02 +01:00
|
|
|
const Toolchains autodetectedUserFileTcs
|
2018-03-07 17:34:09 +01:00
|
|
|
= Utils::filtered(userFileTcs, &ToolChain::isAutoDetected);
|
2023-04-17 10:12:53 +02:00
|
|
|
|
|
|
|
|
// Autodect from system paths on the desktop device.
|
|
|
|
|
// The restriction is intentional to keep startup and automatic validation a limited effort
|
|
|
|
|
ToolchainDetector detector(autodetectedUserFileTcs, DeviceManager::defaultDesktopDevice(), {});
|
|
|
|
|
const Toolchains autodetectedTcs = autoDetectToolChains(detector);
|
2018-03-07 17:34:09 +01:00
|
|
|
|
|
|
|
|
// merge tool chains and register those that we need to keep:
|
|
|
|
|
const ToolChainOperations ops = mergeToolChainLists(systemFileTcs, userFileTcs, autodetectedTcs);
|
|
|
|
|
|
|
|
|
|
// Process ops:
|
2022-04-07 14:04:20 +02:00
|
|
|
for (ToolChain *tc : ops.toDemote) {
|
|
|
|
|
// FIXME: We currently only demote local toolchains, as they are not redetected.
|
|
|
|
|
if (tc->detectionSource().isEmpty())
|
|
|
|
|
tc->setDetection(ToolChain::ManualDetection);
|
|
|
|
|
}
|
2018-03-07 17:34:09 +01:00
|
|
|
|
|
|
|
|
qDeleteAll(ops.toDelete);
|
|
|
|
|
|
|
|
|
|
return ops.toRegister;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-14 17:29:02 +01:00
|
|
|
void ToolChainSettingsAccessor::saveToolChains(const Toolchains &toolchains, QWidget *parent)
|
2018-03-07 17:34:09 +01:00
|
|
|
{
|
|
|
|
|
QVariantMap data;
|
|
|
|
|
|
|
|
|
|
int count = 0;
|
|
|
|
|
for (const ToolChain *tc : toolchains) {
|
2019-04-02 15:08:28 +02:00
|
|
|
if (!tc || (!tc->isValid() && tc->isAutoDetected()))
|
2018-03-07 17:34:09 +01:00
|
|
|
continue;
|
|
|
|
|
const QVariantMap tmp = tc->toMap();
|
|
|
|
|
if (tmp.isEmpty())
|
|
|
|
|
continue;
|
|
|
|
|
data.insert(QString::fromLatin1(TOOLCHAIN_DATA_KEY) + QString::number(count), tmp);
|
|
|
|
|
++count;
|
|
|
|
|
}
|
|
|
|
|
data.insert(TOOLCHAIN_COUNT_KEY, count);
|
|
|
|
|
|
|
|
|
|
// Do not save default debuggers! Those are set by the SDK!
|
|
|
|
|
|
|
|
|
|
saveSettings(data, parent);
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-14 17:29:02 +01:00
|
|
|
Toolchains ToolChainSettingsAccessor::toolChains(const QVariantMap &data) const
|
2018-03-07 17:34:09 +01:00
|
|
|
{
|
2022-01-14 17:29:02 +01:00
|
|
|
Toolchains result;
|
2018-03-07 17:34:09 +01:00
|
|
|
const QList<ToolChainFactory *> factories = ToolChainFactory::allToolChainFactories();
|
|
|
|
|
|
|
|
|
|
const int count = data.value(TOOLCHAIN_COUNT_KEY, 0).toInt();
|
|
|
|
|
for (int i = 0; i < count; ++i) {
|
|
|
|
|
const QString key = QString::fromLatin1(TOOLCHAIN_DATA_KEY) + QString::number(i);
|
|
|
|
|
if (!data.contains(key))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
const QVariantMap tcMap = data.value(key).toMap();
|
|
|
|
|
|
|
|
|
|
bool restored = false;
|
2020-06-26 13:59:38 +02:00
|
|
|
const Utils::Id tcType = ToolChainFactory::typeIdFromMap(tcMap);
|
2019-05-08 14:56:26 +02:00
|
|
|
if (tcType.isValid()) {
|
|
|
|
|
for (ToolChainFactory *f : factories) {
|
|
|
|
|
if (f->supportedToolChainType() == tcType) {
|
|
|
|
|
if (ToolChain *tc = f->restore(tcMap)) {
|
|
|
|
|
result.append(tc);
|
|
|
|
|
restored = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2018-03-07 17:34:09 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!restored)
|
|
|
|
|
qWarning("Warning: Unable to restore compiler type '%s' for tool chain %s.",
|
2019-05-08 14:56:26 +02:00
|
|
|
qPrintable(tcType.toString()),
|
2018-03-07 17:34:09 +01:00
|
|
|
qPrintable(QString::fromUtf8(ToolChainFactory::idFromMap(tcMap))));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace ProjectExplorer
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_TESTS
|
|
|
|
|
#include "projectexplorer.h"
|
|
|
|
|
|
|
|
|
|
#include "abi.h"
|
2018-07-11 08:25:07 +02:00
|
|
|
#include "toolchainconfigwidget.h"
|
2018-03-07 17:34:09 +01:00
|
|
|
|
|
|
|
|
#include <QSet>
|
|
|
|
|
#include <QTest>
|
|
|
|
|
|
|
|
|
|
namespace ProjectExplorer {
|
|
|
|
|
|
2019-05-13 16:18:25 +02:00
|
|
|
const char TestTokenKey[] = "TestTokenKey";
|
|
|
|
|
const char TestToolChainType[] = "TestToolChainType";
|
|
|
|
|
|
|
|
|
|
|
2018-03-07 17:34:09 +01:00
|
|
|
class TTC : public ToolChain
|
|
|
|
|
{
|
|
|
|
|
public:
|
2019-06-19 17:28:20 +02:00
|
|
|
TTC(const QByteArray &t = {}, bool v = true) :
|
2019-05-13 16:18:25 +02:00
|
|
|
ToolChain(TestToolChainType),
|
2018-03-07 17:34:09 +01:00
|
|
|
token(t),
|
|
|
|
|
m_valid(v)
|
|
|
|
|
{
|
|
|
|
|
m_toolChains.append(this);
|
|
|
|
|
setLanguage(Constants::CXX_LANGUAGE_ID);
|
2019-06-19 17:28:20 +02:00
|
|
|
setTypeDisplayName("Test Tool Chain");
|
2020-11-10 14:05:58 +01:00
|
|
|
setTargetAbiNoSignal(Abi::hostAbi());
|
2021-08-10 16:19:02 +02:00
|
|
|
setCompilerCommand("/tmp/test/gcc");
|
2018-03-07 17:34:09 +01:00
|
|
|
}
|
|
|
|
|
|
2019-10-17 17:58:22 +02:00
|
|
|
static QList<TTC *> toolChains() { return m_toolChains; }
|
2018-03-07 17:34:09 +01:00
|
|
|
static bool hasToolChains() { return !m_toolChains.isEmpty(); }
|
|
|
|
|
|
|
|
|
|
bool isValid() const override { return m_valid; }
|
2018-09-27 10:18:44 +02:00
|
|
|
MacroInspectionRunner createMacroInspectionRunner() const override { return MacroInspectionRunner(); }
|
2019-07-23 10:58:00 +02:00
|
|
|
LanguageExtensions languageExtensions(const QStringList &cxxflags) const override { Q_UNUSED(cxxflags) return LanguageExtension::None; }
|
|
|
|
|
WarningFlags warningFlags(const QStringList &cflags) const override { Q_UNUSED(cflags) return WarningFlags::NoWarnings; }
|
2019-07-05 16:58:07 +02:00
|
|
|
BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner(const Utils::Environment &) const override { return BuiltInHeaderPathsRunner(); }
|
2019-07-23 10:58:00 +02:00
|
|
|
void addToEnvironment(Environment &env) const override { Q_UNUSED(env) }
|
2021-08-10 16:19:02 +02:00
|
|
|
FilePath makeCommand(const Environment &) const override { return "make"; }
|
2020-04-16 13:53:05 +02:00
|
|
|
QList<OutputLineParser *> createOutputParsers() const override { return {}; }
|
2018-07-11 08:25:07 +02:00
|
|
|
std::unique_ptr<ToolChainConfigWidget> createConfigurationWidget() override { return nullptr; }
|
2018-03-07 17:34:09 +01:00
|
|
|
bool operator ==(const ToolChain &other) const override {
|
|
|
|
|
if (!ToolChain::operator==(other))
|
|
|
|
|
return false;
|
|
|
|
|
return static_cast<const TTC *>(&other)->token == token;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-13 16:18:25 +02:00
|
|
|
bool fromMap(const QVariantMap &data) final
|
|
|
|
|
{
|
|
|
|
|
ToolChain::fromMap(data);
|
|
|
|
|
token = data.value(TestTokenKey).toByteArray();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QVariantMap toMap() const final
|
|
|
|
|
{
|
|
|
|
|
QVariantMap data = ToolChain::toMap();
|
|
|
|
|
data[TestTokenKey] = token;
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-07 17:34:09 +01:00
|
|
|
QByteArray token;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
bool m_valid = false;
|
|
|
|
|
|
|
|
|
|
static QList<TTC *> m_toolChains;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
QList<TTC *> TTC::m_toolChains;
|
|
|
|
|
|
|
|
|
|
} // namespace ProjectExplorer
|
|
|
|
|
|
|
|
|
|
Q_DECLARE_METATYPE(ProjectExplorer::ToolChain *)
|
|
|
|
|
|
|
|
|
|
namespace ProjectExplorer {
|
|
|
|
|
|
|
|
|
|
void ProjectExplorerPlugin::testToolChainMerging_data()
|
|
|
|
|
{
|
2019-05-13 16:18:25 +02:00
|
|
|
class TestToolChainFactory : ToolChainFactory
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
TestToolChainFactory() {
|
|
|
|
|
setSupportedToolChainType(TestToolChainType);
|
|
|
|
|
setToolchainConstructor([] { return new TTC; });
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TestToolChainFactory factory;
|
|
|
|
|
|
2022-01-14 17:29:02 +01:00
|
|
|
QTest::addColumn<Toolchains>("system");
|
|
|
|
|
QTest::addColumn<Toolchains>("user");
|
|
|
|
|
QTest::addColumn<Toolchains>("autodetect");
|
|
|
|
|
QTest::addColumn<Toolchains>("toDemote");
|
|
|
|
|
QTest::addColumn<Toolchains>("toRegister");
|
2018-03-07 17:34:09 +01:00
|
|
|
|
|
|
|
|
TTC *system1 = nullptr;
|
2019-05-13 16:18:25 +02:00
|
|
|
ToolChain *system1c = nullptr;
|
2018-03-07 17:34:09 +01:00
|
|
|
TTC *system2 = nullptr;
|
|
|
|
|
TTC *system3i = nullptr;
|
|
|
|
|
TTC *user1 = nullptr;
|
2019-05-13 16:18:25 +02:00
|
|
|
ToolChain *user1c = nullptr;
|
2018-03-07 17:34:09 +01:00
|
|
|
TTC *user3i = nullptr;
|
|
|
|
|
TTC *user2 = nullptr;
|
|
|
|
|
TTC *auto1 = nullptr;
|
2019-05-13 16:18:25 +02:00
|
|
|
ToolChain *auto1c = nullptr;
|
2018-03-07 17:34:09 +01:00
|
|
|
TTC *auto1_2 = nullptr;
|
|
|
|
|
TTC *auto2 = nullptr;
|
|
|
|
|
TTC *auto3i = nullptr;
|
|
|
|
|
|
|
|
|
|
if (!TTC::hasToolChains()) {
|
2019-05-08 19:03:15 +02:00
|
|
|
system1 = new TTC("system1");
|
|
|
|
|
system1->setDetection(ToolChain::AutoDetection);
|
2019-05-13 16:18:25 +02:00
|
|
|
system1c = system1->clone(); Q_UNUSED(system1c)
|
2019-05-08 19:03:15 +02:00
|
|
|
system2 = new TTC("system2");
|
|
|
|
|
system2->setDetection(ToolChain::AutoDetection);
|
|
|
|
|
system3i = new TTC("system3", false);
|
|
|
|
|
system3i->setDetection(ToolChain::AutoDetection);
|
|
|
|
|
user1 = new TTC("user1");
|
|
|
|
|
user1->setDetection(ToolChain::ManualDetection);
|
2019-05-13 16:18:25 +02:00
|
|
|
user1c = user1->clone(); Q_UNUSED(user1c)
|
2019-05-08 19:03:15 +02:00
|
|
|
user2 = new TTC("user2");
|
|
|
|
|
user2->setDetection(ToolChain::ManualDetection);
|
|
|
|
|
user3i = new TTC("user3", false);
|
|
|
|
|
user3i->setDetection(ToolChain::ManualDetection);
|
|
|
|
|
auto1 = new TTC("auto1");
|
2019-05-10 16:58:30 +02:00
|
|
|
auto1->setDetection(ToolChain::AutoDetection);
|
2019-05-13 16:18:25 +02:00
|
|
|
auto1c = auto1->clone();
|
2019-05-08 19:03:15 +02:00
|
|
|
auto1_2 = new TTC("auto1");
|
2019-05-10 16:58:30 +02:00
|
|
|
auto1_2->setDetection(ToolChain::AutoDetection);
|
2019-05-08 19:03:15 +02:00
|
|
|
auto2 = new TTC("auto2");
|
2019-05-10 16:58:30 +02:00
|
|
|
auto2->setDetection(ToolChain::AutoDetection);
|
2019-05-08 19:03:15 +02:00
|
|
|
auto3i = new TTC("auto3", false);
|
2019-05-10 16:58:30 +02:00
|
|
|
auto3i->setDetection(ToolChain::AutoDetection);
|
2018-03-07 17:34:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QTest::newRow("no toolchains")
|
2022-01-14 17:29:02 +01:00
|
|
|
<< (Toolchains()) << (Toolchains()) << (Toolchains())
|
|
|
|
|
<< (Toolchains()) << (Toolchains());
|
2018-03-07 17:34:09 +01:00
|
|
|
|
|
|
|
|
QTest::newRow("System: system, no user")
|
2022-01-14 17:29:02 +01:00
|
|
|
<< (Toolchains() << system1) << (Toolchains()) << (Toolchains())
|
|
|
|
|
<< (Toolchains()) << (Toolchains() << system1);
|
2018-03-07 17:34:09 +01:00
|
|
|
QTest::newRow("System: system, user")
|
2022-01-14 17:29:02 +01:00
|
|
|
<< (Toolchains() << system1) << (Toolchains() << system1) << (Toolchains())
|
|
|
|
|
<< (Toolchains()) << (Toolchains() << system1);
|
2018-03-07 17:34:09 +01:00
|
|
|
QTest::newRow("System: no system, user") // keep, the user tool chain as it is still found
|
2022-01-14 17:29:02 +01:00
|
|
|
<< (Toolchains()) << (Toolchains() << system1) << (Toolchains())
|
|
|
|
|
<< (Toolchains() << system1) << (Toolchains() << system1);
|
2018-03-07 17:34:09 +01:00
|
|
|
QTest::newRow("System: no system, invalid user")
|
2022-01-14 17:29:02 +01:00
|
|
|
<< (Toolchains()) << (Toolchains() << system3i) << (Toolchains())
|
|
|
|
|
<< (Toolchains()) << (Toolchains());
|
2018-03-07 17:34:09 +01:00
|
|
|
|
|
|
|
|
QTest::newRow("Auto: no auto, user")
|
2022-01-14 17:29:02 +01:00
|
|
|
<< (Toolchains()) << (Toolchains() << auto1) << (Toolchains())
|
|
|
|
|
<< (Toolchains() << auto1) << (Toolchains() << auto1);
|
2018-03-07 17:34:09 +01:00
|
|
|
QTest::newRow("Auto: auto, no user")
|
2022-01-14 17:29:02 +01:00
|
|
|
<< (Toolchains()) << (Toolchains()) << (Toolchains() << auto1)
|
|
|
|
|
<< (Toolchains()) << (Toolchains() << auto1);
|
2018-03-07 17:34:09 +01:00
|
|
|
QTest::newRow("Auto: auto, user")
|
2022-01-14 17:29:02 +01:00
|
|
|
<< (Toolchains()) << (Toolchains() << auto1) << (Toolchains() << auto1)
|
|
|
|
|
<< (Toolchains()) << (Toolchains() << auto1);
|
2018-03-07 17:34:09 +01:00
|
|
|
QTest::newRow("Auto: auto-redetect, user")
|
2022-01-14 17:29:02 +01:00
|
|
|
<< (Toolchains()) << (Toolchains() << auto1) << (Toolchains() << auto1_2)
|
|
|
|
|
<< (Toolchains()) << (Toolchains() << auto1);
|
2018-03-07 17:34:09 +01:00
|
|
|
QTest::newRow("Auto: auto-redetect, duplicate users")
|
2022-01-14 17:29:02 +01:00
|
|
|
<< (Toolchains()) << (Toolchains() << auto1 << auto1c) << (Toolchains() << auto1_2)
|
|
|
|
|
<< (Toolchains()) << (Toolchains() << auto1);
|
2018-03-07 17:34:09 +01:00
|
|
|
QTest::newRow("Auto: (no) auto, invalid user")
|
2022-01-14 17:29:02 +01:00
|
|
|
<< (Toolchains()) << (Toolchains() << auto3i) << (Toolchains())
|
|
|
|
|
<< (Toolchains()) << (Toolchains());
|
2018-03-07 17:34:09 +01:00
|
|
|
|
2019-04-02 15:08:28 +02:00
|
|
|
QTest::newRow("invalid user")
|
2022-01-14 17:29:02 +01:00
|
|
|
<< (Toolchains()) << (Toolchains() << user3i) << (Toolchains())
|
|
|
|
|
<< (Toolchains()) << (Toolchains{user3i});
|
2018-03-07 17:34:09 +01:00
|
|
|
|
|
|
|
|
QTest::newRow("one of everything")
|
2022-01-14 17:29:02 +01:00
|
|
|
<< (Toolchains() << system1) << (Toolchains() << user1) << (Toolchains() << auto1)
|
|
|
|
|
<< (Toolchains()) << (Toolchains() << system1 << user1 << auto1);
|
2018-03-07 17:34:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ProjectExplorerPlugin::testToolChainMerging()
|
|
|
|
|
{
|
2022-01-14 17:29:02 +01:00
|
|
|
QFETCH(Toolchains, system);
|
|
|
|
|
QFETCH(Toolchains, user);
|
|
|
|
|
QFETCH(Toolchains, autodetect);
|
|
|
|
|
QFETCH(Toolchains, toRegister);
|
|
|
|
|
QFETCH(Toolchains, toDemote);
|
2018-03-07 17:34:09 +01:00
|
|
|
|
|
|
|
|
Internal::ToolChainOperations ops = Internal::mergeToolChainLists(system, user, autodetect);
|
|
|
|
|
|
2019-07-03 18:34:30 +02:00
|
|
|
QSet<ToolChain *> expToRegister = Utils::toSet(toRegister);
|
|
|
|
|
QSet<ToolChain *> expToDemote = Utils::toSet(toDemote);
|
2018-03-07 17:34:09 +01:00
|
|
|
|
2019-07-03 18:34:30 +02:00
|
|
|
QSet<ToolChain *> actToRegister = Utils::toSet(ops.toRegister);
|
|
|
|
|
QSet<ToolChain *> actToDemote = Utils::toSet(ops.toDemote);
|
|
|
|
|
QSet<ToolChain *> actToDelete = Utils::toSet(ops.toDelete);
|
2018-03-07 17:34:09 +01:00
|
|
|
|
|
|
|
|
QCOMPARE(actToRegister.count(), ops.toRegister.count()); // no dups!
|
|
|
|
|
QCOMPARE(actToDemote.count(), ops.toDemote.count()); // no dups!
|
|
|
|
|
QCOMPARE(actToDelete.count(), ops.toDelete.count()); // no dups!
|
|
|
|
|
|
|
|
|
|
QSet<ToolChain *> tmp = actToRegister;
|
|
|
|
|
tmp.intersect(actToDemote);
|
|
|
|
|
QCOMPARE(tmp, actToDemote); // all toDemote are in toRegister
|
|
|
|
|
|
|
|
|
|
tmp = actToRegister;
|
|
|
|
|
tmp.intersect(actToDelete);
|
|
|
|
|
QVERIFY(tmp.isEmpty()); // Nothing that needs to be registered is to be deleted
|
|
|
|
|
|
|
|
|
|
tmp = actToRegister;
|
|
|
|
|
tmp.unite(actToDelete);
|
2019-07-03 18:34:30 +02:00
|
|
|
QCOMPARE(tmp, Utils::toSet(system + user + autodetect)); // All input is accounted for
|
2018-03-07 17:34:09 +01:00
|
|
|
|
|
|
|
|
QCOMPARE(expToRegister, actToRegister);
|
|
|
|
|
QCOMPARE(expToDemote, actToDemote);
|
2019-07-03 18:34:30 +02:00
|
|
|
QCOMPARE(Utils::toSet(system + user + autodetect),
|
|
|
|
|
Utils::toSet(ops.toRegister + ops.toDemote + ops.toDelete));
|
2018-03-07 17:34:09 +01:00
|
|
|
}
|
|
|
|
|
|
2019-10-17 17:58:22 +02:00
|
|
|
void ProjectExplorerPlugin::deleteTestToolchains()
|
|
|
|
|
{
|
|
|
|
|
qDeleteAll(TTC::toolChains());
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-07 17:34:09 +01:00
|
|
|
} // namespace ProjectExplorer
|
|
|
|
|
|
|
|
|
|
#endif // WITH_TESTS
|
|
|
|
|
|