Files
qt-creator/src/plugins/mcusupport/mcukitmanager.cpp
Kwangsub Kim d881932695 McuSupport: Update library path for Windows platform
The Qt shared library for Windows desktop platform has been
moved from Qul 2.3.0 to support MinGW toolchain. The updated
library path needs to be configured correctly.

Task-number: QTCREATORBUG-28303
Change-Id: I7cf8150bfb4a66731904ea49089849496305f22e
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
2022-11-08 10:24:18 +00:00

719 lines
30 KiB
C++

// Copyright (C) 2020 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "mcukitmanager.h"
#include "mculegacyconstants.h"
#include "mcusupportoptions.h"
#include "mcukitinformation.h"
#include "mcupackage.h"
#include "mcusupportconstants.h"
#include "mcusupportplugin.h"
#include "mcusupportsdk.h"
#include "mcusupporttr.h"
#include "mcutarget.h"
#include <cmakeprojectmanager/cmakekitinformation.h>
#include <cmakeprojectmanager/cmaketoolmanager.h>
#include <coreplugin/icore.h>
#include <debugger/debuggeritem.h>
#include <debugger/debuggeritemmanager.h>
#include <debugger/debuggerkitinformation.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/toolchain.h>
#include <qtsupport/qtkitinformation.h>
#include <qtsupport/qtversionmanager.h>
#include <utils/algorithm.h>
#include <QMessageBox>
#include <QPushButton>
using CMakeProjectManager::CMakeConfig;
using CMakeProjectManager::CMakeConfigItem;
using CMakeProjectManager::CMakeConfigurationKitAspect;
using namespace ProjectExplorer;
using namespace Utils;
namespace McuSupport::Internal {
// Utils for managing CMake Configurations
static QMap<QByteArray, QByteArray> cMakeConfigToMap(const CMakeConfig &config)
{
QMap<QByteArray, QByteArray> map;
for (const auto &configItem : std::as_const(config.toList())) {
map.insert(configItem.key, configItem.value);
}
return map;
}
static CMakeConfig mapToCMakeConfig(const QMap<QByteArray, QByteArray> &map)
{
QList<CMakeConfigItem> asList;
for (auto it = map.constKeyValueBegin(); it != map.constKeyValueEnd(); ++it) {
asList.append(CMakeConfigItem(it->first, it->second));
}
return CMakeConfig(asList);
}
namespace McuKitManager {
static const int KIT_VERSION = 9; // Bumps up whenever details in Kit creation change
class McuKitFactory
{
public:
static void setKitToolchains(Kit *k, const McuToolChainPackagePtr &tcPackage)
{
switch (tcPackage->toolchainType()) {
case McuToolChainPackage::ToolChainType::Unsupported:
return;
case McuToolChainPackage::ToolChainType::GHS:
case McuToolChainPackage::ToolChainType::GHSArm:
return; // No Green Hills toolchain, because support for it is missing.
case McuToolChainPackage::ToolChainType::IAR:
case McuToolChainPackage::ToolChainType::KEIL:
case McuToolChainPackage::ToolChainType::MSVC:
case McuToolChainPackage::ToolChainType::GCC:
case McuToolChainPackage::ToolChainType::MinGW:
case McuToolChainPackage::ToolChainType::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(Kit *k, const McuTarget *mcuTarget, const FilePath &sdkPath)
{
using namespace Constants;
const QString kitName{generateKitNameFromTarget(mcuTarget)};
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<int>(mcuTarget->os()));
k->setValue(KIT_MCUTARGET_TOOLCHAIN_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 / "include/qul").toVariant());
k->setValue(QtSupport::KitHasMergedHeaderPathsWithQmlImportPaths::id(), true);
QSet<Id> 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 McuToolChainPackagePtr &tcPackage)
{
if (tcPackage->isDesktopToolchain()) {
// Qt Creator seems to be smart enough to deduce the right Kit debugger from the ToolChain
return;
}
switch (tcPackage->toolchainType()) {
case McuToolChainPackage::ToolChainType::Unsupported:
case McuToolChainPackage::ToolChainType::GHS:
case McuToolChainPackage::ToolChainType::GHSArm:
case McuToolChainPackage::ToolChainType::IAR:
return; // No Green Hills and IAR debugger, because support for it is missing.
case McuToolChainPackage::ToolChainType::KEIL:
case McuToolChainPackage::ToolChainType::MSVC:
case McuToolChainPackage::ToolChainType::GCC:
case McuToolChainPackage::ToolChainType::MinGW:
case McuToolChainPackage::ToolChainType::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 void setKitDependencies(Kit *k,
const McuTarget *mcuTarget,
const McuPackagePtr &qtForMCUsSdkPackage)
{
NameValueItems dependencies;
auto processPackage = [&dependencies](const McuPackagePtr &package) {
const auto cmakeVariableName = package->cmakeVariableName();
if (!cmakeVariableName.isEmpty())
dependencies.append({cmakeVariableName, package->detectionPath().toUserOutput()});
};
for (const 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 setKitEnvironment(Kit *k,
const McuTarget *mcuTarget,
const McuPackagePtr &qtForMCUsSdkPackage)
{
EnvironmentItems changes;
QStringList pathAdditions; // clazy:exclude=inefficient-qlist-soft
// The Desktop version depends on the Qt shared libs.
// As CMake's fileApi is available, we can rely on the "Add library search path to PATH"
// feature of the run configuration.
//
// Since MinGW support is added from Qul 2.3.0,
// the Qt shared libs for Windows desktop platform have been moved
// from Qul_DIR/bin to Qul_DIR/lib/(msvc|gnu)
// and the QPA plugin has been moved to the same location.
// So Windows host requires to add the path in this case.
if (mcuTarget->toolChainPackage()->isDesktopToolchain() && HostOsInfo::isWindowsHost()
&& !McuSupportOptions::isLegacyVersion(mcuTarget->qulVersion())) {
const FilePath libPath = (qtForMCUsSdkPackage->path() / "lib"
/ mcuTarget->desktopCompilerId());
pathAdditions.append(libPath.toUserOutput());
changes.append({"QT_QPA_PLATFORM_PLUGIN_PATH", libPath.toUserOutput()});
}
auto processPackage = [&pathAdditions](const McuPackagePtr &package) {
if (package->isAddToSystemPath())
pathAdditions.append(package->path().toUserOutput());
};
for (const auto &package : mcuTarget->packages())
processPackage(package);
processPackage(qtForMCUsSdkPackage);
if (!pathAdditions.isEmpty()) {
const QString path = QLatin1String(HostOsInfo::isWindowsHost() ? "Path" : "PATH");
pathAdditions.append("${" + path + "}");
changes.append({path, pathAdditions.join(HostOsInfo::pathListSeparator())});
}
if (McuSupportOptions::kitsNeedQtVersion())
changes.append({QLatin1String("LD_LIBRARY_PATH"), "%{Qt:QT_INSTALL_LIBS}"});
EnvironmentKitAspect::setEnvironmentChanges(k, changes);
}
static void setKitCMakeOptions(Kit *k,
const McuTarget *mcuTarget,
const McuPackagePtr &qtForMCUsSdkPackage)
{
using namespace CMakeProjectManager;
auto configMap = cMakeConfigToMap(CMakeConfigurationKitAspect::configuration(k));
// CMake ToolChain file for ghs handles CMAKE_*_COMPILER autonomously
const QList autonomousCompilerDetectionToolchains{
McuToolChainPackage::ToolChainType::GHS,
McuToolChainPackage::ToolChainType::GHSArm,
};
if (!autonomousCompilerDetectionToolchains.contains(
mcuTarget->toolChainPackage()->toolchainType())) {
configMap.insert("CMAKE_CXX_COMPILER", "%{Compiler:Executable:Cxx}");
configMap.insert("CMAKE_C_COMPILER", "%{Compiler:Executable:C}");
}
auto toolchainPackage = mcuTarget->toolChainPackage();
if (toolchainPackage->isDesktopToolchain()) {
auto cToolchain = toolchainPackage->toolChain(ProjectExplorer::Constants::C_LANGUAGE_ID);
auto cxxToolchain = toolchainPackage->toolChain(
ProjectExplorer::Constants::CXX_LANGUAGE_ID);
if (cToolchain && cxxToolchain) {
configMap.insert("CMAKE_CXX_COMPILER",
cxxToolchain->compilerCommand().toString().toLatin1());
configMap.insert("CMAKE_C_COMPILER",
cToolchain->compilerCommand().toString().toLatin1());
} else {
printMessage(Tr::tr("Warning for target %1: invalid toolchain path (%2). "
"Update the toolchain in Edit > Preferences > Kits.")
.arg(generateKitNameFromTarget(mcuTarget),
toolchainPackage->path().toUserOutput()),
true);
}
if (!McuSupportOptions::isLegacyVersion(mcuTarget->qulVersion())
&& HostOsInfo::isWindowsHost()) {
// From 2.3.0, QUL_COMPILER_NAME needs to be set on Windows
// to select proper cmake files depending on the toolchain for Windows.
configMap.insert("QUL_COMPILER_NAME", mcuTarget->desktopCompilerId().toLatin1());
}
} else {
const FilePath cMakeToolchainFile = mcuTarget->toolChainFilePackage()->path();
configMap.insert(Legacy::Constants::TOOLCHAIN_FILE_CMAKE_VARIABLE,
cMakeToolchainFile.toString().toUtf8());
if (!cMakeToolchainFile.exists()) {
printMessage(
McuTarget::tr(
"Warning for target %1: missing CMake toolchain file expected at %2.")
.arg(generateKitNameFromTarget(mcuTarget),
cMakeToolchainFile.toUserOutput()),
false);
}
}
const FilePath generatorsPath = qtForMCUsSdkPackage->path().pathAppended(
"/lib/cmake/Qul/QulGenerators.cmake");
configMap.insert("QUL_GENERATORS", generatorsPath.toString().toUtf8());
if (!generatorsPath.exists()) {
printMessage(McuTarget::tr(
"Warning for target %1: missing QulGenerators expected at %2.")
.arg(generateKitNameFromTarget(mcuTarget),
generatorsPath.toUserOutput()),
false);
}
configMap.insert("QUL_PLATFORM", mcuTarget->platform().name.toLower().toUtf8());
if (mcuTarget->colorDepth() != McuTarget::UnspecifiedColorDepth)
configMap.insert("QUL_COLOR_DEPTH", QString::number(mcuTarget->colorDepth()).toLatin1());
if (McuSupportOptions::kitsNeedQtVersion())
configMap.insert("CMAKE_PREFIX_PATH", "%{Qt:QT_INSTALL_PREFIX}");
if (HostOsInfo::isWindowsHost()) {
auto type = mcuTarget->toolChainPackage()->toolchainType();
if (type == McuToolChainPackage::ToolChainType::GHS
|| type == McuToolChainPackage::ToolChainType::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");
}
}
auto processPackage = [&configMap](const McuPackagePtr &package) {
if (!package->cmakeVariableName().isEmpty())
configMap.insert(package->cmakeVariableName().toUtf8(),
package->path().toUserOutput().toUtf8());
};
for (auto package : mcuTarget->packages())
processPackage(package);
processPackage(qtForMCUsSdkPackage);
CMakeConfigurationKitAspect::setConfiguration(k, mapToCMakeConfig(configMap));
}
static void setKitQtVersionOptions(Kit *k)
{
if (!McuSupportOptions::kitsNeedQtVersion())
QtSupport::QtKitAspect::setQtVersion(k, nullptr);
// else: auto-select a Qt version
}
}; // class McuKitFactory
// Construct kit
Kit *newKit(const McuTarget *mcuTarget, const McuPackagePtr &qtForMCUsSdk)
{
const auto init = [&mcuTarget, qtForMCUsSdk](Kit *k) {
KitGuard kitGuard(k);
McuKitFactory::setKitProperties(k, mcuTarget, qtForMCUsSdk->path());
McuKitFactory::setKitDevice(k, mcuTarget);
McuKitFactory::setKitToolchains(k, mcuTarget->toolChainPackage());
McuKitFactory::setKitDebugger(k, mcuTarget->toolChainPackage());
McuKitFactory::setKitEnvironment(k, mcuTarget, qtForMCUsSdk);
McuKitFactory::setKitCMakeOptions(k, mcuTarget, qtForMCUsSdk);
McuKitFactory::setKitDependencies(k, mcuTarget, qtForMCUsSdk);
McuKitFactory::setKitQtVersionOptions(k);
k->setup();
k->fix();
};
Kit *kit = KitManager::registerKit(init);
if (kit) {
printMessage(Tr::tr("Kit for %1 created.").arg(generateKitNameFromTarget(mcuTarget)), false);
} else {
printMessage(Tr::tr("Error registering Kit for %1.")
.arg(generateKitNameFromTarget(mcuTarget)),
true);
}
return kit;
}
// Kit Information
QString generateKitNameFromTarget(const McuTarget *mcuTarget)
{
McuToolChainPackagePtr tcPkg = mcuTarget->toolChainPackage();
const QString compilerName = tcPkg ? 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);
}
// Kit Information
QVersionNumber kitQulVersion(const Kit *kit)
{
return QVersionNumber::fromString(
kit->value(Constants::KIT_MCUTARGET_SDKVERSION_KEY).toString());
}
// Kit Information
static FilePath kitDependencyPath(const Kit *kit, const QString &cmakeVariableName)
{
const auto config = CMakeConfigurationKitAspect::configuration(kit).toList();
const auto keyName = cmakeVariableName.toUtf8();
for (const CMakeConfigItem &configItem : config) {
if (configItem.key == keyName)
return FilePath::fromUserInput(QString::fromUtf8(configItem.value));
}
return FilePath();
}
// Kit Information
bool kitIsUpToDate(const Kit *kit,
const McuTarget *mcuTarget,
const McuPackagePtr &qtForMCUsSdkPackage)
{
return kitQulVersion(kit) == mcuTarget->qulVersion()
&& kitDependencyPath(kit, qtForMCUsSdkPackage->cmakeVariableName()).toUserOutput()
== qtForMCUsSdkPackage->path().toUserOutput();
}
// Queries
QList<Kit *> 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<int>(mcuTarget->os())
&& kit->value(KIT_MCUTARGET_TOOLCHAIN_KEY)
== mcuTarget->toolChainPackage()->toolChainName()));
});
}
// Queries
QList<Kit *> matchingKits(const McuTarget *mcuTarget, const McuPackagePtr &qtForMCUsSdkPackage)
{
return Utils::filtered(existingKits(mcuTarget), [&mcuTarget, qtForMCUsSdkPackage](Kit *kit) {
return kitIsUpToDate(kit, mcuTarget, qtForMCUsSdkPackage);
});
}
// Queries
QList<Kit *> upgradeableKits(const McuTarget *mcuTarget, const McuPackagePtr &qtForMCUsSdkPackage)
{
return Utils::filtered(existingKits(mcuTarget), [&mcuTarget, qtForMCUsSdkPackage](Kit *kit) {
return !kitIsUpToDate(kit, mcuTarget, qtForMCUsSdkPackage);
});
}
// Queries
QList<Kit *> kitsWithMismatchedDependencies(const McuTarget *mcuTarget)
{
return Utils::filtered(existingKits(mcuTarget), [&mcuTarget](Kit *kit) {
const auto entries = Utils::NameValueDictionary(
McuDependenciesKitAspect::configuration(kit));
return Utils::anyOf(mcuTarget->packages(), [&entries](const McuPackagePtr &package) {
const QString cmakeVariableName = package->cmakeVariableName();
return !cmakeVariableName.isEmpty()
&& entries.value(cmakeVariableName) != package->path().toUserOutput();
});
});
}
// Queries
QList<Kit *> 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;
});
}
// Maintenance
void createAutomaticKits(const SettingsHandler::Ptr &settingsHandler)
{
McuPackagePtr qtForMCUsPackage{createQtForMCUsPackage(settingsHandler)};
const auto createKits = [qtForMCUsPackage, settingsHandler]() {
if (settingsHandler->isAutomaticKitCreationEnabled()) {
qtForMCUsPackage->updateStatus();
if (!qtForMCUsPackage->isValidStatus()) {
switch (qtForMCUsPackage->status()) {
case McuAbstractPackage::Status::ValidPathInvalidPackage: {
printMessage(McuPackage::tr("Path %1 exists, but does not contain %2.")
.arg(qtForMCUsPackage->path().toUserOutput(),
qtForMCUsPackage->detectionPath().toUserOutput()),
true);
break;
}
case McuAbstractPackage::Status::InvalidPath: {
printMessage(McuPackage::tr(
"Path %1 does not exist. Add the path in Edit > Preferences > "
"Devices > MCU.")
.arg(qtForMCUsPackage->path().toUserOutput()),
true);
break;
}
case McuAbstractPackage::Status::EmptyPath: {
printMessage(
McuPackage::tr(
"Missing %1. Add the path in Edit > Preferences > Devices > MCU.")
.arg(qtForMCUsPackage->detectionPath().toUserOutput()),
true);
return;
}
default:
break;
}
return;
}
if (CMakeProjectManager::CMakeToolManager::cmakeTools().isEmpty()) {
printMessage(
McuPackage::tr(
"No CMake tool was detected. Add a CMake tool in Edit > Preferences > "
"Kits > CMake."),
true);
return;
}
McuSdkRepository repo{targetsAndPackages(qtForMCUsPackage, settingsHandler)};
bool needsUpgrade = false;
for (const auto &target : std::as_const(repo.mcuTargets)) {
// if kit already exists, skip
if (!matchingKits(target.get(), qtForMCUsPackage).empty())
continue;
if (!upgradeableKits(target.get(), qtForMCUsPackage).empty()) {
// if kit exists but wrong version/path
needsUpgrade = true;
} else {
// if no kits for this target, create
if (target->isValid())
newKit(target.get(), qtForMCUsPackage);
target->printPackageProblems();
}
}
if (needsUpgrade)
McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade(settingsHandler);
}
};
createKits();
}
// Maintenance
// when the SDK version has changed, and the user has given permission
// to upgrade, create new kits with current data, for the targets
// for which kits already existed
// function parameter is option to keep the old ones or delete them
void upgradeKitsByCreatingNewPackage(const SettingsHandler::Ptr &settingsHandler,
UpgradeOption upgradeOption)
{
if (upgradeOption == UpgradeOption::Ignore)
return;
McuPackagePtr qtForMCUsPackage{createQtForMCUsPackage(settingsHandler)};
McuSdkRepository repo{targetsAndPackages(qtForMCUsPackage, settingsHandler)};
for (const auto &target : std::as_const(repo.mcuTargets)) {
if (!matchingKits(target.get(), qtForMCUsPackage).empty())
// already up-to-date
continue;
const auto kits = upgradeableKits(target.get(), qtForMCUsPackage);
if (!kits.empty()) {
if (upgradeOption == UpgradeOption::Replace) {
for (auto existingKit : kits)
KitManager::deregisterKit(existingKit);
}
if (target->isValid())
newKit(target.get(), qtForMCUsPackage);
target->printPackageProblems();
}
}
}
// Maintenance
// when the user manually asks to upgrade a specific kit
// button is available if SDK version changed
void upgradeKitInPlace(ProjectExplorer::Kit *kit,
const McuTarget *mcuTarget,
const McuPackagePtr &qtForMCUsSdk)
{
McuKitFactory::setKitProperties(kit, mcuTarget, qtForMCUsSdk->path());
McuKitFactory::setKitEnvironment(kit, mcuTarget, qtForMCUsSdk);
McuKitFactory::setKitCMakeOptions(kit, mcuTarget, qtForMCUsSdk);
McuKitFactory::setKitDependencies(kit, mcuTarget, qtForMCUsSdk);
}
// Maintenance
// If the user changed a path in the McuSupport plugin's UI
// update the corresponding cmake variables in all existing kits
void updatePathsInExistingKits(const SettingsHandler::Ptr &settingsHandler)
{
McuPackagePtr qtForMCUsPackage{createQtForMCUsPackage(settingsHandler)};
McuSdkRepository repo{targetsAndPackages(qtForMCUsPackage, settingsHandler)};
for (const auto &target : std::as_const(repo.mcuTargets)) {
if (target->isValid()) {
for (auto *kit : kitsWithMismatchedDependencies(target.get())) {
if (kitQulVersion(kit) != target->qulVersion()) {
//Do not update kits made for other Qt for MCUs SDK versions
continue;
}
auto changes = cMakeConfigToMap(CMakeConfigurationKitAspect::configuration(kit));
const auto updateForPackage = [&changes](const McuPackagePtr &package) {
if (!package->cmakeVariableName().isEmpty() && package->isValidStatus()) {
changes.insert(package->cmakeVariableName().toUtf8(),
package->path().toUserOutput().toUtf8());
}
};
for (const auto &package : target->packages()) {
updateForPackage(package);
}
updateForPackage(qtForMCUsPackage);
CMakeConfigurationKitAspect::setConfiguration(kit,
CMakeProjectManager::CMakeConfig(
mapToCMakeConfig(changes)));
}
}
}
}
// Maintenance
// if we changed minor details in the kits across versions of QtCreator
// this function updates those details in existing older kits
void fixExistingKits(const SettingsHandler::Ptr &settingsHandler)
{
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 : std::as_const(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
McuPackagePtr qtForMCUsPackage{createQtForMCUsPackage(settingsHandler)};
qtForMCUsPackage->updateStatus();
if (qtForMCUsPackage->isValidStatus()) {
McuSdkRepository repo{targetsAndPackages(qtForMCUsPackage, settingsHandler)};
for (const auto &target : std::as_const(repo.mcuTargets))
for (auto kit : existingKits(target.get())) {
if (McuDependenciesKitAspect::dependencies(kit).isEmpty()) {
McuKitFactory::setKitCMakeOptions(kit, target.get(), qtForMCUsPackage);
McuKitFactory::setKitDependencies(kit, target.get(), qtForMCUsPackage);
}
}
}
}
// Maintenance
// removes kits with older schemes
void removeOutdatedKits()
{
for (auto kit : outdatedKits())
KitManager::deregisterKit(kit);
}
} // namespace McuKitManager
} // namespace McuSupport::Internal