diff --git a/src/plugins/mcusupport/CMakeLists.txt b/src/plugins/mcusupport/CMakeLists.txt index c82bf2b1f45..6d7602c2f0e 100644 --- a/src/plugins/mcusupport/CMakeLists.txt +++ b/src/plugins/mcusupport/CMakeLists.txt @@ -8,8 +8,10 @@ add_qtc_plugin(McuSupport mcusupportconstants.h mcusupportdevice.cpp mcusupportdevice.h mcusupportoptions.cpp mcusupportoptions.h mcuabstractpackage.h + mcukitmanager.cpp mcukitmanager.h mcusupportoptionspage.cpp mcusupportoptionspage.h mcupackage.cpp mcupackage.h + mcutarget.cpp mcutarget.h mcusupportplugin.cpp mcusupportplugin.h mcusupportsdk.cpp mcusupportsdk.h mcusupportrunconfiguration.cpp mcusupportrunconfiguration.h diff --git a/src/plugins/mcusupport/mcukitmanager.cpp b/src/plugins/mcusupport/mcukitmanager.cpp new file mode 100644 index 00000000000..e142072242d --- /dev/null +++ b/src/plugins/mcusupport/mcukitmanager.cpp @@ -0,0 +1,596 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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 "mcukitmanager.h" +#include "mcusupportoptions.h" + +#include "mcusupportconstants.h" +#include "mcukitinformation.h" +#include "mcupackage.h" +#include "mcutarget.h" +#include "mcusupportplugin.h" +#include "mcusupportsdk.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using CMakeProjectManager::CMakeConfigItem; +using CMakeProjectManager::CMakeConfigurationKitAspect; +using namespace ProjectExplorer; +using namespace Utils; + +namespace McuSupport { +namespace Internal { +namespace McuKitManager { + +static const int KIT_VERSION = 9; // Bumps up whenever details in Kit creation change + +static FilePath qulDocsDir() +{ + const FilePath qulDir = McuSupportOptions::qulDirFromSettings(); + if (qulDir.isEmpty() || !qulDir.exists()) + return {}; + const FilePath docsDir = qulDir.pathAppended("docs"); + return docsDir.exists() ? docsDir : FilePath(); +} + +static void setKitToolchains(Kit *k, const McuToolChainPackage *tcPackage) +{ + switch (tcPackage->type()) { + case McuToolChainPackage::Type::Unsupported: + return; + + case McuToolChainPackage::Type::GHS: + case McuToolChainPackage::Type::GHSArm: + return; // No Green Hills toolchain, because support for it is missing. + + case McuToolChainPackage::Type::IAR: + case McuToolChainPackage::Type::KEIL: + case McuToolChainPackage::Type::MSVC: + case McuToolChainPackage::Type::GCC: + case McuToolChainPackage::Type::ArmGcc: + ToolChainKitAspect::setToolChain(k, + tcPackage->toolChain( + ProjectExplorer::Constants::C_LANGUAGE_ID)); + ToolChainKitAspect::setToolChain(k, + tcPackage->toolChain( + ProjectExplorer::Constants::CXX_LANGUAGE_ID)); + return; + + default: + Q_UNREACHABLE(); + } +} + + +static void setKitProperties(const QString &kitName, + Kit *k, + const McuTarget *mcuTarget, + const FilePath &sdkPath) +{ + using namespace Constants; + + k->setUnexpandedDisplayName(kitName); + k->setValue(KIT_MCUTARGET_VENDOR_KEY, mcuTarget->platform().vendor); + k->setValue(KIT_MCUTARGET_MODEL_KEY, mcuTarget->platform().name); + k->setValue(KIT_MCUTARGET_COLORDEPTH_KEY, mcuTarget->colorDepth()); + k->setValue(KIT_MCUTARGET_SDKVERSION_KEY, mcuTarget->qulVersion().toString()); + k->setValue(KIT_MCUTARGET_KITVERSION_KEY, KIT_VERSION); + k->setValue(KIT_MCUTARGET_OS_KEY, static_cast(mcuTarget->os())); + k->setValue(KIT_MCUTARGET_TOOCHAIN_KEY, mcuTarget->toolChainPackage()->toolChainName()); + k->setAutoDetected(false); + k->makeSticky(); + if (mcuTarget->toolChainPackage()->isDesktopToolchain()) + k->setDeviceTypeForIcon(DEVICE_TYPE); + k->setValue(QtSupport::SuppliesQtQuickImportPath::id(), true); + k->setValue(QtSupport::KitQmlImportPath::id(), sdkPath.pathAppended("include/qul").toVariant()); + k->setValue(QtSupport::KitHasMergedHeaderPathsWithQmlImportPaths::id(), true); + QSet irrelevant = { + SysRootKitAspect::id(), + QtSupport::SuppliesQtQuickImportPath::id(), + QtSupport::KitQmlImportPath::id(), + QtSupport::KitHasMergedHeaderPathsWithQmlImportPaths::id(), + }; + if (!McuSupportOptions::kitsNeedQtVersion()) + irrelevant.insert(QtSupport::QtKitAspect::id()); + k->setIrrelevantAspects(irrelevant); +} + + +static void setKitDebugger(Kit *k, const McuToolChainPackage *tcPackage) +{ + if (tcPackage->isDesktopToolchain()) { + // Qt Creator seems to be smart enough to deduce the right Kit debugger from the ToolChain + return; + } + + switch (tcPackage->type()) { + case McuToolChainPackage::Type::Unsupported: + case McuToolChainPackage::Type::GHS: + case McuToolChainPackage::Type::GHSArm: + case McuToolChainPackage::Type::IAR: + return; // No Green Hills and IAR debugger, because support for it is missing. + + case McuToolChainPackage::Type::KEIL: + case McuToolChainPackage::Type::MSVC: + case McuToolChainPackage::Type::GCC: + case McuToolChainPackage::Type::ArmGcc: { + const QVariant debuggerId = tcPackage->debuggerId(); + if (debuggerId.isValid()) { + Debugger::DebuggerKitAspect::setDebugger(k, debuggerId); + } + return; + } + + default: + Q_UNREACHABLE(); + } +} + +static void setKitDevice(Kit *k, const McuTarget *mcuTarget) +{ + // "Device Type" Desktop is the default. We use that for the Qt for MCUs Desktop Kit + if (mcuTarget->toolChainPackage()->isDesktopToolchain()) + return; + + DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DEVICE_TYPE); +} + +static bool expectsCmakeVars(const McuTarget *mcuTarget) +{ + return mcuTarget->qulVersion() >= QVersionNumber{2, 0}; +} + +static void setKitDependencies(Kit *k, + const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdkPackage) +{ + NameValueItems dependencies; + + auto processPackage = [&dependencies](const McuAbstractPackage *package) { + if (!package->environmentVariableName().isEmpty()) + dependencies.append({package->environmentVariableName(), + QDir::toNativeSeparators(package->detectionPath())}); + }; + for (auto package : mcuTarget->packages()) + processPackage(package); + processPackage(qtForMCUsSdkPackage); + + McuDependenciesKitAspect::setDependencies(k, dependencies); + + auto irrelevant = k->irrelevantAspects(); + irrelevant.insert(McuDependenciesKitAspect::id()); + k->setIrrelevantAspects(irrelevant); +} + +static void setKitCMakeOptions(Kit *k, const McuTarget *mcuTarget, const FilePath &qulDir) +{ + using namespace CMakeProjectManager; + + CMakeConfig config = CMakeConfigurationKitAspect::configuration(k); + // CMake ToolChain file for ghs handles CMAKE_*_COMPILER autonomously + if (mcuTarget->toolChainPackage()->type() != McuToolChainPackage::Type::GHS + && mcuTarget->toolChainPackage()->type() != McuToolChainPackage::Type::GHSArm) { + config.append(CMakeConfigItem("CMAKE_CXX_COMPILER", "%{Compiler:Executable:Cxx}")); + config.append(CMakeConfigItem("CMAKE_C_COMPILER", "%{Compiler:Executable:C}")); + } + + if (!mcuTarget->toolChainPackage()->isDesktopToolchain()) { + const FilePath cMakeToolchainFile = qulDir.pathAppended( + "lib/cmake/Qul/toolchain/" + mcuTarget->toolChainPackage()->cmakeToolChainFileName()); + + config.append( + CMakeConfigItem("CMAKE_TOOLCHAIN_FILE", cMakeToolchainFile.toString().toUtf8())); + if (!cMakeToolchainFile.exists()) { + printMessage(McuTarget::tr( + "Warning for target %1: missing CMake toolchain file expected at %2.") + .arg(kitName(mcuTarget), + cMakeToolchainFile.toUserOutput()), + false); + } + } + + const FilePath generatorsPath = qulDir.pathAppended("/lib/cmake/Qul/QulGenerators.cmake"); + config.append(CMakeConfigItem("QUL_GENERATORS", generatorsPath.toString().toUtf8())); + if (!generatorsPath.exists()) { + printMessage(McuTarget::tr("Warning for target %1: missing QulGenerators expected at %2.") + .arg(kitName(mcuTarget), generatorsPath.toUserOutput()), + false); + } + + config.append(CMakeConfigItem("QUL_PLATFORM", mcuTarget->platform().name.toUtf8())); + + if (mcuTarget->colorDepth() != McuTarget::UnspecifiedColorDepth) + config.append(CMakeConfigItem("QUL_COLOR_DEPTH", + QString::number(mcuTarget->colorDepth()).toLatin1())); + if (McuSupportOptions::kitsNeedQtVersion()) + config.append(CMakeConfigItem("CMAKE_PREFIX_PATH", "%{Qt:QT_INSTALL_PREFIX}")); + CMakeConfigurationKitAspect::setConfiguration(k, config); + + if (HostOsInfo::isWindowsHost()) { + auto type = mcuTarget->toolChainPackage()->type(); + if (type == McuToolChainPackage::Type::GHS || type == McuToolChainPackage::Type::GHSArm) { + // See https://bugreports.qt.io/browse/UL-4247?focusedCommentId=565802&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-565802 + // and https://bugreports.qt.io/browse/UL-4247?focusedCommentId=565803&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-565803 + CMakeGeneratorKitAspect::setGenerator(k, "NMake Makefiles JOM"); + } + } +} + +static void setKitQtVersionOptions(Kit *k) +{ + if (!McuSupportOptions::kitsNeedQtVersion()) + QtSupport::QtKitAspect::setQtVersion(k, nullptr); + // else: auto-select a Qt version +} + +QString kitName(const McuTarget *mcuTarget) +{ + const McuToolChainPackage *tcPkg = mcuTarget->toolChainPackage(); + const QString compilerName = tcPkg && !tcPkg->isDesktopToolchain() + ? QString::fromLatin1(" (%1)").arg( + tcPkg->toolChainName().toUpper()) + : ""; + const QString colorDepth = mcuTarget->colorDepth() != McuTarget::UnspecifiedColorDepth + ? QString::fromLatin1(" %1bpp").arg(mcuTarget->colorDepth()) + : ""; + const QString targetName = mcuTarget->platform().displayName.isEmpty() + ? mcuTarget->platform().name + : mcuTarget->platform().displayName; + return QString::fromLatin1("Qt for MCUs %1.%2 - %3%4%5") + .arg(QString::number(mcuTarget->qulVersion().majorVersion()), + QString::number(mcuTarget->qulVersion().minorVersion()), + targetName, + colorDepth, + compilerName); +} + +QList existingKits(const McuTarget *mcuTarget) +{ + using namespace Constants; + return Utils::filtered(KitManager::kits(), [mcuTarget](Kit *kit) { + return kit->value(KIT_MCUTARGET_KITVERSION_KEY) == KIT_VERSION + && (!mcuTarget + || (kit->value(KIT_MCUTARGET_VENDOR_KEY) == mcuTarget->platform().vendor + && kit->value(KIT_MCUTARGET_MODEL_KEY) == mcuTarget->platform().name + && kit->value(KIT_MCUTARGET_COLORDEPTH_KEY) == mcuTarget->colorDepth() + && kit->value(KIT_MCUTARGET_OS_KEY).toInt() + == static_cast(mcuTarget->os()) + && kit->value(KIT_MCUTARGET_TOOCHAIN_KEY) + == mcuTarget->toolChainPackage()->toolChainName())); + }); +} + +QList matchingKits(const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdkPackage) +{ + return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) { + return kitIsUpToDate(kit, mcuTarget, qtForMCUsSdkPackage); + }); +} + +QList upgradeableKits(const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdkPackage) +{ + return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) { + return !kitIsUpToDate(kit, mcuTarget, qtForMCUsSdkPackage); + }); +} + +QList kitsWithMismatchedDependencies(const McuTarget *mcuTarget) +{ + return Utils::filtered(existingKits(mcuTarget), [mcuTarget](Kit *kit) { + const auto environment = Utils::NameValueDictionary( + Utils::NameValueItem::toStringList(EnvironmentKitAspect::environmentChanges(kit))); + return Utils::anyOf(mcuTarget->packages(), + [&environment](const McuAbstractPackage *package) { + return !package->environmentVariableName().isEmpty() + && environment.value(package->environmentVariableName()) + != package->path().toUserOutput(); + }); + }); +} + +QList outdatedKits() +{ + return Utils::filtered(KitManager::kits(), [](Kit *kit) { + return !kit->value(Constants::KIT_MCUTARGET_VENDOR_KEY).isNull() + && kit->value(Constants::KIT_MCUTARGET_KITVERSION_KEY) != KIT_VERSION; + }); +} + +void removeOutdatedKits() +{ + for (auto kit : outdatedKits()) + KitManager::deregisterKit(kit); +} + +Kit *newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk) +{ + const auto init = [mcuTarget, qtForMCUsSdk](Kit *k) { + KitGuard kitGuard(k); + + setKitProperties(kitName(mcuTarget), k, mcuTarget, qtForMCUsSdk->path()); + setKitDevice(k, mcuTarget); + setKitToolchains(k, mcuTarget->toolChainPackage()); + setKitDebugger(k, mcuTarget->toolChainPackage()); + McuSupportOptions::setKitEnvironment(k, mcuTarget, qtForMCUsSdk); + setKitDependencies(k, mcuTarget, qtForMCUsSdk); + setKitCMakeOptions(k, mcuTarget, qtForMCUsSdk->path()); + setKitQtVersionOptions(k); + + k->setup(); + k->fix(); + }; + + return KitManager::registerKit(init); +} + +QVersionNumber kitQulVersion(const Kit *kit) +{ + return QVersionNumber::fromString( + kit->value(McuSupport::Constants::KIT_MCUTARGET_SDKVERSION_KEY).toString()); +} + +static FilePath kitDependencyPath(const Kit *kit, const QString &variableName) +{ + for (const NameValueItem &nameValueItem : EnvironmentKitAspect::environmentChanges(kit)) { + if (nameValueItem.name == variableName) + return FilePath::fromUserInput(nameValueItem.value); + } + return FilePath(); +} + +bool kitIsUpToDate(const Kit *kit, + const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdkPackage) +{ + return kitQulVersion(kit) == mcuTarget->qulVersion() + && kitDependencyPath(kit, qtForMCUsSdkPackage->environmentVariableName()).toUserOutput() + == qtForMCUsSdkPackage->path().toUserOutput(); +} + +void createAutomaticKits() +{ + auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); + + const auto createKits = [qtForMCUsPackage]() { + if (qtForMCUsPackage->automaticKitCreationEnabled()) { + qtForMCUsPackage->updateStatus(); + if (!qtForMCUsPackage->validStatus()) { + switch (qtForMCUsPackage->status()) { + case McuAbstractPackage::Status::ValidPathInvalidPackage: { + const QString displayPath + = FilePath::fromString(qtForMCUsPackage->detectionPath()).toUserOutput(); + printMessage(McuPackage::tr("Path %1 exists, but does not contain %2.") + .arg(qtForMCUsPackage->path().toUserOutput(), displayPath), + true); + break; + } + case McuAbstractPackage::Status::InvalidPath: { + printMessage(McuPackage::tr("Path %1 does not exist. Add the path in Tools > Options > " + "Devices > MCU.") + .arg(qtForMCUsPackage->path().toUserOutput()), + true); + break; + } + case McuAbstractPackage::Status::EmptyPath: { + printMessage(McuPackage::tr("Missing %1. Add the path in Tools > Options > Devices > MCU.") + .arg(qtForMCUsPackage->detectionPath()), + true); + return; + } + default: + break; + } + return; + } + + if (CMakeProjectManager::CMakeToolManager::cmakeTools().isEmpty()) { + printMessage(McuPackage::tr("No CMake tool was detected. Add a CMake tool in Tools > Options > " + "Kits > CMake."), + true); + return; + } + + FilePath dir = qtForMCUsPackage->path(); + McuSdkRepository repo; + Sdk::targetsAndPackages(dir, &repo); + + bool needsUpgrade = false; + for (const auto &target : qAsConst(repo.mcuTargets)) { + // if kit already exists, skip + if (!matchingKits(target, qtForMCUsPackage).empty()) + continue; + if (!upgradeableKits(target, qtForMCUsPackage).empty()) { + // if kit exists but wrong version/path + needsUpgrade = true; + } else { + // if no kits for this target, create + if (target->isValid()) + newKit(target, qtForMCUsPackage); + target->printPackageProblems(); + } + } + + repo.deletePackagesAndTargets(); + + if (needsUpgrade) + McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade(); + } + }; + + createKits(); + delete qtForMCUsPackage; +} + +void upgradeKitsByCreatingNewPackage(UpgradeOption upgradeOption) +{ + if (upgradeOption == UpgradeOption::Ignore) + return; + + auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); + + auto dir = qtForMCUsPackage->path(); + McuSdkRepository repo; + Sdk::targetsAndPackages(dir, &repo); + + for (const auto &target : qAsConst(repo.mcuTargets)) { + if (!matchingKits(target, qtForMCUsPackage).empty()) + // already up-to-date + continue; + + const auto kits = upgradeableKits(target, qtForMCUsPackage); + if (!kits.empty()) { + if (upgradeOption == UpgradeOption::Replace) { + for (auto existingKit : kits) + KitManager::deregisterKit(existingKit); + } + + if (target->isValid()) + newKit(target, qtForMCUsPackage); + target->printPackageProblems(); + } + } + + repo.deletePackagesAndTargets(); + delete qtForMCUsPackage; +} + +void upgradeKitInPlace(ProjectExplorer::Kit *kit, + const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdk) +{ + setKitProperties(kitName(mcuTarget), kit, mcuTarget, qtForMCUsSdk->path()); + McuSupportOptions::setKitEnvironment(kit, mcuTarget, qtForMCUsSdk); + setKitDependencies(kit, mcuTarget, qtForMCUsSdk); +} + +void fixKitsDependencies() +{ + auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); + + FilePath dir = qtForMCUsPackage->path(); + McuSdkRepository repo; + Sdk::targetsAndPackages(dir, &repo); + for (const auto &target : qAsConst(repo.mcuTargets)) { + if (target->isValid()) { + for (auto *kit : kitsWithMismatchedDependencies(target)) { + McuSupportOptions::updateKitEnvironment(kit, target); + } + } + } + + repo.deletePackagesAndTargets(); + delete qtForMCUsPackage; +} + +/** + * @brief Fix/update existing kits if needed + */ +void fixExistingKits() +{ + for (Kit *kit : KitManager::kits()) { + if (!kit->hasValue(Constants::KIT_MCUTARGET_KITVERSION_KEY)) + continue; + + if (kit->isAutoDetected()) { + kit->setAutoDetected(false); + } + + // Check if the MCU kits are flagged as supplying a QtQuick import path, in order + // to tell the QMLJS code-model that it won't need to add a fall-back import + // path. + const auto bringsQtQuickImportPath = QtSupport::SuppliesQtQuickImportPath::id(); + auto irrelevantAspects = kit->irrelevantAspects(); + if (!irrelevantAspects.contains(bringsQtQuickImportPath)) { + irrelevantAspects.insert(bringsQtQuickImportPath); + kit->setIrrelevantAspects(irrelevantAspects); + } + if (!kit->hasValue(bringsQtQuickImportPath)) { + kit->setValue(bringsQtQuickImportPath, true); + } + + // Check if the MCU kit supplies its import path. + const auto kitQmlImportPath = QtSupport::KitQmlImportPath::id(); + if (!irrelevantAspects.contains(kitQmlImportPath)) { + irrelevantAspects.insert(kitQmlImportPath); + kit->setIrrelevantAspects(irrelevantAspects); + } + if (!kit->hasValue(kitQmlImportPath)) { + auto config = CMakeProjectManager::CMakeConfigurationKitAspect::configuration(kit); + for (const auto &cfgItem : qAsConst(config)) { + if (cfgItem.key == "QUL_GENERATORS") { + auto idx = cfgItem.value.indexOf("/lib/cmake/Qul"); + auto qulDir = cfgItem.value.left(idx); + kit->setValue(kitQmlImportPath, QVariant(qulDir + "/include/qul")); + break; + } + } + } + + // Check if the MCU kit has the flag for merged header/qml-import paths set. + const auto mergedPaths = QtSupport::KitHasMergedHeaderPathsWithQmlImportPaths::id(); + if (!irrelevantAspects.contains(mergedPaths)) { + irrelevantAspects.insert(mergedPaths); + kit->setIrrelevantAspects(irrelevantAspects); + } + if (!kit->value(mergedPaths, false).toBool()) { + kit->setValue(mergedPaths, true); + } + } + + // Fix kit dependencies for known targets + auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); + qtForMCUsPackage->updateStatus(); + if (qtForMCUsPackage->validStatus()) { + FilePath dir = qtForMCUsPackage->path(); + McuSdkRepository repo; + Sdk::targetsAndPackages(dir, &repo); + for (const auto &target : qAsConst(repo.mcuTargets)) + for (auto kit : existingKits(target)) { + if (McuDependenciesKitAspect::dependencies(kit).isEmpty()) { + setKitDependencies(kit, target, qtForMCUsPackage); + } + } + + repo.deletePackagesAndTargets(); + } + delete qtForMCUsPackage; +} + +} // namespace McuKitManager +} // namespace Internal +} // namespace McuSupport diff --git a/src/plugins/mcusupport/mcukitmanager.h b/src/plugins/mcusupport/mcukitmanager.h new file mode 100644 index 00000000000..1814fb26432 --- /dev/null +++ b/src/plugins/mcusupport/mcukitmanager.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** 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 +#include "mcusupport_global.h" + +#include +#include +#include +#include + +namespace ProjectExplorer { +class Kit; +} // namespace ProjectExplorer + +namespace McuSupport { +namespace Internal { + +class McuAbstractPackage; +class McuToolChainPackage; +class McuTarget; + +namespace McuKitManager +{ + enum class UpgradeOption { + Ignore, + Keep, + Replace + }; + + // Creating kits: + ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk); + void createAutomaticKits(); + + // Querying the kits: + QList existingKits(const McuTarget *mcuTarget); + QList matchingKits(const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdkPackage); + QList upgradeableKits( + const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage); + QList kitsWithMismatchedDependencies(const McuTarget *mcuTarget); + + // Upgrading kits: + void upgradeKitsByCreatingNewPackage(UpgradeOption upgradeOption); + void upgradeKitInPlace(ProjectExplorer::Kit *kit, const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk); + + // Fixing kits: + void fixKitsDependencies(); + void fixExistingKits(); + + // Outdated kits: + QList outdatedKits(); + void removeOutdatedKits(); + + // Querying kits: + QString kitName(const McuTarget* mcuTarget); + QVersionNumber kitQulVersion(const ProjectExplorer::Kit *kit); + bool kitIsUpToDate(const ProjectExplorer::Kit *kit, const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage); + +} // namespace McuKitManager +} // namespace Internal +} // namespace McuSupport diff --git a/src/plugins/mcusupport/mcupackage.cpp b/src/plugins/mcusupport/mcupackage.cpp index b27752e79e2..ed963652edb 100644 --- a/src/plugins/mcusupport/mcupackage.cpp +++ b/src/plugins/mcusupport/mcupackage.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -25,6 +25,7 @@ #include "mcupackage.h" #include "mcusupportconstants.h" +#include "mcusupportversiondetection.h" #include "mcusupportsdk.h" #include @@ -314,4 +315,5 @@ bool McuToolChainPackage::isDesktopToolchain() const return m_type == Type::MSVC || m_type == Type::GCC; } + } // namespace McuSupport::Internal diff --git a/src/plugins/mcusupport/mcupackage.h b/src/plugins/mcusupport/mcupackage.h index 5afa32e009f..f2d6aa5276d 100644 --- a/src/plugins/mcusupport/mcupackage.h +++ b/src/plugins/mcusupport/mcupackage.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 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,10 +26,8 @@ #pragma once #include "mcuabstractpackage.h" -#include "mcusupportversiondetection.h" #include -#include #include @@ -42,11 +40,14 @@ class ToolChain; namespace Utils { class PathChooser; class InfoLabel; +class Id; } // namespace Utils namespace McuSupport { namespace Internal { +class McuPackageVersionDetector; + class McuPackage : public McuAbstractPackage { Q_OBJECT diff --git a/src/plugins/mcusupport/mcusupport.qbs b/src/plugins/mcusupport/mcusupport.qbs index 1710166a975..b7b8e146102 100644 --- a/src/plugins/mcusupport/mcusupport.qbs +++ b/src/plugins/mcusupport/mcusupport.qbs @@ -18,6 +18,8 @@ QtcPlugin { "mcuabstractpackage.h", "mcupackage.cpp", "mcupackage.h", + "mcutarget.cpp", + "mcutarget.h", "mcusupport.qrc", "mcusupport_global.h", "mcusupportconstants.h", @@ -25,6 +27,8 @@ QtcPlugin { "mcusupportdevice.h", "mcusupportoptions.cpp", "mcusupportoptions.h", + "mcukitmanager.cpp", + "mcukitmanager.h", "mcusupportoptionspage.cpp", "mcusupportoptionspage.h", "mcusupportplugin.cpp", diff --git a/src/plugins/mcusupport/mcusupportoptions.cpp b/src/plugins/mcusupport/mcusupportoptions.cpp index f9972473613..8d8721323b9 100644 --- a/src/plugins/mcusupport/mcusupportoptions.cpp +++ b/src/plugins/mcusupport/mcusupportoptions.cpp @@ -25,47 +25,26 @@ #include "mcusupportoptions.h" -#include "mcukitinformation.h" #include "mcupackage.h" +#include "mcutarget.h" +#include "mcukitmanager.h" +#include "mcukitinformation.h" #include "mcusupportcmakemapper.h" #include "mcusupportconstants.h" -#include "mcusupportplugin.h" #include "mcusupportsdk.h" +#include "mcusupportplugin.h" -#include #include #include #include #include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include #include #include -#include -#include -#include -#include #include #include -#include -#include -#include using CMakeProjectManager::CMakeConfigItem; using CMakeProjectManager::CMakeConfigurationKitAspect; @@ -75,261 +54,6 @@ using namespace Utils; namespace McuSupport { namespace Internal { -static const int KIT_VERSION = 9; // Bumps up whenever details in Kit creation change - -static bool kitNeedsQtVersion() -{ - // Only on Windows, Qt is linked into the distributed qul Desktop libs. Also, the host tools - // are missing the Qt runtime libraries on non-Windows. - return !HostOsInfo::isWindowsHost(); -} - -static ToolChain *msvcToolChain(Id language) -{ - ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) { - const Abi abi = t->targetAbi(); - // TODO: Should Abi::WindowsMsvc2022Flavor be added too? - return (abi.osFlavor() == Abi::WindowsMsvc2017Flavor - || abi.osFlavor() == Abi::WindowsMsvc2019Flavor) - && abi.architecture() == Abi::X86Architecture && abi.wordWidth() == 64 - && t->language() == language; - }); - return toolChain; -} - -static ToolChain *gccToolChain(Id language) -{ - ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) { - const Abi abi = t->targetAbi(); - return abi.os() != Abi::WindowsOS && abi.architecture() == Abi::X86Architecture - && abi.wordWidth() == 64 && t->language() == language; - }); - return toolChain; -} - -static ToolChain *armGccToolChain(const FilePath &path, Id language) -{ - ToolChain *toolChain = ToolChainManager::toolChain([&path, language](const ToolChain *t) { - return t->compilerCommand() == path && t->language() == language; - }); - if (!toolChain) { - ToolChainFactory *gccFactory - = Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), - [](ToolChainFactory *f) { - return f->supportedToolChainType() - == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID; - }); - if (gccFactory) { - const QList detected = gccFactory->detectForImport({path, language}); - if (!detected.isEmpty()) { - toolChain = detected.first(); - toolChain->setDetection(ToolChain::ManualDetection); - toolChain->setDisplayName("Arm GCC"); - ToolChainManager::registerToolChain(toolChain); - } - } - } - - return toolChain; -} - -static ToolChain *iarToolChain(const FilePath &path, Id language) -{ - ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) { - return t->typeId() == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID - && t->language() == language; - }); - if (!toolChain) { - ToolChainFactory *iarFactory - = Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), - [](ToolChainFactory *f) { - return f->supportedToolChainType() - == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID; - }); - if (iarFactory) { - Toolchains detected = iarFactory->autoDetect(ToolchainDetector({}, {})); - if (detected.isEmpty()) - detected = iarFactory->detectForImport({path, language}); - for (auto tc : detected) { - if (tc->language() == language) { - toolChain = tc; - toolChain->setDetection(ToolChain::ManualDetection); - toolChain->setDisplayName("IAREW"); - ToolChainManager::registerToolChain(toolChain); - } - } - } - } - - return toolChain; -} - -ToolChain *McuToolChainPackage::toolChain(Id language) const -{ - switch (m_type) { - case Type::MSVC: - return msvcToolChain(language); - case Type::GCC: - return gccToolChain(language); - case Type::IAR: { - const FilePath compiler = path().pathAppended("/bin/iccarm").withExecutableSuffix(); - return iarToolChain(compiler, language); - } - case Type::ArmGcc: - case Type::KEIL: - case Type::GHS: - case Type::GHSArm: - case Type::Unsupported: { - const QLatin1String compilerName( - language == ProjectExplorer::Constants::C_LANGUAGE_ID ? "gcc" : "g++"); - const QString comp = QLatin1String(m_type == Type::ArmGcc ? "/bin/arm-none-eabi-%1" - : "/bar/foo-keil-%1") - .arg(compilerName); - const FilePath compiler = path().pathAppended(comp).withExecutableSuffix(); - - return armGccToolChain(compiler, language); - } - default: - Q_UNREACHABLE(); - } -} - -QString McuToolChainPackage::toolChainName() const -{ - switch (m_type) { - case Type::ArmGcc: - return QLatin1String("armgcc"); - case Type::IAR: - return QLatin1String("iar"); - case Type::KEIL: - return QLatin1String("keil"); - case Type::GHS: - return QLatin1String("ghs"); - case Type::GHSArm: - return QLatin1String("ghs-arm"); - default: - return QLatin1String("unsupported"); - } -} - -QString McuToolChainPackage::cmakeToolChainFileName() const -{ - return toolChainName() + QLatin1String(".cmake"); -} - -QVariant McuToolChainPackage::debuggerId() const -{ - using namespace Debugger; - - QString sub, displayName; - DebuggerEngineType engineType; - - switch (m_type) { - case Type::ArmGcc: { - sub = QString::fromLatin1("bin/arm-none-eabi-gdb-py"); - displayName = McuPackage::tr("Arm GDB at %1"); - engineType = Debugger::GdbEngineType; - break; - } - case Type::IAR: { - sub = QString::fromLatin1("../common/bin/CSpyBat"); - displayName = QLatin1String("CSpy"); - engineType = Debugger::NoEngineType; // support for IAR missing - break; - } - case Type::KEIL: { - sub = QString::fromLatin1("UV4/UV4"); - displayName = QLatin1String("KEIL uVision Debugger"); - engineType = Debugger::UvscEngineType; - break; - } - default: - return QVariant(); - } - - const FilePath command = path().pathAppended(sub).withExecutableSuffix(); - if (const DebuggerItem *debugger = DebuggerItemManager::findByCommand(command)) { - return debugger->id(); - } - - DebuggerItem newDebugger; - newDebugger.setCommand(command); - newDebugger.setUnexpandedDisplayName(displayName.arg(command.toUserOutput())); - newDebugger.setEngineType(engineType); - return DebuggerItemManager::registerDebugger(newDebugger); -} - -McuTarget::McuTarget(const QVersionNumber &qulVersion, - const Platform &platform, - OS os, - const QVector &packages, - const McuToolChainPackage *toolChainPackage, - int colorDepth) - : m_qulVersion(qulVersion) - , m_platform(platform) - , m_os(os) - , m_packages(packages) - , m_toolChainPackage(toolChainPackage) - , m_colorDepth(colorDepth) -{} - -const QVector &McuTarget::packages() const -{ - return m_packages; -} - -const McuToolChainPackage *McuTarget::toolChainPackage() const -{ - return m_toolChainPackage; -} - -McuTarget::OS McuTarget::os() const -{ - return m_os; -} - -const McuTarget::Platform &McuTarget::platform() const -{ - return m_platform; -} - -bool McuTarget::isValid() const -{ - return Utils::allOf(packages(), [](McuAbstractPackage *package) { - package->updateStatus(); - return package->validStatus(); - }); -} - -void McuTarget::printPackageProblems() const -{ - for (auto package : packages()) { - package->updateStatus(); - if (!package->validStatus()) - printMessage(tr("Error creating kit for target %1, package %2: %3") - .arg(McuKitManager::kitName(this), - package->label(), - package->statusText()), - true); - if (package->status() == McuAbstractPackage::Status::ValidPackageMismatchedVersion) - printMessage(tr("Warning creating kit for target %1, package %2: %3") - .arg(McuKitManager::kitName(this), - package->label(), - package->statusText()), - false); - } -} - -const QVersionNumber &McuTarget::qulVersion() const -{ - return m_qulVersion; -} - -int McuTarget::colorDepth() const -{ - return m_colorDepth; -} - void McuSdkRepository::deletePackagesAndTargets() { qDeleteAll(packages); @@ -423,39 +147,6 @@ FilePath McuSupportOptions::qulDirFromSettings() QSettings::UserScope, {}); } -static void setKitProperties(const QString &kitName, - Kit *k, - const McuTarget *mcuTarget, - const FilePath &sdkPath) -{ - using namespace Constants; - - k->setUnexpandedDisplayName(kitName); - k->setValue(KIT_MCUTARGET_VENDOR_KEY, mcuTarget->platform().vendor); - k->setValue(KIT_MCUTARGET_MODEL_KEY, mcuTarget->platform().name); - k->setValue(KIT_MCUTARGET_COLORDEPTH_KEY, mcuTarget->colorDepth()); - k->setValue(KIT_MCUTARGET_SDKVERSION_KEY, mcuTarget->qulVersion().toString()); - k->setValue(KIT_MCUTARGET_KITVERSION_KEY, KIT_VERSION); - k->setValue(KIT_MCUTARGET_OS_KEY, static_cast(mcuTarget->os())); - k->setValue(KIT_MCUTARGET_TOOCHAIN_KEY, mcuTarget->toolChainPackage()->toolChainName()); - k->setAutoDetected(false); - k->makeSticky(); - if (mcuTarget->toolChainPackage()->isDesktopToolchain()) - k->setDeviceTypeForIcon(DEVICE_TYPE); - k->setValue(QtSupport::SuppliesQtQuickImportPath::id(), true); - k->setValue(QtSupport::KitQmlImportPath::id(), sdkPath.pathAppended("include/qul").toVariant()); - k->setValue(QtSupport::KitHasMergedHeaderPathsWithQmlImportPaths::id(), true); - QSet irrelevant = { - SysRootKitAspect::id(), - QtSupport::SuppliesQtQuickImportPath::id(), - QtSupport::KitQmlImportPath::id(), - QtSupport::KitHasMergedHeaderPathsWithQmlImportPaths::id(), - }; - if (!kitNeedsQtVersion()) - irrelevant.insert(QtSupport::QtKitAspect::id()); - k->setIrrelevantAspects(irrelevant); -} - void McuSupportOptions::remapQul2xCmakeVars(Kit *kit, const EnvironmentItems &envItems) { const auto cmakeVars = mapEnvVarsToQul2xCmakeVars(envItems); @@ -567,7 +258,7 @@ void McuSupportOptions::setKitEnvironment(Kit *k, processPackage(package); processPackage(qtForMCUsSdkPackage); - if (kitNeedsQtVersion()) + if (McuSupportOptions::kitsNeedQtVersion()) changes.append({QLatin1String("LD_LIBRARY_PATH"), "%{Qt:QT_INSTALL_LIBS}"}); // Hack, this problem should be solved in lower layer @@ -666,7 +357,7 @@ static void setKitCMakeOptions(Kit *k, const McuTarget *mcuTarget, const FilePat if (mcuTarget->colorDepth() != McuTarget::UnspecifiedColorDepth) config.append(CMakeConfigItem("QUL_COLOR_DEPTH", QString::number(mcuTarget->colorDepth()).toLatin1())); - if (kitNeedsQtVersion()) + if (McuSupportOptions::kitsNeedQtVersion()) config.append(CMakeConfigItem("CMAKE_PREFIX_PATH", "%{Qt:QT_INSTALL_PREFIX}")); CMakeConfigurationKitAspect::setConfiguration(k, config); @@ -682,129 +373,11 @@ static void setKitCMakeOptions(Kit *k, const McuTarget *mcuTarget, const FilePat static void setKitQtVersionOptions(Kit *k) { - if (!kitNeedsQtVersion()) + if (!McuSupportOptions::kitsNeedQtVersion()) QtSupport::QtKitAspect::setQtVersion(k, nullptr); // else: auto-select a Qt version } -QString McuKitManager::kitName(const McuTarget *mcuTarget) -{ - const McuToolChainPackage *tcPkg = mcuTarget->toolChainPackage(); - const QString compilerName = tcPkg && !tcPkg->isDesktopToolchain() - ? QString::fromLatin1(" (%1)").arg( - tcPkg->toolChainName().toUpper()) - : ""; - const QString colorDepth = mcuTarget->colorDepth() != McuTarget::UnspecifiedColorDepth - ? QString::fromLatin1(" %1bpp").arg(mcuTarget->colorDepth()) - : ""; - const QString targetName = mcuTarget->platform().displayName.isEmpty() - ? mcuTarget->platform().name - : mcuTarget->platform().displayName; - return QString::fromLatin1("Qt for MCUs %1.%2 - %3%4%5") - .arg(QString::number(mcuTarget->qulVersion().majorVersion()), - QString::number(mcuTarget->qulVersion().minorVersion()), - targetName, - colorDepth, - compilerName); -} - -QList McuKitManager::existingKits(const McuTarget *mcuTarget) -{ - using namespace Constants; - return Utils::filtered(KitManager::kits(), [mcuTarget](Kit *kit) { - return kit->value(KIT_MCUTARGET_KITVERSION_KEY) == KIT_VERSION - && (!mcuTarget - || (kit->value(KIT_MCUTARGET_VENDOR_KEY) == mcuTarget->platform().vendor - && kit->value(KIT_MCUTARGET_MODEL_KEY) == mcuTarget->platform().name - && kit->value(KIT_MCUTARGET_COLORDEPTH_KEY) == mcuTarget->colorDepth() - && kit->value(KIT_MCUTARGET_OS_KEY).toInt() - == static_cast(mcuTarget->os()) - && kit->value(KIT_MCUTARGET_TOOCHAIN_KEY) - == mcuTarget->toolChainPackage()->toolChainName())); - }); -} - -QList McuKitManager::matchingKits(const McuTarget *mcuTarget, - const McuAbstractPackage *qtForMCUsSdkPackage) -{ - return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) { - return kitIsUpToDate(kit, mcuTarget, qtForMCUsSdkPackage); - }); -} - -QList McuKitManager::upgradeableKits(const McuTarget *mcuTarget, - const McuAbstractPackage *qtForMCUsSdkPackage) -{ - return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) { - return !kitIsUpToDate(kit, mcuTarget, qtForMCUsSdkPackage); - }); -} - -QList McuKitManager::kitsWithMismatchedDependencies(const McuTarget *mcuTarget) -{ - return Utils::filtered(existingKits(mcuTarget), [mcuTarget](Kit *kit) { - const auto environment = Utils::NameValueDictionary( - Utils::NameValueItem::toStringList(EnvironmentKitAspect::environmentChanges(kit))); - return Utils::anyOf(mcuTarget->packages(), - [&environment](const McuAbstractPackage *package) { - return !package->environmentVariableName().isEmpty() - && environment.value(package->environmentVariableName()) - != package->path().toUserOutput(); - }); - }); -} - -QList McuKitManager::outdatedKits() -{ - return Utils::filtered(KitManager::kits(), [](Kit *kit) { - return !kit->value(Constants::KIT_MCUTARGET_VENDOR_KEY).isNull() - && kit->value(Constants::KIT_MCUTARGET_KITVERSION_KEY) != KIT_VERSION; - }); -} - -void McuKitManager::removeOutdatedKits() -{ - for (auto kit : outdatedKits()) - KitManager::deregisterKit(kit); -} - -Kit *McuKitManager::newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk) -{ - const auto init = [mcuTarget, qtForMCUsSdk](Kit *k) { - KitGuard kitGuard(k); - - setKitProperties(kitName(mcuTarget), k, mcuTarget, qtForMCUsSdk->path()); - setKitDevice(k, mcuTarget); - setKitToolchains(k, mcuTarget->toolChainPackage()); - setKitDebugger(k, mcuTarget->toolChainPackage()); - McuSupportOptions::setKitEnvironment(k, mcuTarget, qtForMCUsSdk); - setKitDependencies(k, mcuTarget, qtForMCUsSdk); - setKitCMakeOptions(k, mcuTarget, qtForMCUsSdk->path()); - setKitQtVersionOptions(k); - - k->setup(); - k->fix(); - }; - - return KitManager::registerKit(init); -} - -void printMessage(const QString &message, bool important) -{ - const QString displayMessage = QCoreApplication::translate("QtForMCUs", "Qt for MCUs: %1") - .arg(message); - if (important) - Core::MessageManager::writeFlashing(displayMessage); - else - Core::MessageManager::writeSilently(displayMessage); -} - -QVersionNumber McuKitManager::kitQulVersion(const Kit *kit) -{ - return QVersionNumber::fromString( - kit->value(McuSupport::Constants::KIT_MCUTARGET_SDKVERSION_KEY).toString()); -} - static FilePath kitDependencyPath(const Kit *kit, const QString &variableName) { for (const NameValueItem &nameValueItem : EnvironmentKitAspect::environmentChanges(kit)) { @@ -814,21 +387,7 @@ static FilePath kitDependencyPath(const Kit *kit, const QString &variableName) return FilePath(); } -bool McuKitManager::kitIsUpToDate(const Kit *kit, - const McuTarget *mcuTarget, - const McuAbstractPackage *qtForMCUsSdkPackage) -{ - return kitQulVersion(kit) == mcuTarget->qulVersion() - && kitDependencyPath(kit, qtForMCUsSdkPackage->environmentVariableName()).toUserOutput() - == qtForMCUsSdkPackage->path().toUserOutput(); -} - -void McuSupportOptions::deletePackagesAndTargets() -{ - sdkRepository.deletePackagesAndTargets(); -} - -McuKitManager::UpgradeOption McuKitManager::askForKitUpgrades() +McuKitManager::UpgradeOption McuSupportOptions::askForKitUpgrades() { QMessageBox upgradePopup(Core::ICore::dialogParent()); upgradePopup.setStandardButtons(QMessageBox::Cancel); @@ -841,88 +400,21 @@ McuKitManager::UpgradeOption McuKitManager::askForKitUpgrades() upgradePopup.exec(); if (upgradePopup.clickedButton() == keepButton) - return UpgradeOption::Keep; + return McuKitManager::UpgradeOption::Keep; if (upgradePopup.clickedButton() == replaceButton) - return UpgradeOption::Replace; + return McuKitManager::UpgradeOption::Replace; - return UpgradeOption::Ignore; + return McuKitManager::UpgradeOption::Ignore; } -void McuKitManager::createAutomaticKits() + +void McuSupportOptions::deletePackagesAndTargets() { - auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); - - const auto createKits = [qtForMCUsPackage]() { - if (qtForMCUsPackage->automaticKitCreationEnabled()) { - qtForMCUsPackage->updateStatus(); - if (!qtForMCUsPackage->validStatus()) { - switch (qtForMCUsPackage->status()) { - case McuAbstractPackage::Status::ValidPathInvalidPackage: { - const QString displayPath - = FilePath::fromString(qtForMCUsPackage->detectionPath()).toUserOutput(); - printMessage(tr("Path %1 exists, but does not contain %2.") - .arg(qtForMCUsPackage->path().toUserOutput(), displayPath), - true); - break; - } - case McuAbstractPackage::Status::InvalidPath: { - printMessage(tr("Path %1 does not exist. Add the path in Tools > Options > " - "Devices > MCU.") - .arg(qtForMCUsPackage->path().toUserOutput()), - true); - break; - } - case McuAbstractPackage::Status::EmptyPath: { - printMessage(tr("Missing %1. Add the path in Tools > Options > Devices > MCU.") - .arg(qtForMCUsPackage->detectionPath()), - true); - return; - } - default: - break; - } - return; - } - - if (CMakeProjectManager::CMakeToolManager::cmakeTools().isEmpty()) { - printMessage(tr("No CMake tool was detected. Add a CMake tool in Tools > Options > " - "Kits > CMake."), - true); - return; - } - - FilePath dir = qtForMCUsPackage->path(); - McuSdkRepository repo; - Sdk::targetsAndPackages(dir, &repo); - - bool needsUpgrade = false; - for (const auto &target : qAsConst(repo.mcuTargets)) { - // if kit already exists, skip - if (!matchingKits(target, qtForMCUsPackage).empty()) - continue; - if (!upgradeableKits(target, qtForMCUsPackage).empty()) { - // if kit exists but wrong version/path - needsUpgrade = true; - } else { - // if no kits for this target, create - if (target->isValid()) - newKit(target, qtForMCUsPackage); - target->printPackageProblems(); - } - } - - repo.deletePackagesAndTargets(); - - if (needsUpgrade) - McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade(); - } - }; - - createKits(); - delete qtForMCUsPackage; + sdkRepository.deletePackagesAndTargets(); } + void McuSupportOptions::checkUpgradeableKits() { if (!qtForMCUsSdkPackage->validStatus() || sdkRepository.mcuTargets.length() == 0) @@ -932,142 +424,14 @@ void McuSupportOptions::checkUpgradeableKits() return !McuKitManager::upgradeableKits(target, this->qtForMCUsSdkPackage).empty() && McuKitManager::matchingKits(target, this->qtForMCUsSdkPackage).empty(); })) - McuKitManager::upgradeKitsByCreatingNewPackage(McuKitManager::askForKitUpgrades()); + McuKitManager::upgradeKitsByCreatingNewPackage(askForKitUpgrades()); } -void McuKitManager::upgradeKitsByCreatingNewPackage(UpgradeOption upgradeOption) +bool McuSupportOptions::kitsNeedQtVersion() { - if (upgradeOption == UpgradeOption::Ignore) - return; - - auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); - - auto dir = qtForMCUsPackage->path(); - McuSdkRepository repo; - Sdk::targetsAndPackages(dir, &repo); - - for (const auto &target : qAsConst(repo.mcuTargets)) { - if (!McuKitManager::matchingKits(target, qtForMCUsPackage).empty()) - // already up-to-date - continue; - - const auto kits = McuKitManager::upgradeableKits(target, qtForMCUsPackage); - if (!kits.empty()) { - if (upgradeOption == UpgradeOption::Replace) { - for (auto existingKit : kits) - KitManager::deregisterKit(existingKit); - } - - if (target->isValid()) - newKit(target, qtForMCUsPackage); - target->printPackageProblems(); - } - } - - repo.deletePackagesAndTargets(); - delete qtForMCUsPackage; -} - -void McuKitManager::upgradeKitInPlace(ProjectExplorer::Kit *kit, - const McuTarget *mcuTarget, - const McuAbstractPackage *qtForMCUsSdk) -{ - setKitProperties(kitName(mcuTarget), kit, mcuTarget, qtForMCUsSdk->path()); - McuSupportOptions::setKitEnvironment(kit, mcuTarget, qtForMCUsSdk); - setKitDependencies(kit, mcuTarget, qtForMCUsSdk); -} - -void McuKitManager::fixKitsDependencies() -{ - auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); - - FilePath dir = qtForMCUsPackage->path(); - McuSdkRepository repo; - Sdk::targetsAndPackages(dir, &repo); - for (const auto &target : qAsConst(repo.mcuTargets)) { - if (target->isValid()) { - for (auto *kit : kitsWithMismatchedDependencies(target)) { - McuSupportOptions::updateKitEnvironment(kit, target); - } - } - } - - repo.deletePackagesAndTargets(); - delete qtForMCUsPackage; -} - -/** - * @brief Fix/update existing kits if needed - */ -void McuKitManager::fixExistingKits() -{ - for (Kit *kit : KitManager::kits()) { - if (!kit->hasValue(Constants::KIT_MCUTARGET_KITVERSION_KEY)) - continue; - - if (kit->isAutoDetected()) { - kit->setAutoDetected(false); - } - - // Check if the MCU kits are flagged as supplying a QtQuick import path, in order - // to tell the QMLJS code-model that it won't need to add a fall-back import - // path. - const auto bringsQtQuickImportPath = QtSupport::SuppliesQtQuickImportPath::id(); - auto irrelevantAspects = kit->irrelevantAspects(); - if (!irrelevantAspects.contains(bringsQtQuickImportPath)) { - irrelevantAspects.insert(bringsQtQuickImportPath); - kit->setIrrelevantAspects(irrelevantAspects); - } - if (!kit->hasValue(bringsQtQuickImportPath)) { - kit->setValue(bringsQtQuickImportPath, true); - } - - // Check if the MCU kit supplies its import path. - const auto kitQmlImportPath = QtSupport::KitQmlImportPath::id(); - if (!irrelevantAspects.contains(kitQmlImportPath)) { - irrelevantAspects.insert(kitQmlImportPath); - kit->setIrrelevantAspects(irrelevantAspects); - } - if (!kit->hasValue(kitQmlImportPath)) { - auto config = CMakeProjectManager::CMakeConfigurationKitAspect::configuration(kit); - for (const auto &cfgItem : qAsConst(config)) { - if (cfgItem.key == "QUL_GENERATORS") { - auto idx = cfgItem.value.indexOf("/lib/cmake/Qul"); - auto qulDir = cfgItem.value.left(idx); - kit->setValue(kitQmlImportPath, QVariant(qulDir + "/include/qul")); - break; - } - } - } - - // Check if the MCU kit has the flag for merged header/qml-import paths set. - const auto mergedPaths = QtSupport::KitHasMergedHeaderPathsWithQmlImportPaths::id(); - if (!irrelevantAspects.contains(mergedPaths)) { - irrelevantAspects.insert(mergedPaths); - kit->setIrrelevantAspects(irrelevantAspects); - } - if (!kit->value(mergedPaths, false).toBool()) { - kit->setValue(mergedPaths, true); - } - } - - // Fix kit dependencies for known targets - auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); - qtForMCUsPackage->updateStatus(); - if (qtForMCUsPackage->validStatus()) { - FilePath dir = qtForMCUsPackage->path(); - McuSdkRepository repo; - Sdk::targetsAndPackages(dir, &repo); - for (const auto &target : qAsConst(repo.mcuTargets)) - for (auto kit : existingKits(target)) { - if (McuDependenciesKitAspect::dependencies(kit).isEmpty()) { - setKitDependencies(kit, target, qtForMCUsPackage); - } - } - - repo.deletePackagesAndTargets(); - } - delete qtForMCUsPackage; + // Only on Windows, Qt is linked into the distributed qul Desktop libs. Also, the host tools + // are missing the Qt runtime libraries on non-Windows. + return !HostOsInfo::isWindowsHost(); } } // namespace Internal diff --git a/src/plugins/mcusupport/mcusupportoptions.h b/src/plugins/mcusupport/mcusupportoptions.h index 61be8a8df6c..02e672486c2 100644 --- a/src/plugins/mcusupport/mcusupportoptions.h +++ b/src/plugins/mcusupport/mcusupportoptions.h @@ -27,8 +27,8 @@ #include #include "mcusupport_global.h" +#include "mcukitmanager.h" -#include #include #include #include @@ -51,49 +51,7 @@ namespace Internal { class McuAbstractPackage; class McuToolChainPackage; - -void printMessage(const QString &message, bool important); - -class McuTarget : public QObject -{ - Q_OBJECT - -public: - enum class OS { Desktop, BareMetal, FreeRTOS }; - - struct Platform - { - QString name; - QString displayName; - QString vendor; - }; - - enum { UnspecifiedColorDepth = -1 }; - - McuTarget(const QVersionNumber &qulVersion, - const Platform &platform, - OS os, - const QVector &packages, - const McuToolChainPackage *toolChainPackage, - int colorDepth = UnspecifiedColorDepth); - - const QVersionNumber &qulVersion() const; - const QVector &packages() const; - const McuToolChainPackage *toolChainPackage() const; - const Platform &platform() const; - OS os() const; - int colorDepth() const; - bool isValid() const; - void printPackageProblems() const; - -private: - const QVersionNumber m_qulVersion; - const Platform m_platform; - const OS m_os; - const QVector m_packages; - const McuToolChainPackage *m_toolChainPackage; - const int m_colorDepth; -}; // class McuTarget +class McuTarget; class McuSdkRepository { @@ -122,6 +80,7 @@ public: static void updateKitEnvironment(ProjectExplorer::Kit *, const McuTarget *); static void remapQul2xCmakeVars(ProjectExplorer::Kit *, const Utils::EnvironmentItems &); static Utils::FilePath qulDirFromSettings(); + static McuKitManager::UpgradeOption askForKitUpgrades(); static void registerQchFiles(); static void registerExamples(); @@ -130,6 +89,8 @@ public: void checkUpgradeableKits(); void populatePackagesAndTargets(); + + static bool kitsNeedQtVersion(); private: void deletePackagesAndTargets(); @@ -137,47 +98,6 @@ signals: void packagesChanged(); }; -class McuKitManager -{ - Q_DECLARE_TR_FUNCTIONS(McuSupport::Internal::McuKitManager) - -public: - enum class UpgradeOption { - Ignore, - Keep, - Replace - }; - - // Creating kits: - static ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk); - static void createAutomaticKits(); - - // Querying the kits: - static QList existingKits(const McuTarget *mcuTarget); - static QList matchingKits(const McuTarget *mcuTarget, - const McuAbstractPackage *qtForMCUsSdkPackage); - static QList upgradeableKits( - const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage); - static QList kitsWithMismatchedDependencies(const McuTarget *mcuTarget); - - // Upgrading kits: - static UpgradeOption askForKitUpgrades(); - static void upgradeKitsByCreatingNewPackage(UpgradeOption upgradeOption); - static void upgradeKitInPlace(ProjectExplorer::Kit *kit, const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk); - - // Fixing kits: - static void fixKitsDependencies(); - static void fixExistingKits(); - - // Outdated kits: - static QList outdatedKits(); - static void removeOutdatedKits(); - - // Querying kits: - static QString kitName(const McuTarget* mcuTarget); - static QVersionNumber kitQulVersion(const ProjectExplorer::Kit *kit); - static bool kitIsUpToDate(const ProjectExplorer::Kit *kit, const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage); -}; } // namespace Internal } // namespace McuSupport diff --git a/src/plugins/mcusupport/mcusupportoptionspage.cpp b/src/plugins/mcusupport/mcusupportoptionspage.cpp index 81fd58080e3..7eb8c160b0b 100644 --- a/src/plugins/mcusupport/mcusupportoptionspage.cpp +++ b/src/plugins/mcusupport/mcusupportoptionspage.cpp @@ -25,9 +25,11 @@ #include "mcusupportoptionspage.h" #include "mcupackage.h" +#include "mcutarget.h" #include "mcusupportconstants.h" #include "mcusupportoptions.h" #include "mcusupportsdk.h" +#include "mcukitmanager.h" #include #include diff --git a/src/plugins/mcusupport/mcusupportplugin.cpp b/src/plugins/mcusupport/mcusupportplugin.cpp index 75cc6b78921..f0778b04b24 100644 --- a/src/plugins/mcusupport/mcusupportplugin.cpp +++ b/src/plugins/mcusupport/mcusupportplugin.cpp @@ -28,6 +28,7 @@ #include "mcusupportconstants.h" #include "mcusupportdevice.h" #include "mcusupportoptions.h" +#include "mcukitmanager.h" #include "mcusupportoptionspage.h" #include "mcusupportrunconfiguration.h" @@ -38,6 +39,7 @@ #include #include #include +#include #include #include @@ -53,6 +55,16 @@ using namespace ProjectExplorer; namespace McuSupport { namespace Internal { +void printMessage(const QString &message, bool important) +{ + const QString displayMessage = QCoreApplication::translate("QtForMCUs", "Qt for MCUs: %1") + .arg(message); + if (important) + Core::MessageManager::writeFlashing(displayMessage); + else + Core::MessageManager::writeSilently(displayMessage); +} + class McuSupportPluginPrivate { public: diff --git a/src/plugins/mcusupport/mcusupportplugin.h b/src/plugins/mcusupport/mcusupportplugin.h index 2286ed0aad2..21767a02f07 100644 --- a/src/plugins/mcusupport/mcusupportplugin.h +++ b/src/plugins/mcusupport/mcusupportplugin.h @@ -31,6 +31,8 @@ namespace McuSupport::Internal { +void printMessage(const QString &message, bool important); + class McuSupportPlugin final : public ExtensionSystem::IPlugin { Q_OBJECT diff --git a/src/plugins/mcusupport/mcusupportsdk.cpp b/src/plugins/mcusupport/mcusupportsdk.cpp index 9911fcbf50c..5550a6848cc 100644 --- a/src/plugins/mcusupport/mcusupportsdk.cpp +++ b/src/plugins/mcusupport/mcusupportsdk.cpp @@ -25,10 +25,13 @@ #include "mcusupportsdk.h" #include "mcupackage.h" +#include "mcutarget.h" #include "mcusupportconstants.h" #include "mcusupportoptions.h" +#include "mcukitmanager.h" #include "mcusupportversiondetection.h" #include "mcutargetdescription.h" +#include "mcusupportplugin.h" #include #include diff --git a/src/plugins/mcusupport/mcutarget.cpp b/src/plugins/mcusupport/mcutarget.cpp new file mode 100644 index 00000000000..291b861e221 --- /dev/null +++ b/src/plugins/mcusupport/mcutarget.cpp @@ -0,0 +1,290 @@ +/**************************************************************************** +** +** 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 "mcutarget.h" +#include "mcupackage.h" +#include "mcukitmanager.h" + +#include "mcusupportplugin.h" + +#include +#include +#include +#include +#include +#include + +using namespace ProjectExplorer; +using namespace Utils; + +namespace McuSupport::Internal { + +static ToolChain *msvcToolChain(Id language) +{ + ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) { + const Abi abi = t->targetAbi(); + // TODO: Should Abi::WindowsMsvc2022Flavor be added too? + return (abi.osFlavor() == Abi::WindowsMsvc2017Flavor + || abi.osFlavor() == Abi::WindowsMsvc2019Flavor) + && abi.architecture() == Abi::X86Architecture && abi.wordWidth() == 64 + && t->language() == language; + }); + return toolChain; +} + +static ToolChain *gccToolChain(Id language) +{ + ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) { + const Abi abi = t->targetAbi(); + return abi.os() != Abi::WindowsOS && abi.architecture() == Abi::X86Architecture + && abi.wordWidth() == 64 && t->language() == language; + }); + return toolChain; +} + +static ToolChain *armGccToolChain(const FilePath &path, Id language) +{ + ToolChain *toolChain = ToolChainManager::toolChain([&path, language](const ToolChain *t) { + return t->compilerCommand() == path && t->language() == language; + }); + if (!toolChain) { + ToolChainFactory *gccFactory + = Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), + [](ToolChainFactory *f) { + return f->supportedToolChainType() + == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID; + }); + if (gccFactory) { + const QList detected = gccFactory->detectForImport({path, language}); + if (!detected.isEmpty()) { + toolChain = detected.first(); + toolChain->setDetection(ToolChain::ManualDetection); + toolChain->setDisplayName("Arm GCC"); + ToolChainManager::registerToolChain(toolChain); + } + } + } + + return toolChain; +} + +static ToolChain *iarToolChain(const FilePath &path, Id language) +{ + ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) { + return t->typeId() == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID + && t->language() == language; + }); + if (!toolChain) { + ToolChainFactory *iarFactory + = Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), + [](ToolChainFactory *f) { + return f->supportedToolChainType() + == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID; + }); + if (iarFactory) { + Toolchains detected = iarFactory->autoDetect(ToolchainDetector({}, {})); + if (detected.isEmpty()) + detected = iarFactory->detectForImport({path, language}); + for (auto tc : detected) { + if (tc->language() == language) { + toolChain = tc; + toolChain->setDetection(ToolChain::ManualDetection); + toolChain->setDisplayName("IAREW"); + ToolChainManager::registerToolChain(toolChain); + } + } + } + } + + return toolChain; +} + +ToolChain *McuToolChainPackage::toolChain(Id language) const +{ + switch (m_type) { + case Type::MSVC: + return msvcToolChain(language); + case Type::GCC: + return gccToolChain(language); + case Type::IAR: { + const FilePath compiler = path().pathAppended("/bin/iccarm").withExecutableSuffix(); + return iarToolChain(compiler, language); + } + case Type::ArmGcc: + case Type::KEIL: + case Type::GHS: + case Type::GHSArm: + case Type::Unsupported: { + const QLatin1String compilerName( + language == ProjectExplorer::Constants::C_LANGUAGE_ID ? "gcc" : "g++"); + const QString comp = QLatin1String(m_type == Type::ArmGcc ? "/bin/arm-none-eabi-%1" + : "/bar/foo-keil-%1") + .arg(compilerName); + const FilePath compiler = path().pathAppended(comp).withExecutableSuffix(); + + return armGccToolChain(compiler, language); + } + default: + Q_UNREACHABLE(); + } +} + +QString McuToolChainPackage::toolChainName() const +{ + switch (m_type) { + case Type::ArmGcc: + return QLatin1String("armgcc"); + case Type::IAR: + return QLatin1String("iar"); + case Type::KEIL: + return QLatin1String("keil"); + case Type::GHS: + return QLatin1String("ghs"); + case Type::GHSArm: + return QLatin1String("ghs-arm"); + default: + return QLatin1String("unsupported"); + } +} + +QString McuToolChainPackage::cmakeToolChainFileName() const +{ + return toolChainName() + QLatin1String(".cmake"); +} + +QVariant McuToolChainPackage::debuggerId() const +{ + using namespace Debugger; + + QString sub, displayName; + DebuggerEngineType engineType; + + switch (m_type) { + case Type::ArmGcc: { + sub = QString::fromLatin1("bin/arm-none-eabi-gdb-py"); + displayName = McuPackage::tr("Arm GDB at %1"); + engineType = Debugger::GdbEngineType; + break; + } + case Type::IAR: { + sub = QString::fromLatin1("../common/bin/CSpyBat"); + displayName = QLatin1String("CSpy"); + engineType = Debugger::NoEngineType; // support for IAR missing + break; + } + case Type::KEIL: { + sub = QString::fromLatin1("UV4/UV4"); + displayName = QLatin1String("KEIL uVision Debugger"); + engineType = Debugger::UvscEngineType; + break; + } + default: + return QVariant(); + } + + const FilePath command = path().pathAppended(sub).withExecutableSuffix(); + if (const DebuggerItem *debugger = DebuggerItemManager::findByCommand(command)) { + return debugger->id(); + } + + DebuggerItem newDebugger; + newDebugger.setCommand(command); + newDebugger.setUnexpandedDisplayName(displayName.arg(command.toUserOutput())); + newDebugger.setEngineType(engineType); + return DebuggerItemManager::registerDebugger(newDebugger); +} + +McuTarget::McuTarget(const QVersionNumber &qulVersion, + const Platform &platform, + OS os, + const QVector &packages, + const McuToolChainPackage *toolChainPackage, + int colorDepth) + : m_qulVersion(qulVersion) + , m_platform(platform) + , m_os(os) + , m_packages(packages) + , m_toolChainPackage(toolChainPackage) + , m_colorDepth(colorDepth) +{} + +const QVector &McuTarget::packages() const +{ + return m_packages; +} + +const McuToolChainPackage *McuTarget::toolChainPackage() const +{ + return m_toolChainPackage; +} + +McuTarget::OS McuTarget::os() const +{ + return m_os; +} + +const McuTarget::Platform &McuTarget::platform() const +{ + return m_platform; +} + +bool McuTarget::isValid() const +{ + return Utils::allOf(packages(), [](McuAbstractPackage *package) { + package->updateStatus(); + return package->validStatus(); + }); +} + +void McuTarget::printPackageProblems() const +{ + for (auto package : packages()) { + package->updateStatus(); + if (!package->validStatus()) + printMessage(tr("Error creating kit for target %1, package %2: %3") + .arg(McuKitManager::kitName(this), + package->label(), + package->statusText()), + true); + if (package->status() == McuAbstractPackage::Status::ValidPackageMismatchedVersion) + printMessage(tr("Warning creating kit for target %1, package %2: %3") + .arg(McuKitManager::kitName(this), + package->label(), + package->statusText()), + false); + } +} + +const QVersionNumber &McuTarget::qulVersion() const +{ + return m_qulVersion; +} + +int McuTarget::colorDepth() const +{ + return m_colorDepth; +} + +} // namespace McuSupport::Internal diff --git a/src/plugins/mcusupport/mcutarget.h b/src/plugins/mcusupport/mcutarget.h new file mode 100644 index 00000000000..7426f81e152 --- /dev/null +++ b/src/plugins/mcusupport/mcutarget.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** 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 +#include + +namespace ProjectExplorer { +class ToolChain; +} + +namespace Utils { +class PathChooser; +class InfoLabel; +} // namespace Utils + +namespace McuSupport { +namespace Internal { + +class McuAbstractPackage; +class McuToolChainPackage; + +class McuTarget : public QObject +{ + Q_OBJECT + +public: + enum class OS { Desktop, BareMetal, FreeRTOS }; + + struct Platform + { + QString name; + QString displayName; + QString vendor; + }; + + enum { UnspecifiedColorDepth = -1 }; + + McuTarget(const QVersionNumber &qulVersion, + const Platform &platform, + OS os, + const QVector &packages, + const McuToolChainPackage *toolChainPackage, + int colorDepth = UnspecifiedColorDepth); + + const QVersionNumber &qulVersion() const; + const QVector &packages() const; + const McuToolChainPackage *toolChainPackage() const; + const Platform &platform() const; + OS os() const; + int colorDepth() const; + bool isValid() const; + void printPackageProblems() const; + +private: + const QVersionNumber m_qulVersion; + const Platform m_platform; + const OS m_os; + const QVector m_packages; + const McuToolChainPackage *m_toolChainPackage; + const int m_colorDepth; +}; // class McuTarget + + +} // namespace Internal +} // namespace McuSupport diff --git a/src/plugins/mcusupport/test/unittest.cpp b/src/plugins/mcusupport/test/unittest.cpp index c5de1a208fb..3651369cb92 100644 --- a/src/plugins/mcusupport/test/unittest.cpp +++ b/src/plugins/mcusupport/test/unittest.cpp @@ -25,6 +25,7 @@ #include "unittest.h" #include "mcutargetdescription.h" +#include "mcukitmanager.h" #include "nxp_1064_json.h" #include "utils/filepath.h" #include diff --git a/src/plugins/mcusupport/test/unittest.h b/src/plugins/mcusupport/test/unittest.h index 0f2235afa19..dcdb5370b2d 100644 --- a/src/plugins/mcusupport/test/unittest.h +++ b/src/plugins/mcusupport/test/unittest.h @@ -26,6 +26,7 @@ #pragma once #include "mcupackage.h" +#include "mcutarget.h" #include "mcusupportoptions.h" #include "mcusupportplugin.h" #include "mcusupportsdk.h"