McuSupport: Detect dependency versions when building MCU kits

Task-number: QTCREATORBUG-25261
Change-Id: I79d24aa2e26a3f647bd2251c0407c7d09eea73b3
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Dawid Śliwa <dawid.sliwa@qt.io>
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
Christiaan Janssen
2021-02-15 16:20:38 +01:00
committed by christiaan.janssen
parent 3cb6d17d5a
commit 3e08210998
9 changed files with 365 additions and 32 deletions

View File

@@ -11,4 +11,5 @@ add_qtc_plugin(McuSupport
mcusupportplugin.cpp mcusupportplugin.h mcusupportplugin.cpp mcusupportplugin.h
mcusupportsdk.cpp mcusupportsdk.h mcusupportsdk.cpp mcusupportsdk.h
mcusupportrunconfiguration.cpp mcusupportrunconfiguration.h mcusupportrunconfiguration.cpp mcusupportrunconfiguration.h
mcusupportversiondetection.cpp mcusupportversiondetection.h
) )

View File

@@ -12,7 +12,8 @@ HEADERS += \
mcusupportoptionspage.h \ mcusupportoptionspage.h \
mcusupportplugin.h \ mcusupportplugin.h \
mcusupportsdk.h \ mcusupportsdk.h \
mcusupportrunconfiguration.h mcusupportrunconfiguration.h \
mcusupportversiondetection.h
SOURCES += \ SOURCES += \
mcusupportdevice.cpp \ mcusupportdevice.cpp \
@@ -20,7 +21,8 @@ SOURCES += \
mcusupportoptionspage.cpp \ mcusupportoptionspage.cpp \
mcusupportplugin.cpp \ mcusupportplugin.cpp \
mcusupportsdk.cpp \ mcusupportsdk.cpp \
mcusupportrunconfiguration.cpp mcusupportrunconfiguration.cpp \
mcusupportversiondetection.cpp
RESOURCES += \ RESOURCES += \
mcusupport.qrc mcusupport.qrc

View File

@@ -30,5 +30,7 @@ QtcPlugin {
"mcusupportsdk.h", "mcusupportsdk.h",
"mcusupportrunconfiguration.cpp", "mcusupportrunconfiguration.cpp",
"mcusupportrunconfiguration.h", "mcusupportrunconfiguration.h",
"mcusupportversiondetection.cpp",
"mcusupportversiondetection.h",
] ]
} }

View File

@@ -96,11 +96,13 @@ static bool kitNeedsQtVersion()
} }
McuPackage::McuPackage(const QString &label, const QString &defaultPath, McuPackage::McuPackage(const QString &label, const QString &defaultPath,
const QString &detectionPath, const QString &settingsKey) const QString &detectionPath, const QString &settingsKey,
const McuPackageVersionDetector *versionDetector)
: m_label(label) : m_label(label)
, m_defaultPath(packagePathFromSettings(settingsKey, QSettings::SystemScope, defaultPath)) , m_defaultPath(packagePathFromSettings(settingsKey, QSettings::SystemScope, defaultPath))
, m_detectionPath(detectionPath) , m_detectionPath(detectionPath)
, m_settingsKey(settingsKey) , m_settingsKey(settingsKey)
, m_versionDetector(versionDetector)
{ {
m_path = packagePathFromSettings(settingsKey, QSettings::UserScope, m_defaultPath); m_path = packagePathFromSettings(settingsKey, QSettings::UserScope, m_defaultPath);
m_automaticKitCreation = automaticKitCreationFromSettings(QSettings::UserScope); m_automaticKitCreation = automaticKitCreationFromSettings(QSettings::UserScope);
@@ -182,6 +184,11 @@ McuPackage::Status McuPackage::status() const
return m_status; return m_status;
} }
bool McuPackage::validStatus() const
{
return m_status == McuPackage::ValidPackage || m_status == McuPackage::ValidPackageMismatchedVersion;
}
void McuPackage::setDownloadUrl(const QString &url) void McuPackage::setDownloadUrl(const QString &url)
{ {
m_downloadUrl = url; m_downloadUrl = url;
@@ -227,6 +234,11 @@ void McuPackage::setRelativePathModifier(const QString &path)
m_relativePathModifier = path; m_relativePathModifier = path;
} }
void McuPackage::setVersions(const QVector<QString> &versions)
{
m_versions = versions;
}
bool McuPackage::automaticKitCreationEnabled() const bool McuPackage::automaticKitCreationEnabled() const
{ {
return m_automaticKitCreation; return m_automaticKitCreation;
@@ -249,34 +261,59 @@ void McuPackage::updateStatus()
bool validPath = !m_path.isEmpty() && FilePath::fromString(m_path).exists(); bool validPath = !m_path.isEmpty() && FilePath::fromString(m_path).exists();
const FilePath detectionPath = FilePath::fromString(basePath() + "/" + m_detectionPath); const FilePath detectionPath = FilePath::fromString(basePath() + "/" + m_detectionPath);
const bool validPackage = m_detectionPath.isEmpty() || detectionPath.exists(); const bool validPackage = m_detectionPath.isEmpty() || detectionPath.exists();
m_detectedVersion = validPath && validPackage && m_versionDetector ? m_versionDetector->parseVersion(basePath()) : QString();
const bool validVersion = m_detectedVersion.isEmpty() ||
m_versions.isEmpty() || m_versions.contains(m_detectedVersion);
m_status = validPath ? (validPackage ? ValidPackage : ValidPathInvalidPackage) : m_status = validPath ?
m_path.isEmpty() ? EmptyPath : InvalidPath; ( validPackage ?
(validVersion ? ValidPackage : ValidPackageMismatchedVersion)
: ValidPathInvalidPackage )
: m_path.isEmpty() ? EmptyPath : InvalidPath;
emit statusChanged(); emit statusChanged();
} }
void McuPackage::updateStatusUi() void McuPackage::updateStatusUi()
{ {
m_infoLabel->setType(m_status == ValidPackage ? InfoLabel::Ok : InfoLabel::NotOk); m_infoLabel->setType(validStatus() ? InfoLabel::Ok : InfoLabel::NotOk);
m_infoLabel->setText(statusText()); m_infoLabel->setText(statusText());
} }
QString McuPackage::statusText() const QString McuPackage::statusText() const
{ {
const QString displayPackagePath = FilePath::fromString(m_path).toUserOutput(); const QString displayPackagePath = FilePath::fromString(m_path).toUserOutput();
const QString displayDetectionPath = FilePath::fromString(m_detectionPath).toUserOutput(); const QString displayVersions = m_versions.isEmpty() ? "" :
QString(" (%1)").arg(QStringList(m_versions.toList()).join(" / "));
const QString displayRequiredPath = QString("%1 %2").arg(
FilePath::fromString(m_detectionPath).toUserOutput(),
displayVersions);
const QString displayDetectedPath = QString("%1 %2").arg(
FilePath::fromString(m_detectionPath).toUserOutput(),
m_detectedVersion);
QString response; QString response;
switch (m_status) { switch (m_status) {
case ValidPackage: case ValidPackage:
response = m_detectionPath.isEmpty() response = m_detectionPath.isEmpty()
? tr("Path %1 exists.").arg(displayPackagePath) ? ( m_detectedVersion.isEmpty()
? tr("Path %1 exists.").arg(displayPackagePath)
: tr("Path %1 exists. Version %2 was found.")
.arg(displayPackagePath, m_detectedVersion) )
: tr("Path %1 is valid, %2 was found.") : tr("Path %1 is valid, %2 was found.")
.arg(displayPackagePath, displayDetectionPath); .arg(displayPackagePath, displayDetectedPath);
break; break;
case ValidPackageMismatchedVersion: {
const QString versionWarning = m_versions.size() == 1 ?
tr("version %1 is recommended").arg(m_versions.first()) :
tr("versions %1 are recommended").arg(displayVersions);
response = tr("Path %1 is valid, %2 was found, but %3.")
.arg(displayPackagePath, displayDetectedPath, versionWarning);
break;
}
case ValidPathInvalidPackage: case ValidPathInvalidPackage:
response = tr("Path %1 exists, but does not contain %2.") response = tr("Path %1 exists, but does not contain %2.")
.arg(displayPackagePath, displayDetectionPath); .arg(displayPackagePath, displayRequiredPath);
break; break;
case InvalidPath: case InvalidPath:
response = tr("Path %1 does not exist.").arg(displayPackagePath); response = tr("Path %1 does not exist.").arg(displayPackagePath);
@@ -285,7 +322,7 @@ QString McuPackage::statusText() const
response = m_detectionPath.isEmpty() response = m_detectionPath.isEmpty()
? tr("Path is empty.") ? tr("Path is empty.")
: tr("Path is empty, %1 not found.") : tr("Path is empty, %1 not found.")
.arg(displayDetectionPath); .arg(displayRequiredPath);
break; break;
} }
return response; return response;
@@ -295,8 +332,9 @@ McuToolChainPackage::McuToolChainPackage(const QString &label,
const QString &defaultPath, const QString &defaultPath,
const QString &detectionPath, const QString &detectionPath,
const QString &settingsKey, const QString &settingsKey,
McuToolChainPackage::Type type) McuToolChainPackage::Type type,
: McuPackage(label, defaultPath, detectionPath, settingsKey) const McuPackageVersionDetector *versionDetector)
: McuPackage(label, defaultPath, detectionPath, settingsKey, versionDetector)
, m_type(type) , m_type(type)
{ {
} }
@@ -484,9 +522,9 @@ McuTarget::Platform McuTarget::platform() const
bool McuTarget::isValid() const bool McuTarget::isValid() const
{ {
return !Utils::anyOf(packages(), [](McuPackage *package) { return Utils::allOf(packages(), [](McuPackage *package) {
package->updateStatus(); package->updateStatus();
return package->status() != McuPackage::ValidPackage; return package->validStatus();
}); });
} }
@@ -494,12 +532,18 @@ void McuTarget::printPackageProblems() const
{ {
for (auto package: packages()) { for (auto package: packages()) {
package->updateStatus(); package->updateStatus();
if (package->status() != McuPackage::ValidPackage) if (!package->validStatus())
printMessage(QString("Error creating kit for target %1, package %2: %3").arg( printMessage(tr("Error creating kit for target %1, package %2: %3").arg(
McuSupportOptions::kitName(this), McuSupportOptions::kitName(this),
package->label(), package->label(),
package->statusText()), package->statusText()),
true); true);
if (package->status() == McuPackage::ValidPackageMismatchedVersion)
printMessage(tr("Warning creating kit for target %1, package %2: %3").arg(
McuSupportOptions::kitName(this),
package->label(),
package->statusText()),
false);
} }
} }
@@ -598,7 +642,7 @@ void McuSupportOptions::setQulDir(const FilePath &dir)
{ {
deletePackagesAndTargets(); deletePackagesAndTargets();
qtForMCUsSdkPackage->updateStatus(); qtForMCUsSdkPackage->updateStatus();
if (qtForMCUsSdkPackage->status() == McuPackage::Status::ValidPackage) if (qtForMCUsSdkPackage->validStatus())
Sdk::targetsAndPackages(dir, &packages, &mcuTargets); Sdk::targetsAndPackages(dir, &packages, &mcuTargets);
for (auto package : qAsConst(packages)) for (auto package : qAsConst(packages))
connect(package, &McuPackage::changed, this, &McuSupportOptions::changed); connect(package, &McuPackage::changed, this, &McuSupportOptions::changed);
@@ -858,7 +902,7 @@ void McuSupportOptions::createAutomaticKits()
const auto createKits = [qtForMCUsPackage]() { const auto createKits = [qtForMCUsPackage]() {
if (qtForMCUsPackage->automaticKitCreationEnabled()) { if (qtForMCUsPackage->automaticKitCreationEnabled()) {
qtForMCUsPackage->updateStatus(); qtForMCUsPackage->updateStatus();
if (qtForMCUsPackage->status() != McuPackage::ValidPackage) { if (!qtForMCUsPackage->validStatus()) {
switch (qtForMCUsPackage->status()) { switch (qtForMCUsPackage->status()) {
case McuPackage::ValidPathInvalidPackage: { case McuPackage::ValidPathInvalidPackage: {
const QString displayPath = FilePath::fromString(qtForMCUsPackage->detectionPath()) const QString displayPath = FilePath::fromString(qtForMCUsPackage->detectionPath())
@@ -900,8 +944,7 @@ void McuSupportOptions::createAutomaticKits()
if (existingKits(target).isEmpty()) { if (existingKits(target).isEmpty()) {
if (target->isValid()) if (target->isValid())
newKit(target, qtForMCUsPackage); newKit(target, qtForMCUsPackage);
else target->printPackageProblems();
target->printPackageProblems();
} }
qDeleteAll(packages); qDeleteAll(packages);

View File

@@ -25,6 +25,8 @@
#pragma once #pragma once
#include "mcusupportversiondetection.h"
#include <utils/id.h> #include <utils/id.h>
#include <QObject> #include <QObject>
@@ -58,11 +60,13 @@ public:
EmptyPath, EmptyPath,
InvalidPath, InvalidPath,
ValidPathInvalidPackage, ValidPathInvalidPackage,
ValidPackageMismatchedVersion,
ValidPackage ValidPackage
}; };
McuPackage(const QString &label, const QString &defaultPath, const QString &detectionPath, McuPackage(const QString &label, const QString &defaultPath,
const QString &settingsKey); const QString &detectionPath, const QString &settingsKey,
const McuPackageVersionDetector *versionDetector = nullptr);
virtual ~McuPackage() = default; virtual ~McuPackage() = default;
QString basePath() const; QString basePath() const;
@@ -74,6 +78,7 @@ public:
void updateStatus(); void updateStatus();
Status status() const; Status status() const;
bool validStatus() const;
void setDownloadUrl(const QString &url); void setDownloadUrl(const QString &url);
void setEnvironmentVariableName(const QString &name); void setEnvironmentVariableName(const QString &name);
void setAddToPath(bool addToPath); void setAddToPath(bool addToPath);
@@ -81,6 +86,7 @@ public:
void writeGeneralSettings() const; void writeGeneralSettings() const;
void writeToSettings() const; void writeToSettings() const;
void setRelativePathModifier(const QString &path); void setRelativePathModifier(const QString &path);
void setVersions(const QVector<QString> &versions);
bool automaticKitCreationEnabled() const; bool automaticKitCreationEnabled() const;
void setAutomaticKitCreationEnabled(const bool enabled); void setAutomaticKitCreationEnabled(const bool enabled);
@@ -105,9 +111,12 @@ private:
const QString m_defaultPath; const QString m_defaultPath;
const QString m_detectionPath; const QString m_detectionPath;
const QString m_settingsKey; const QString m_settingsKey;
const McuPackageVersionDetector *m_versionDetector;
QString m_path; QString m_path;
QString m_relativePathModifier; // relative path to m_path to be returned by path() QString m_relativePathModifier; // relative path to m_path to be returned by path()
QString m_detectedVersion;
QVector<QString> m_versions;
QString m_downloadUrl; QString m_downloadUrl;
QString m_environmentVariableName; QString m_environmentVariableName;
bool m_addToPath = false; bool m_addToPath = false;
@@ -133,7 +142,9 @@ public:
const QString &defaultPath, const QString &defaultPath,
const QString &detectionPath, const QString &detectionPath,
const QString &settingsKey, const QString &settingsKey,
Type type); Type type,
const McuPackageVersionDetector *versionDetector = nullptr
);
Type type() const; Type type() const;
bool isDesktopToolchain() const; bool isDesktopToolchain() const;

View File

@@ -185,7 +185,7 @@ void McuSupportOptionsWidget::updateStatus()
{ {
m_qtForMCUsSdkGroupBox->setVisible(cMakeAvailable); m_qtForMCUsSdkGroupBox->setVisible(cMakeAvailable);
const bool valid = cMakeAvailable && const bool valid = cMakeAvailable &&
m_options.qtForMCUsSdkPackage->status() == McuPackage::ValidPackage; m_options.qtForMCUsSdkPackage->validStatus();
const bool ready = valid && mcuTarget; const bool ready = valid && mcuTarget;
m_mcuTargetsGroupBox->setVisible(ready); m_mcuTargetsGroupBox->setVisible(ready);
m_packagesGroupBox->setVisible(ready && !mcuTarget->packages().isEmpty()); m_packagesGroupBox->setVisible(ready && !mcuTarget->packages().isEmpty());

View File

@@ -26,6 +26,7 @@
#include "mcusupportconstants.h" #include "mcusupportconstants.h"
#include "mcusupportoptions.h" #include "mcusupportoptions.h"
#include "mcusupportsdk.h" #include "mcusupportsdk.h"
#include "mcusupportversiondetection.h"
#include <baremetal/baremetalconstants.h> #include <baremetal/baremetalconstants.h>
#include <projectexplorer/toolchain.h> #include <projectexplorer/toolchain.h>
@@ -107,12 +108,20 @@ static McuToolChainPackage *createArmGccPackage()
if (defaultPath.isEmpty()) if (defaultPath.isEmpty())
defaultPath = QDir::homePath(); defaultPath = QDir::homePath();
const QString detectionPath = Utils::HostOsInfo::withExecutableSuffix("bin/arm-none-eabi-g++");
const auto versionDetector = new McuPackageExecutableVersionDetector(
detectionPath,
{ "--version" },
"\\b(\\d+\\.\\d+\\.\\d+)\\b"
);
auto result = new McuToolChainPackage( auto result = new McuToolChainPackage(
McuPackage::tr("GNU Arm Embedded Toolchain"), McuPackage::tr("GNU Arm Embedded Toolchain"),
defaultPath, defaultPath,
Utils::HostOsInfo::withExecutableSuffix("bin/arm-none-eabi-g++"), detectionPath,
"GNUArmEmbeddedToolchain", "GNUArmEmbeddedToolchain",
McuToolChainPackage::TypeArmGcc); McuToolChainPackage::TypeArmGcc,
versionDetector);
result->setEnvironmentVariableName(envVar); result->setEnvironmentVariableName(envVar);
return result; return result;
} }
@@ -124,12 +133,19 @@ static McuToolChainPackage *createGhsToolchainPackage()
const QString defaultPath = const QString defaultPath =
qEnvironmentVariableIsSet(envVar) ? qEnvironmentVariable(envVar) : QDir::homePath(); qEnvironmentVariableIsSet(envVar) ? qEnvironmentVariable(envVar) : QDir::homePath();
const auto versionDetector = new McuPackageExecutableVersionDetector(
Utils::HostOsInfo::withExecutableSuffix("as850"),
{"-V"},
"\\bv(\\d+\\.\\d+\\.\\d+)\\b"
);
auto result = new McuToolChainPackage( auto result = new McuToolChainPackage(
"Green Hills Compiler", "Green Hills Compiler",
defaultPath, defaultPath,
Utils::HostOsInfo::withExecutableSuffix("ccv850"), Utils::HostOsInfo::withExecutableSuffix("ccv850"),
"GHSToolchain", "GHSToolchain",
McuToolChainPackage::TypeGHS); McuToolChainPackage::TypeGHS,
versionDetector);
result->setEnvironmentVariableName(envVar); result->setEnvironmentVariableName(envVar);
return result; return result;
} }
@@ -154,12 +170,20 @@ static McuToolChainPackage *createIarToolChainPackage()
defaultPath = QDir::homePath(); defaultPath = QDir::homePath();
} }
const QString detectionPath = Utils::HostOsInfo::withExecutableSuffix("bin/iccarm");
const auto versionDetector = new McuPackageExecutableVersionDetector(
detectionPath,
{"--version"},
"\\bV(\\d+\\.\\d+\\.\\d+)\\.\\d+\\b"
);
auto result = new McuToolChainPackage( auto result = new McuToolChainPackage(
"IAR ARM Compiler", "IAR ARM Compiler",
defaultPath, defaultPath,
Utils::HostOsInfo::withExecutableSuffix("bin/iccarm"), detectionPath,
"IARToolchain", "IARToolchain",
McuToolChainPackage::TypeIAR); McuToolChainPackage::TypeIAR,
versionDetector);
result->setEnvironmentVariableName(envVar); result->setEnvironmentVariableName(envVar);
return result; return result;
} }
@@ -257,14 +281,30 @@ struct McuTargetDescription
QString platformVendor; QString platformVendor;
QVector<int> colorDepths; QVector<int> colorDepths;
QString toolchainId; QString toolchainId;
QVector<QString> toolchainVersions;
QString boardSdkEnvVar; QString boardSdkEnvVar;
QString boardSdkName; QString boardSdkName;
QString boardSdkDefaultPath; QString boardSdkDefaultPath;
QVector<QString> boardSdkVersions;
QString freeRTOSEnvVar; QString freeRTOSEnvVar;
QString freeRTOSBoardSdkSubDir; QString freeRTOSBoardSdkSubDir;
TargetType type; TargetType type;
}; };
static McuPackageVersionDetector* generatePackageVersionDetector(QString envVar)
{
if (envVar.startsWith("EVK"))
return new McuPackageXmlVersionDetector("*_manifest_*.xml", "ksdk", "version", ".*");
if (envVar.startsWith("STM32"))
return new McuPackageXmlVersionDetector("package.xml", "PackDescription", "Release", "\\b(\\d+\\.\\d+\\.\\d+)\\b");
if (envVar.startsWith("RGL"))
return new McuPackageDirectoryVersionDetector("rgl_*_obj_*", "\\d+\\.\\d+\\.\\w+", false);
return nullptr;
}
static McuPackage *createBoardSdkPackage(const McuTargetDescription& desc) static McuPackage *createBoardSdkPackage(const McuTargetDescription& desc)
{ {
const auto generateSdkName = [](const QString& envVar) { const auto generateSdkName = [](const QString& envVar) {
@@ -291,11 +331,14 @@ static McuPackage *createBoardSdkPackage(const McuTargetDescription& desc)
return QDir::homePath(); return QDir::homePath();
}(); }();
const auto versionDetector = generatePackageVersionDetector(desc.boardSdkEnvVar);
auto result = new McuPackage( auto result = new McuPackage(
sdkName, sdkName,
defaultPath, defaultPath,
{}, {},
desc.boardSdkEnvVar); desc.boardSdkEnvVar,
versionDetector);
result->setEnvironmentVariableName(desc.boardSdkEnvVar); result->setEnvironmentVariableName(desc.boardSdkEnvVar);
return result; return result;
} }
@@ -429,7 +472,10 @@ protected:
QVector<McuTarget *> mcuTargets; QVector<McuTarget *> mcuTargets;
McuToolChainPackage *tcPkg = tcPkgs.value(desc.toolchainId); McuToolChainPackage *tcPkg = tcPkgs.value(desc.toolchainId);
if (!tcPkg) if (tcPkg) {
if (QVersionNumber::fromString(desc.qulVersion) >= QVersionNumber({1,8}))
tcPkg->setVersions(desc.toolchainVersions);
} else
tcPkg = createUnsupportedToolChainPackage(); tcPkg = createUnsupportedToolChainPackage();
for (int colorDepth : desc.colorDepths) { for (int colorDepth : desc.colorDepths) {
QVector<McuPackage*> required3rdPartyPkgs; QVector<McuPackage*> required3rdPartyPkgs;
@@ -451,6 +497,7 @@ protected:
boardSdkPkgs.insert(desc.boardSdkEnvVar, boardSdkPkg); boardSdkPkgs.insert(desc.boardSdkEnvVar, boardSdkPkg);
} }
auto boardSdkPkg = boardSdkPkgs.value(desc.boardSdkEnvVar); auto boardSdkPkg = boardSdkPkgs.value(desc.boardSdkEnvVar);
boardSdkPkg->setVersions(desc.boardSdkVersions);
boardSdkDefaultPath = boardSdkPkg->defaultPath(); boardSdkDefaultPath = boardSdkPkg->defaultPath();
required3rdPartyPkgs.append(boardSdkPkg); required3rdPartyPkgs.append(boardSdkPkg);
} }
@@ -537,6 +584,12 @@ static McuTargetDescription parseDescriptionJson(const QByteArray &data)
const QVariantList colorDepths = target.value("colorDepths").toArray().toVariantList(); const QVariantList colorDepths = target.value("colorDepths").toArray().toVariantList();
const auto colorDepthsVector = Utils::transform<QVector<int> >( const auto colorDepthsVector = Utils::transform<QVector<int> >(
colorDepths, [&](const QVariant &colorDepth) { return colorDepth.toInt(); }); colorDepths, [&](const QVariant &colorDepth) { return colorDepth.toInt(); });
const QVariantList toolchainVersions = toolchain.value("versions").toArray().toVariantList();
const auto toolchainVersionsVector = Utils::transform<QVector<QString> >(
toolchainVersions, [&](const QVariant &version) { return version.toString(); });
const QVariantList boardSdkVersions = boardSdk.value("versions").toArray().toVariantList();
const auto boardSdkVersionsVector = Utils::transform<QVector<QString> >(
boardSdkVersions, [&](const QVariant &version) { return version.toString(); });
return { return {
target.value("qulVersion").toString(), target.value("qulVersion").toString(),
@@ -545,9 +598,11 @@ static McuTargetDescription parseDescriptionJson(const QByteArray &data)
target.value("platformVendor").toString(), target.value("platformVendor").toString(),
colorDepthsVector, colorDepthsVector,
toolchain.value("id").toString(), toolchain.value("id").toString(),
toolchainVersionsVector,
boardSdk.value("envVar").toString(), boardSdk.value("envVar").toString(),
boardSdk.value("name").toString(), boardSdk.value("name").toString(),
boardSdk.value("defaultPath").toString(), boardSdk.value("defaultPath").toString(),
boardSdkVersionsVector,
freeRTOS.value("envVar").toString(), freeRTOS.value("envVar").toString(),
freeRTOS.value("boardSdkSubDir").toString(), freeRTOS.value("boardSdkSubDir").toString(),
boardSdk.empty() ? McuTargetDescription::TargetType::Desktop : McuTargetDescription::TargetType::MCU boardSdk.empty() ? McuTargetDescription::TargetType::Desktop : McuTargetDescription::TargetType::MCU

View File

@@ -0,0 +1,135 @@
/****************************************************************************
**
** 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 "mcusupportversiondetection.h"
#include <utils/fileutils.h>
#include <QDir>
#include <QRegularExpression>
#include <QProcess>
namespace McuSupport {
namespace Internal {
McuPackageVersionDetector::McuPackageVersionDetector()
{
}
McuPackageExecutableVersionDetector::McuPackageExecutableVersionDetector(
const QString &detectionPath,
const QStringList &detectionArgs,
const QString &detectionRegExp)
: McuPackageVersionDetector()
, m_detectionPath(detectionPath)
, m_detectionArgs(detectionArgs)
, m_detectionRegExp(detectionRegExp)
{
}
QString McuPackageExecutableVersionDetector::parseVersion(const QString &packagePath) const
{
if (m_detectionPath.isEmpty() || m_detectionRegExp.isEmpty())
return QString();
QString binaryPath = QDir::toNativeSeparators(packagePath + "/" + m_detectionPath);
if (!Utils::FilePath::fromString(binaryPath).exists())
return QString();
const QRegularExpression regExp(m_detectionRegExp);
const int execTimeout = 3000; // usually runs below 1s, but we want to be on the safe side
QProcess binaryProcess;
binaryProcess.start(binaryPath, m_detectionArgs);
if (!binaryProcess.waitForStarted())
return QString();
binaryProcess.waitForFinished(execTimeout);
if (binaryProcess.exitCode() == QProcess::ExitStatus::NormalExit) {
const QString processOutput = QString::fromUtf8(
binaryProcess.readAllStandardOutput().append(
binaryProcess.readAllStandardError()));
const QRegularExpressionMatch match = regExp.match(processOutput);
if (match.hasMatch())
return match.captured(regExp.captureCount());
}
// Fail gracefully: return empty string if execution failed or regexp did not match
return QString();
}
McuPackageXmlVersionDetector::McuPackageXmlVersionDetector(const QString &filePattern,
const QString &versionElement,
const QString &versionAttribute,
const QString &versionRegExp)
: m_filePattern(filePattern),
m_versionElement(versionElement),
m_versionAttribute(versionAttribute),
m_versionRegExp(versionRegExp)
{
}
QString McuPackageXmlVersionDetector::parseVersion(const QString &packagePath) const
{
const QRegularExpression regExp(m_versionRegExp);
const auto files = QDir(packagePath, m_filePattern).entryInfoList();
for (const auto &xmlFile: files) {
QFile sdkXmlFile = QFile(xmlFile.absoluteFilePath());
sdkXmlFile.open(QFile::OpenModeFlag::ReadOnly);
QXmlStreamReader xmlReader(&sdkXmlFile);
while (xmlReader.readNext()) {
if (xmlReader.name() == m_versionElement) {
const QString versionString = xmlReader.attributes().value(m_versionAttribute).toString();
const QRegularExpressionMatch match = regExp.match(versionString);
return match.hasMatch() ? match.captured(regExp.captureCount()) : versionString;
}
}
}
return QString();
}
McuPackageDirectoryVersionDetector::McuPackageDirectoryVersionDetector(const QString &filePattern,
const QString &versionRegExp,
const bool isFile)
: m_filePattern(filePattern),
m_versionRegExp(versionRegExp),
m_isFile(isFile)
{
}
QString McuPackageDirectoryVersionDetector::parseVersion(const QString &packagePath) const
{
const auto files = QDir(packagePath, m_filePattern)
.entryInfoList(m_isFile ? QDir::Filter::Files : QDir::Filter::Dirs);
for (const auto &entry: files) {
const QRegularExpression regExp(m_versionRegExp);
const QRegularExpressionMatch match = regExp.match(entry.fileName());
if (match.hasMatch())
return match.captured(regExp.captureCount());
}
return QString();
}
} // Internal
} // McuSupport

View File

@@ -0,0 +1,84 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#ifndef MCUSUPPORTVERSIONDETECTION_H
#define MCUSUPPORTVERSIONDETECTION_H
#include <QObject>
namespace McuSupport {
namespace Internal {
class McuPackageVersionDetector : public QObject {
Q_OBJECT
public:
McuPackageVersionDetector();
virtual ~McuPackageVersionDetector() = default;
virtual QString parseVersion(const QString &packagePath) const = 0;
};
// Get version from the output of an executable
class McuPackageExecutableVersionDetector : public McuPackageVersionDetector {
public:
McuPackageExecutableVersionDetector(const QString &detectionPath,
const QStringList &detectionArgs,
const QString &detectionRegExp);
virtual QString parseVersion(const QString &packagePath) const;
private:
const QString m_detectionPath;
const QStringList m_detectionArgs;
const QString m_detectionRegExp;
};
// Get version through parsing an XML file
class McuPackageXmlVersionDetector : public McuPackageVersionDetector {
public:
McuPackageXmlVersionDetector(const QString &filePattern,
const QString &elementName,
const QString &versionAttribute,
const QString &versionRegExp);
QString parseVersion(const QString &packagePath) const;
private:
const QString m_filePattern;
const QString m_versionElement;
const QString m_versionAttribute;
const QString m_versionRegExp;
};
// Get version from the filename of a given file/dir in the package directory
class McuPackageDirectoryVersionDetector : public McuPackageVersionDetector {
public:
McuPackageDirectoryVersionDetector(const QString &filePattern, const QString &versionRegExp, const bool isFile);
QString parseVersion(const QString &packagePath) const;
private:
const QString m_filePattern;
const QString m_versionRegExp;
const bool m_isFile;
};
} // Internal
} // McuSupport
#endif // MCUSUPPORTVERSIONDETECTION_H