diff --git a/cmake/FindGoogletest.cmake b/cmake/FindGoogletest.cmake index eee8127a959..fdd3e245ded 100644 --- a/cmake/FindGoogletest.cmake +++ b/cmake/FindGoogletest.cmake @@ -101,6 +101,8 @@ if(Googletest_FOUND AND NOT TARGET Googletest) GTEST_HAS_DEATH_TEST ) set_target_properties(Googletest PROPERTIES AUTOMOC OFF AUTOUIC OFF) + set_property(TARGET Googletest PROPERTY POSITION_INDEPENDENT_CODE ON) + target_compile_definitions(Googletest PUBLIC GOOGLE_TEST_IS_FOUND) target_link_libraries(Googletest Threads::Threads) endif() diff --git a/src/plugins/mcusupport/CMakeLists.txt b/src/plugins/mcusupport/CMakeLists.txt index 261dd6e0b52..a42fd4f6003 100644 --- a/src/plugins/mcusupport/CMakeLists.txt +++ b/src/plugins/mcusupport/CMakeLists.txt @@ -7,7 +7,7 @@ add_qtc_plugin(McuSupport mcusupport_global.h mcusupportconstants.h mcusupportdevice.cpp mcusupportdevice.h - mcusupportoptions.cpp mcusupportoptions.h + mcusupportoptions.cpp mcusupportoptions.h mcuabstractpackage.h mcusupportoptionspage.cpp mcusupportoptionspage.h mcupackage.cpp mcupackage.h mcusupportplugin.cpp mcusupportplugin.h @@ -16,3 +16,5 @@ add_qtc_plugin(McuSupport mcusupportversiondetection.cpp mcusupportversiondetection.h mcusupportcmakemapper.cpp mcusupportcmakemapper.h ) + +add_subdirectory(test) diff --git a/src/plugins/mcusupport/mcuabstractpackage.h b/src/plugins/mcusupport/mcuabstractpackage.h new file mode 100644 index 00000000000..e008e2af1a8 --- /dev/null +++ b/src/plugins/mcusupport/mcuabstractpackage.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +namespace Utils { +class FilePath; +} // namespace Utils + +namespace McuSupport::Internal { + +class McuAbstractPackage : public QObject +{ + Q_OBJECT +public: + enum Status { + EmptyPath, + InvalidPath, + ValidPathInvalidPackage, + ValidPackageMismatchedVersion, + ValidPackage + }; + + virtual Utils::FilePath basePath() const = 0; + virtual Utils::FilePath path() const = 0; + virtual QString label() const = 0; + virtual Utils::FilePath defaultPath() const = 0; + virtual QString detectionPath() const = 0; + virtual QString statusText() const = 0; + virtual void updateStatus() = 0; + + virtual Status status() const = 0; + virtual bool validStatus() const = 0; + virtual const QString &environmentVariableName() const = 0; + virtual void setAddToPath(bool) = 0; + virtual bool addToPath() const = 0; + virtual void writeGeneralSettings() const = 0; + virtual bool writeToSettings() const = 0; + virtual void setRelativePathModifier(const QString &) = 0; + virtual void setVersions(const QStringList &) = 0; + + virtual bool automaticKitCreationEnabled() const = 0; + virtual void setAutomaticKitCreationEnabled(const bool enabled) = 0; + + virtual QWidget *widget() = 0; +signals: + void changed(); + void statusChanged(); + +}; // class McuAbstractPackage +} // namespace McuSupport::Internal diff --git a/src/plugins/mcusupport/mcupackage.h b/src/plugins/mcusupport/mcupackage.h index 8729a40a335..dc933920af9 100644 --- a/src/plugins/mcusupport/mcupackage.h +++ b/src/plugins/mcusupport/mcupackage.h @@ -25,6 +25,7 @@ #pragma once +#include "mcuabstractpackage.h" #include "mcusupportversiondetection.h" #include @@ -46,48 +47,44 @@ class InfoLabel; namespace McuSupport { namespace Internal { -class McuPackage : public QObject +class McuPackage : public McuAbstractPackage { Q_OBJECT public: - enum Status { - EmptyPath, - InvalidPath, - ValidPathInvalidPackage, - ValidPackageMismatchedVersion, - ValidPackage - }; - - McuPackage(const QString &label, const Utils::FilePath &defaultPath, - const QString &detectionPath, const QString &settingsKey, - const QString &envVarName = {}, const QString &downloadUrl = {}, + McuPackage(const QString &label, + const Utils::FilePath &defaultPath, + const QString &detectionPath, + const QString &settingsKey, + const QString &envVarName = {}, + const QString &downloadUrl = {}, const McuPackageVersionDetector *versionDetector = nullptr); - virtual ~McuPackage() = default; + ~McuPackage() override = default; - Utils::FilePath basePath() const; - Utils::FilePath path() const; - QString label() const; - Utils::FilePath defaultPath() const; - QString detectionPath() const; - QString statusText() const; - void updateStatus(); + Utils::FilePath basePath() const override; + Utils::FilePath path() const override; + QString label() const override; + Utils::FilePath defaultPath() const override; + QString detectionPath() const override; + QString statusText() const override; + void updateStatus() override; - Status status() const; - bool validStatus() const; - void setAddToPath(bool addToPath); - bool addToPath() const; - void writeGeneralSettings() const; - bool writeToSettings() const; - void setRelativePathModifier(const QString &path); - void setVersions(const QStringList &versions); + Status status() const override; + bool validStatus() const override; + void setAddToPath(bool addToPath) override; + bool addToPath() const override; + void writeGeneralSettings() const override; + bool writeToSettings() const override; + void setRelativePathModifier(const QString &path) override; + void setVersions(const QStringList &versions) override; - bool automaticKitCreationEnabled() const; - void setAutomaticKitCreationEnabled(const bool enabled); + //TODO(piotr.mucko): Why every package knows about automatic kit creation. This should be outside of this class. + bool automaticKitCreationEnabled() const override; + void setAutomaticKitCreationEnabled(const bool enabled) override; - QWidget *widget(); + QWidget *widget() override; - const QString &environmentVariableName() const; + const QString &environmentVariableName() const override; signals: void changed(); @@ -116,7 +113,7 @@ private: bool m_addToPath = false; bool m_automaticKitCreation = true; - Status m_status = InvalidPath; + Status m_status = Status::InvalidPath; }; class McuToolChainPackage : public McuPackage diff --git a/src/plugins/mcusupport/mcusupport.qbs b/src/plugins/mcusupport/mcusupport.qbs index e8529e24649..ef2c4aa6bb4 100644 --- a/src/plugins/mcusupport/mcusupport.qbs +++ b/src/plugins/mcusupport/mcusupport.qbs @@ -15,6 +15,7 @@ QtcPlugin { Depends { name: "QtSupport" } files: [ + "mcuabstractpackage.h", "mcupackage.cpp", "mcupackage.h", "mcusupport.qrc", diff --git a/src/plugins/mcusupport/mcusupportoptions.cpp b/src/plugins/mcusupport/mcusupportoptions.cpp index 36811c5a13a..5137af37725 100644 --- a/src/plugins/mcusupport/mcusupportoptions.cpp +++ b/src/plugins/mcusupport/mcusupportoptions.cpp @@ -67,6 +67,8 @@ #include #include +using CMakeProjectManager::CMakeConfigItem; +using CMakeProjectManager::CMakeConfigurationKitAspect; using namespace ProjectExplorer; using namespace Utils; @@ -82,22 +84,6 @@ static bool kitNeedsQtVersion() return !HostOsInfo::isWindowsHost(); } -static void remapQul2xCmakeVars(Kit *kit, const EnvironmentItems &envItems) -{ - using namespace CMakeProjectManager; - const auto cmakeVars = mapEnvVarsToQul2xCmakeVars(envItems); - const auto cmakeVarNames = Utils::transform(cmakeVars, &CMakeConfigItem::key); - - // First filter out all Qul2.x CMake vars - auto config = Utils::filtered(CMakeConfigurationKitAspect::configuration(kit), - [&](const auto &configItem) { - return !cmakeVarNames.contains(configItem.key); - }); - // Then append them with new values - config.append(cmakeVars); - CMakeConfigurationKitAspect::setConfiguration(kit, config); -} - static ToolChain *msvcToolChain(Id language) { @@ -269,7 +255,7 @@ QVariant McuToolChainPackage::debuggerId() const McuTarget::McuTarget(const QVersionNumber &qulVersion, const Platform &platform, OS os, - const QVector &packages, + const QVector &packages, const McuToolChainPackage *toolChainPackage, int colorDepth) : m_qulVersion(qulVersion) @@ -281,7 +267,7 @@ McuTarget::McuTarget(const QVersionNumber &qulVersion, { } -const QVector &McuTarget::packages() const +const QVector &McuTarget::packages() const { return m_packages; } @@ -303,7 +289,7 @@ const McuTarget::Platform &McuTarget::platform() const bool McuTarget::isValid() const { - return Utils::allOf(packages(), [](McuPackage *package) { + return Utils::allOf(packages(), [](McuAbstractPackage *package) { package->updateStatus(); return package->validStatus(); }); @@ -319,7 +305,7 @@ void McuTarget::printPackageProblems() const package->label(), package->statusText()), true); - if (package->status() == McuPackage::ValidPackageMismatchedVersion) + if (package->status() == McuAbstractPackage::ValidPackageMismatchedVersion) printMessage(tr("Warning creating kit for target %1, package %2: %3").arg( McuSupportOptions::kitName(this), package->label(), @@ -350,7 +336,7 @@ McuSupportOptions::McuSupportOptions(QObject *parent) : QObject(parent) , qtForMCUsSdkPackage(Sdk::createQtForMCUsPackage()) { - connect(qtForMCUsSdkPackage, &McuPackage::changed, + connect(qtForMCUsSdkPackage, &McuAbstractPackage::changed, this, &McuSupportOptions::populatePackagesAndTargets); } @@ -421,7 +407,7 @@ void McuSupportOptions::setQulDir(const FilePath &dir) if (qtForMCUsSdkPackage->validStatus()) Sdk::targetsAndPackages(dir, &sdkRepository); for (const auto &package : qAsConst(sdkRepository.packages)) - connect(package, &McuPackage::changed, this, &McuSupportOptions::changed); + connect(package, &McuAbstractPackage::changed, this, &McuSupportOptions::changed); emit changed(); } @@ -463,6 +449,22 @@ static void setKitProperties(const QString &kitName, Kit *k, const McuTarget *mc k->setIrrelevantAspects(irrelevant); } +void McuSupportOptions::remapQul2xCmakeVars(Kit *kit, const EnvironmentItems &envItems) +{ + const auto cmakeVars = mapEnvVarsToQul2xCmakeVars(envItems); + const auto cmakeVarNames = Utils::transform(cmakeVars, &CMakeConfigItem::key); + + // First filter out all Qul2.x CMake vars + auto config = Utils::filtered(CMakeConfigurationKitAspect::configuration(kit), + [&](const auto &configItem) { + return !cmakeVarNames.contains(configItem.key); + }); + // Then append them with new values + config.append(cmakeVars); + CMakeConfigurationKitAspect::setConfiguration(kit, config); +} + + static void setKitToolchains(Kit *k, const McuToolChainPackage *tcPackage) { switch (tcPackage->type()) { @@ -535,8 +537,8 @@ static bool expectsCmakeVars(const McuTarget *mcuTarget) return mcuTarget->qulVersion() >= QVersionNumber{2,0}; } -static void setKitEnvironment(Kit *k, const McuTarget *mcuTarget, - const McuPackage *qtForMCUsSdkPackage) +void McuSupportOptions::setKitEnvironment(Kit *k, const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdkPackage) { EnvironmentItems changes; QStringList pathAdditions; @@ -548,7 +550,7 @@ static void setKitEnvironment(Kit *k, const McuTarget *mcuTarget, && !CMakeProjectManager::CMakeToolManager::defaultCMakeTool()->hasFileApi()) pathAdditions.append(qtForMCUsSdkPackage->path().pathAppended("bin").toUserOutput()); - auto processPackage = [&pathAdditions, &changes](const McuPackage *package) { + auto processPackage = [&pathAdditions, &changes](const McuAbstractPackage *package) { if (package->addToPath()) pathAdditions.append(package->path().toUserOutput()); if (!package->environmentVariableName().isEmpty()) @@ -571,18 +573,18 @@ static void setKitEnvironment(Kit *k, const McuTarget *mcuTarget, // Hack, this problem should be solved in lower layer if (expectsCmakeVars(mcuTarget)) { - remapQul2xCmakeVars(k, changes); + McuSupportOptions::remapQul2xCmakeVars(k, changes); } EnvironmentKitAspect::setEnvironmentChanges(k, changes); } static void setKitDependencies(Kit *k, const McuTarget *mcuTarget, - const McuPackage *qtForMCUsSdkPackage) + const McuAbstractPackage *qtForMCUsSdkPackage) { NameValueItems dependencies; - auto processPackage = [&dependencies](const McuPackage *package) { + auto processPackage = [&dependencies](const McuAbstractPackage *package) { if (!package->environmentVariableName().isEmpty()) dependencies.append({package->environmentVariableName(), QDir::toNativeSeparators(package->detectionPath())}); @@ -598,7 +600,7 @@ static void setKitDependencies(Kit *k, const McuTarget *mcuTarget, k->setIrrelevantAspects(irrelevant); } -static void updateKitEnvironment(Kit *k, const McuTarget *mcuTarget) +void McuSupportOptions::updateKitEnvironment(Kit *k, const McuTarget *mcuTarget) { EnvironmentItems changes = EnvironmentKitAspect::environmentChanges(k); for (auto package : mcuTarget->packages()) { @@ -730,14 +732,14 @@ QList McuSupportOptions::existingKits(const McuTarget *mcuTarget) }); } -QList McuSupportOptions::matchingKits(const McuTarget *mcuTarget, const McuPackage *qtForMCUsSdkPackage) +QList McuSupportOptions::matchingKits(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage) { return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) { return kitUpToDate(kit, mcuTarget, qtForMCUsSdkPackage); }); } -QList McuSupportOptions::upgradeableKits(const McuTarget *mcuTarget, const McuPackage *qtForMCUsSdkPackage) +QList McuSupportOptions::upgradeableKits(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage) { return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) { return !kitUpToDate(kit, mcuTarget, qtForMCUsSdkPackage); @@ -750,7 +752,7 @@ QList McuSupportOptions::kitsWithMismatchedDependencies(const McuTarget * const auto environment = Utils::NameValueDictionary( Utils::NameValueItem::toStringList( EnvironmentKitAspect::environmentChanges(kit))); - return Utils::anyOf(mcuTarget->packages(), [&environment](const McuPackage *package) { + return Utils::anyOf(mcuTarget->packages(), [&environment](const McuAbstractPackage *package) { return !package->environmentVariableName().isEmpty() && environment.value(package->environmentVariableName()) != package->path().toUserOutput(); }); @@ -771,7 +773,7 @@ void McuSupportOptions::removeOutdatedKits() KitManager::deregisterKit(kit); } -Kit *McuSupportOptions::newKit(const McuTarget *mcuTarget, const McuPackage *qtForMCUsSdk) +Kit *McuSupportOptions::newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk) { const auto init = [mcuTarget, qtForMCUsSdk](Kit *k) { KitGuard kitGuard(k); @@ -818,7 +820,7 @@ static FilePath kitDependencyPath(const Kit *kit, const QString &variableName) } bool McuSupportOptions::kitUpToDate(const Kit *kit, const McuTarget *mcuTarget, - const McuPackage *qtForMCUsSdkPackage) + const McuAbstractPackage *qtForMCUsSdkPackage) { return kitQulVersion(kit) == mcuTarget->qulVersion() && kitDependencyPath(kit, qtForMCUsSdkPackage->environmentVariableName()).toUserOutput() == qtForMCUsSdkPackage->path().toUserOutput(); @@ -858,7 +860,7 @@ void McuSupportOptions::createAutomaticKits() qtForMCUsPackage->updateStatus(); if (!qtForMCUsPackage->validStatus()) { switch (qtForMCUsPackage->status()) { - case McuPackage::ValidPathInvalidPackage: { + case McuAbstractPackage::ValidPathInvalidPackage: { const QString displayPath = FilePath::fromString(qtForMCUsPackage->detectionPath()) .toUserOutput(); printMessage(tr("Path %1 exists, but does not contain %2.") @@ -866,13 +868,13 @@ void McuSupportOptions::createAutomaticKits() true); break; } - case McuPackage::InvalidPath: { + case McuAbstractPackage::InvalidPath: { printMessage(tr("Path %1 does not exist. Add the path in Tools > Options > Devices > MCU.") .arg(qtForMCUsPackage->path().toUserOutput()), true); break; } - case McuPackage::EmptyPath: { + case McuAbstractPackage::EmptyPath: { printMessage(tr("Missing %1. Add the path in Tools > Options > Devices > MCU.") .arg(qtForMCUsPackage->detectionPath()), true); @@ -964,7 +966,7 @@ void McuSupportOptions::upgradeKits(UpgradeOption upgradeOption) delete qtForMCUsPackage; } -void McuSupportOptions::upgradeKitInPlace(ProjectExplorer::Kit *kit, const McuTarget *mcuTarget, const McuPackage *qtForMCUsSdk) +void McuSupportOptions::upgradeKitInPlace(ProjectExplorer::Kit *kit, const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk) { setKitProperties(kitName(mcuTarget), kit, mcuTarget, qtForMCUsSdk->path()); setKitEnvironment(kit, mcuTarget, qtForMCUsSdk); @@ -980,7 +982,7 @@ void McuSupportOptions::fixKitsDependencies() Sdk::targetsAndPackages(dir, &repo); for (const auto &target: qAsConst(repo.mcuTargets)) { if (target->isValid()) { - for (auto kit : kitsWithMismatchedDependencies(target)) { + for (auto* kit : kitsWithMismatchedDependencies(target)) { updateKitEnvironment(kit, target); } } diff --git a/src/plugins/mcusupport/mcusupportoptions.h b/src/plugins/mcusupport/mcusupportoptions.h index e7b0f66015a..662a80bf759 100644 --- a/src/plugins/mcusupport/mcusupportoptions.h +++ b/src/plugins/mcusupport/mcusupportoptions.h @@ -1,7 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2021 -** The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -26,8 +25,7 @@ #pragma once -#include "mcusupport_global.h" - +#include #include #include #include @@ -43,12 +41,12 @@ class InfoLabel; namespace ProjectExplorer { class Kit; class ToolChain; -} +} // namespace ProjectExplorer namespace McuSupport { namespace Internal { -class McuPackage; +class McuAbstractPackage; class McuToolChainPackage; void printMessage(const QString &message, bool important); @@ -75,12 +73,12 @@ public: McuTarget(const QVersionNumber &qulVersion, const Platform &platform, OS os, - const QVector &packages, + const QVector &packages, const McuToolChainPackage *toolChainPackage, int colorDepth = UnspecifiedColorDepth); const QVersionNumber &qulVersion() const; - const QVector &packages() const; + const QVector &packages() const; const McuToolChainPackage *toolChainPackage() const; const Platform &platform() const; OS os() const; @@ -92,16 +90,16 @@ private: const QVersionNumber m_qulVersion; const Platform m_platform; const OS m_os; - const QVector m_packages; + const QVector m_packages; const McuToolChainPackage *m_toolChainPackage; const int m_colorDepth; -}; +}; // class McuTarget class McuSdkRepository { public: - QVector packages; - QVector mcuTargets; + QVector packages; + QVector mcuTargets; void deletePackagesAndTargets(); }; @@ -117,28 +115,33 @@ public: Replace }; - McuSupportOptions(QObject *parent = nullptr); + explicit McuSupportOptions(QObject *parent = nullptr); ~McuSupportOptions() override; - McuPackage *qtForMCUsSdkPackage = nullptr; + McuAbstractPackage *qtForMCUsSdkPackage = nullptr; McuSdkRepository sdkRepository; void setQulDir(const Utils::FilePath &dir); + static void setKitEnvironment(ProjectExplorer::Kit *, const McuTarget *, const McuAbstractPackage *); + static void updateKitEnvironment(ProjectExplorer::Kit *, const McuTarget *); + static void remapQul2xCmakeVars(ProjectExplorer::Kit *, const Utils::EnvironmentItems &); static Utils::FilePath qulDirFromSettings(); static QString kitName(const McuTarget* mcuTarget); static QList existingKits(const McuTarget *mcuTarget); - static QList matchingKits(const McuTarget *mcuTarget, const McuPackage *qtForMCUsSdkPackage); - static QList upgradeableKits(const McuTarget *mcuTarget, const McuPackage *qtForMCUsSdkPackage); + static QList matchingKits(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage); + static QList upgradeableKits(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage); static QList kitsWithMismatchedDependencies(const McuTarget *mcuTarget); static QList outdatedKits(); static void removeOutdatedKits(); - static ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget, const McuPackage *qtForMCUsSdk); + static ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk); static void createAutomaticKits(); static UpgradeOption askForKitUpgrades(); static void upgradeKits(UpgradeOption upgradeOption); - static void upgradeKitInPlace(ProjectExplorer::Kit *kit, const McuTarget *mcuTarget, const McuPackage *qtForMCUsSdk); + static void upgradeKitInPlace(ProjectExplorer::Kit *kit, + const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdk); static void fixKitsDependencies(); void checkUpgradeableKits(); static void fixExistingKits(); @@ -149,7 +152,10 @@ public: static const QVersionNumber &minimalQulVersion(); static QVersionNumber kitQulVersion(const ProjectExplorer::Kit *kit); - static bool kitUpToDate(const ProjectExplorer::Kit *kit, const McuTarget *mcuTarget, const McuPackage *qtForMCUsSdkPackage); + static bool kitUpToDate(const ProjectExplorer::Kit *kit, + const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdkPackage); + private: void deletePackagesAndTargets(); diff --git a/src/plugins/mcusupport/mcusupportoptionspage.cpp b/src/plugins/mcusupport/mcusupportoptionspage.cpp index eb83d48f30a..914869448c5 100644 --- a/src/plugins/mcusupport/mcusupportoptionspage.cpp +++ b/src/plugins/mcusupport/mcusupportoptionspage.cpp @@ -119,7 +119,7 @@ McuSupportOptionsWidget::McuSupportOptionsWidget() layout->addWidget(m_mcuTargetsComboBox); connect(m_mcuTargetsComboBox, &QComboBox::currentTextChanged, this, &McuSupportOptionsWidget::showMcuTargetPackages); - connect(m_options.qtForMCUsSdkPackage, &McuPackage::changed, + connect(m_options.qtForMCUsSdkPackage, &McuAbstractPackage::changed, this, &McuSupportOptionsWidget::populateMcuTargetsComboBox); } diff --git a/src/plugins/mcusupport/mcusupportplugin.cpp b/src/plugins/mcusupport/mcusupportplugin.cpp index 21d8878645b..86fd2ee37f5 100644 --- a/src/plugins/mcusupport/mcusupportplugin.cpp +++ b/src/plugins/mcusupport/mcusupportplugin.cpp @@ -31,6 +31,10 @@ #include "mcusupportoptionspage.h" #include "mcusupportrunconfiguration.h" +#if defined(WITH_TESTS) && defined(GOOGLE_TEST_IS_FOUND) +#include "test/unittest.h" +#endif + #include #include #include @@ -61,14 +65,9 @@ public: }; McuSupportOptionsPage optionsPage; McuDependenciesKitAspect environmentPathsKitAspect; -}; +}; // class McuSupportPluginPrivate -static McuSupportPluginPrivate *dd = nullptr; - -McuSupportPlugin::McuSupportPlugin() -{ - setObjectName("McuSupportPlugin"); -} +static McuSupportPluginPrivate* dd{nullptr}; McuSupportPlugin::~McuSupportPlugin() { @@ -76,11 +75,12 @@ McuSupportPlugin::~McuSupportPlugin() dd = nullptr; } -bool McuSupportPlugin::initialize(const QStringList& arguments, QString* errorString) +bool McuSupportPlugin::initialize(const QStringList &arguments, QString *errorString) { Q_UNUSED(arguments) Q_UNUSED(errorString) + setObjectName("McuSupportPlugin"); dd = new McuSupportPluginPrivate; McuSupportOptions::registerQchFiles(); @@ -150,5 +150,14 @@ void McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade() ICore::infoBar()->addInfo(info); } +QVector McuSupportPlugin::createTestObjects() const +{ + QVector tests; +#if defined(WITH_TESTS) && defined(GOOGLE_TEST_IS_FOUND) + tests << new Test::McuSupportTest; +#endif + return tests; +} + } // namespace Internal } // namespace McuSupport diff --git a/src/plugins/mcusupport/mcusupportplugin.h b/src/plugins/mcusupport/mcusupportplugin.h index b8237f34128..2286ed0aad2 100644 --- a/src/plugins/mcusupport/mcusupportplugin.h +++ b/src/plugins/mcusupport/mcusupportplugin.h @@ -29,23 +29,25 @@ #include -namespace McuSupport { -namespace Internal { +namespace McuSupport::Internal { -class McuSupportPlugin : public ExtensionSystem::IPlugin +class McuSupportPlugin final : public ExtensionSystem::IPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "McuSupport.json") public: - McuSupportPlugin(); - ~McuSupportPlugin() override; + ~McuSupportPlugin() final; + + bool initialize(const QStringList &arguments, QString *errorString) final; + void extensionsInitialized() final; - bool initialize(const QStringList &arguments, QString *errorString) override; - void extensionsInitialized() override; static void askUserAboutMcuSupportKitsSetup(); static void askUserAboutMcuSupportKitsUpgrade(); -}; -} // namespace Internal -} // namespace McuSupport +private: + QVector createTestObjects() const final; + +}; // class McuSupportPlugin + +} // namespace McuSupport::Internal diff --git a/src/plugins/mcusupport/mcusupportsdk.cpp b/src/plugins/mcusupport/mcusupportsdk.cpp index a966d10870d..9a5c441bcf2 100644 --- a/src/plugins/mcusupport/mcusupportsdk.cpp +++ b/src/plugins/mcusupport/mcusupportsdk.cpp @@ -34,8 +34,8 @@ #include #include #include -#include #include +#include #include #include @@ -336,39 +336,7 @@ static McuPackage *createRenesasProgrammerPackage() return result; } -struct McuTargetDescription -{ - enum class TargetType { - MCU, - Desktop - }; - - QString qulVersion; - QString compatVersion; - struct { - QString id; - QString name; - QString vendor; - QVector colorDepths; - TargetType type; - } platform; - struct { - QString id; - QStringList versions; - } toolchain; - struct { - QString name; - QString defaultPath; - QString envVar; - QStringList versions; - } boardSdk; - struct { - QString envVar; - QString boardSdkSubDir; - } freeRTOS; -}; - -static McuPackageVersionDetector* generatePackageVersionDetector(QString envVar) +static McuPackageVersionDetector *generatePackageVersionDetector(QString envVar) { if (envVar.startsWith("EVK")) return new McuPackageXmlVersionDetector("*_manifest_*.xml", "ksdk", "version", ".*"); @@ -461,9 +429,9 @@ struct McuTargetFactory return createTargetsImpl(description); } - QVector getMcuPackages() const + QVector getMcuPackages() const { - QVector packages; + QVector packages; for (auto *package : qAsConst(boardSdkPkgs)) packages.append(package); for (auto *package : qAsConst(freeRTOSPkgs)) @@ -481,7 +449,7 @@ protected: tcPkg = createUnsupportedToolChainPackage(); for (auto os : {McuTarget::OS::BareMetal, McuTarget::OS::FreeRTOS}) { for (int colorDepth : desc.platform.colorDepths) { - QVector required3rdPartyPkgs = { tcPkg }; + QVector required3rdPartyPkgs = { tcPkg }; if (vendorPkgs.contains(desc.platform.vendor)) required3rdPartyPkgs.push_back(vendorPkgs.value(desc.platform.vendor)); @@ -555,7 +523,7 @@ protected: } else tcPkg = createUnsupportedToolChainPackage(); for (int colorDepth : desc.platform.colorDepths) { - QVector required3rdPartyPkgs; + QVector required3rdPartyPkgs; // Desktop toolchains don't need any additional settings if (tcPkg && !tcPkg->isDesktopToolchain() @@ -608,10 +576,10 @@ private: QHash boardSdkPkgs; QHash freeRTOSPkgs; -}; +}; // struct McuTargetFactory -static QVector targetsFromDescriptions(const QList &descriptions, - QVector *packages) +QVector targetsFromDescriptions(const QList &descriptions, + QVector *packages) { const QHash tcPkgs = { {{"armgcc"}, createArmGccPackage()}, @@ -639,7 +607,7 @@ static QVector targetsFromDescriptions(const QListappend(Utils::transform >( + packages->append(Utils::transform >( tcPkgs.values(), [&](McuToolChainPackage *tcPkg) { return tcPkg; })); for (auto *package : vendorPkgs) packages->append(package); @@ -732,7 +700,7 @@ static McuTargetDescription parseDescriptionJsonV2x(const QString &qulVersion, c return description; } -static McuTargetDescription parseDescriptionJson(const QByteArray &data) +McuTargetDescription parseDescriptionJson(const QByteArray &data) { const QJsonDocument document = QJsonDocument::fromJson(data); const QJsonObject target = document.object(); diff --git a/src/plugins/mcusupport/mcusupportsdk.h b/src/plugins/mcusupport/mcusupportsdk.h index 8429462880d..9592616c927 100644 --- a/src/plugins/mcusupport/mcusupportsdk.h +++ b/src/plugins/mcusupport/mcusupportsdk.h @@ -25,28 +25,65 @@ #pragma once +#include "utils/filepath.h" + #include #include -namespace Utils { -class FilePath; -} - namespace McuSupport { namespace Internal { #define MAX_COMPATIBILITY_VERSION 1 class McuSdkRepository; +class McuAbstractPackage; class McuPackage; +class McuTarget; + namespace Sdk { +struct McuTargetDescription +{ + enum class TargetType { MCU, Desktop }; + + QString qulVersion; + QString compatVersion; + struct + { + QString id; + QString name; + QString vendor; + QVector colorDepths; + TargetType type; + } platform; + struct + { + QString id; + QStringList versions; + } toolchain; + struct + { + QString name; + QString defaultPath; + QString envVar; + QStringList versions; + } boardSdk; + struct + { + QString envVar; + QString boardSdkSubDir; + } freeRTOS; +}; + McuPackage *createQtForMCUsPackage(); bool checkDeprecatedSdkError(const Utils::FilePath &qulDir, QString &message); void targetsAndPackages(const Utils::FilePath &qulDir, McuSdkRepository *repo); +McuTargetDescription parseDescriptionJson(const QByteArray &); +QVector targetsFromDescriptions(const QList &, QVector *); + Utils::FilePath kitsPath(const Utils::FilePath &dir); Utils::FilePath packagePathFromSettings(const QString &settingsKey, diff --git a/src/plugins/mcusupport/test/CMakeLists.txt b/src/plugins/mcusupport/test/CMakeLists.txt new file mode 100644 index 00000000000..8e693fd3e1e --- /dev/null +++ b/src/plugins/mcusupport/test/CMakeLists.txt @@ -0,0 +1,13 @@ +find_package(Googletest MODULE) + +if(TARGET Googletest) + message("Googletest target is present") + extend_qtc_plugin(McuSupport + CONDITION WITH_TESTS + DEPENDS Googletest + SOURCES + unittest.h unittest.cpp packagemock.h + ) +else() + message("Googletest target is missing") +endif() diff --git a/src/plugins/mcusupport/test/nxp_1064_json.h b/src/plugins/mcusupport/test/nxp_1064_json.h new file mode 100644 index 00000000000..4e8f53afa96 --- /dev/null +++ b/src/plugins/mcusupport/test/nxp_1064_json.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +constexpr auto nxp_1064_json = R"({ + "boardSdk": { + "cmakeCacheEntries": [ + { + "cmakeOptionName": "QUL_BOARD_SDK_DIR", + "description": "Board SDK for MIMXRT1064-EVK", + "id": "NXP_SDK_DIR", + "optional": false, + "type": "path" + } + ], + "envVar": "EVK_MIMXRT1064_SDK_PATH", + "versions": ["2.10.0"] + }, + "compatVersion": "1", + "freeRTOS": { + "cmakeCacheEntries": [ + { + "cmakeOptionName": "FREERTOS_DIR", + "defaultValue": "$QUL_BOARD_SDK_DIR/rtos/freertos/freertos_kernel", + "description": "FreeRTOS SDK for MIMXRT1064-EVK", + "id": "NXP_FREERTOS_DIR", + "optional": false, + "type": "path" + } + ], + "envVar": "IMXRT1064_FREERTOS_DIR" + }, + "platform": { + "cmakeCacheEntries": [ + { + "cmakeOptionName": "Qul_ROOT", + "description": "Qt for MCUs SDK", + "id": "Qul_DIR", + "optional": false, + "type": "path" + }, + { + "cmakeOptionName": "MCUXPRESSO_IDE_PATH", + "defaultValue": { + "unix": "/usr/local/mcuxpressoide/", + "windows": "$ROOT/nxp/MCUXpressoIDE*" + } + } + ], + "colorDepths": [16], + "environmentEntries": [], + "id": "MIMXRT1064-EVK-FREERTOS", + "pathEntries": [], + "vendor": "NXP" + }, + "qulVersion": "2.0.0", + "toolchain": { + "cmakeCacheEntries": [ + { + "cmakeOptionName": "QUL_TARGET_TOOLCHAIN_DIR", + "description": "IAR ARM Compiler", + "id": "IAR_DIR", + "optional": false, + "type": "path" + } + ], + "id": "iar", + "versions": ["8.50.9"] + } +})"; diff --git a/src/plugins/mcusupport/test/packagemock.h b/src/plugins/mcusupport/test/packagemock.h new file mode 100644 index 00000000000..45a23947bee --- /dev/null +++ b/src/plugins/mcusupport/test/packagemock.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "mcuabstractpackage.h" + +#include +#include + +namespace McuSupport::Internal { + +class PackageMock : public McuAbstractPackage +{ +public: + MOCK_METHOD(Utils::FilePath, basePath, (), (const)); + MOCK_METHOD(Utils::FilePath, path, (), (const)); + MOCK_METHOD(QString, label, (), (const)); + MOCK_METHOD(Utils::FilePath, defaultPath, (), (const)); + MOCK_METHOD(QString, detectionPath, (), (const)); + MOCK_METHOD(QString, statusText, (), (const)); + MOCK_METHOD(void, updateStatus, ()); + + MOCK_METHOD(Status, status, (), (const)); + MOCK_METHOD(bool, validStatus, (), (const)); + MOCK_METHOD(void, setDownloadUrl, (const QString &) ); + MOCK_METHOD(void, setEnvironmentVariableName, (const QString &) ); + MOCK_METHOD(const QString&, environmentVariableName, (), (const)); + MOCK_METHOD(void, setAddToPath, (bool) ); + MOCK_METHOD(bool, addToPath, (), (const)); + MOCK_METHOD(void, writeGeneralSettings, (), (const)); + MOCK_METHOD(bool, writeToSettings, (), (const)); + MOCK_METHOD(void, setRelativePathModifier, (const QString &) ); + MOCK_METHOD(void, setVersions, (const QStringList &) ); + + MOCK_METHOD(bool, automaticKitCreationEnabled, (), (const)); + MOCK_METHOD(void, setAutomaticKitCreationEnabled, (const bool enabled)); + + MOCK_METHOD(QWidget *, widget, ()); +}; // class PackageMock +} // namespace McuSupport::Internal diff --git a/src/plugins/mcusupport/test/unittest.cpp b/src/plugins/mcusupport/test/unittest.cpp new file mode 100644 index 00000000000..1d74f1d2e98 --- /dev/null +++ b/src/plugins/mcusupport/test/unittest.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "nxp_1064_json.h" +#include "unittest.h" +#include "utils/filepath.h" +#include +#include +#include +#include +#include + +namespace McuSupport::Internal::Test { + +using CMakeProjectManager::CMakeConfigItem; +using CMakeProjectManager::CMakeConfigurationKitAspect; +using ProjectExplorer::EnvironmentKitAspect; +using ProjectExplorer::KitManager; +using testing::Return; +using testing::ReturnRef; +using Utils::FilePath; + +void McuSupportTest::initTestCase() +{ + EXPECT_CALL(freeRtosPackage, environmentVariableName()).WillRepeatedly(ReturnRef(freeRtosEnvVar)); + EXPECT_CALL(freeRtosPackage, validStatus()).WillRepeatedly(Return(true)); + EXPECT_CALL(freeRtosPackage, path()) + .WillRepeatedly(Return(FilePath::fromString(defaultfreeRtosPath))); +} + +void McuSupportTest::test_parseBasicInfoFromJson() +{ + const auto description = Sdk::parseDescriptionJson(nxp_1064_json); + + QVERIFY(not description.freeRTOS.envVar.isEmpty()); + QVERIFY(description.freeRTOS.boardSdkSubDir.isEmpty()); +} + +void McuSupportTest::test_addNewKit() +{ + auto &kitManager{*KitManager::instance()}; + + QSignalSpy kitAddedSpy(&kitManager, &KitManager::kitAdded); + + auto *newKit{McuSupportOptions::newKit(&mcuTarget, &freeRtosPackage)}; + QVERIFY(newKit != nullptr); + + QCOMPARE(kitAddedSpy.count(), 1); + QList arguments = kitAddedSpy.takeFirst(); + auto *createdKit = qvariant_cast(arguments.at(0)); + QVERIFY(createdKit != nullptr); + QCOMPARE(createdKit, newKit); + + auto cmakeAspect{CMakeConfigurationKitAspect{}}; + QVERIFY(createdKit->hasValue(cmakeAspect.id())); + QVERIFY(createdKit->value(cmakeAspect.id(), freeRtosCmakeVar).isValid()); +} + +void McuSupportTest::test_addFreeRtosCmakeVarToKit() +{ + McuSupportOptions::updateKitEnvironment(&kit, &mcuTarget); + + QVERIFY(kit.hasValue(EnvironmentKitAspect::id())); + QVERIFY(kit.isValid()); + QVERIFY(not kit.allKeys().empty()); + + const auto &cmakeConfig{CMakeConfigurationKitAspect::configuration(&kit)}; + QCOMPARE(cmakeConfig.size(), 1); + + CMakeConfigItem expectedCmakeVar{freeRtosCmakeVar.toLocal8Bit(), + defaultfreeRtosPath.toLocal8Bit()}; + QVERIFY(cmakeConfig.contains(expectedCmakeVar)); +} + +} // namespace McuSupport::Internal::Test diff --git a/src/plugins/mcusupport/test/unittest.h b/src/plugins/mcusupport/test/unittest.h new file mode 100644 index 00000000000..738e4d45cea --- /dev/null +++ b/src/plugins/mcusupport/test/unittest.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "mcusupportoptions.h" +#include "mcusupportplugin.h" +#include "mcusupportsdk.h" +#include "mcupackage.h" +#include "packagemock.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace McuSupport::Internal::Test { + +using ProjectExplorer::Kit; + +class McuSupportTest : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + + void test_addFreeRtosCmakeVarToKit(); + void test_addNewKit(); + void test_parseBasicInfoFromJson(); + +private: + QVersionNumber currentQulVersion{2, 0}; + + const QString id{"target_id"}; + const QString name{"target_name"}; + const QString vendor{"target_vendor"}; + + const QString freeRtosEnvVar{"EVK_MIMXRT1170_FREERTOS_PATH"}; + const QString freeRtosCmakeVar{"FREERTOS_DIR"}; + const QString defaultfreeRtosPath{"/opt/freertos/default"}; + + PackageMock freeRtosPackage; + Kit kit; + + McuToolChainPackage toolchainPackage{{}, {}, {}, {}, {}}; + const McuTarget::Platform platform{id, name, vendor}; + McuTarget mcuTarget{currentQulVersion, + platform, + McuTarget::OS::FreeRTOS, + {&freeRtosPackage}, + &toolchainPackage}; + +}; // class McuSupportTest + +} // namespace McuSupport::Internal::Test