forked from qt-creator/qt-creator
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:
committed by
christiaan.janssen
parent
3cb6d17d5a
commit
3e08210998
@@ -11,4 +11,5 @@ add_qtc_plugin(McuSupport
|
||||
mcusupportplugin.cpp mcusupportplugin.h
|
||||
mcusupportsdk.cpp mcusupportsdk.h
|
||||
mcusupportrunconfiguration.cpp mcusupportrunconfiguration.h
|
||||
mcusupportversiondetection.cpp mcusupportversiondetection.h
|
||||
)
|
||||
|
@@ -12,7 +12,8 @@ HEADERS += \
|
||||
mcusupportoptionspage.h \
|
||||
mcusupportplugin.h \
|
||||
mcusupportsdk.h \
|
||||
mcusupportrunconfiguration.h
|
||||
mcusupportrunconfiguration.h \
|
||||
mcusupportversiondetection.h
|
||||
|
||||
SOURCES += \
|
||||
mcusupportdevice.cpp \
|
||||
@@ -20,7 +21,8 @@ SOURCES += \
|
||||
mcusupportoptionspage.cpp \
|
||||
mcusupportplugin.cpp \
|
||||
mcusupportsdk.cpp \
|
||||
mcusupportrunconfiguration.cpp
|
||||
mcusupportrunconfiguration.cpp \
|
||||
mcusupportversiondetection.cpp
|
||||
|
||||
RESOURCES += \
|
||||
mcusupport.qrc
|
||||
|
@@ -30,5 +30,7 @@ QtcPlugin {
|
||||
"mcusupportsdk.h",
|
||||
"mcusupportrunconfiguration.cpp",
|
||||
"mcusupportrunconfiguration.h",
|
||||
"mcusupportversiondetection.cpp",
|
||||
"mcusupportversiondetection.h",
|
||||
]
|
||||
}
|
||||
|
@@ -96,11 +96,13 @@ static bool kitNeedsQtVersion()
|
||||
}
|
||||
|
||||
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_defaultPath(packagePathFromSettings(settingsKey, QSettings::SystemScope, defaultPath))
|
||||
, m_detectionPath(detectionPath)
|
||||
, m_settingsKey(settingsKey)
|
||||
, m_versionDetector(versionDetector)
|
||||
{
|
||||
m_path = packagePathFromSettings(settingsKey, QSettings::UserScope, m_defaultPath);
|
||||
m_automaticKitCreation = automaticKitCreationFromSettings(QSettings::UserScope);
|
||||
@@ -182,6 +184,11 @@ McuPackage::Status McuPackage::status() const
|
||||
return m_status;
|
||||
}
|
||||
|
||||
bool McuPackage::validStatus() const
|
||||
{
|
||||
return m_status == McuPackage::ValidPackage || m_status == McuPackage::ValidPackageMismatchedVersion;
|
||||
}
|
||||
|
||||
void McuPackage::setDownloadUrl(const QString &url)
|
||||
{
|
||||
m_downloadUrl = url;
|
||||
@@ -227,6 +234,11 @@ void McuPackage::setRelativePathModifier(const QString &path)
|
||||
m_relativePathModifier = path;
|
||||
}
|
||||
|
||||
void McuPackage::setVersions(const QVector<QString> &versions)
|
||||
{
|
||||
m_versions = versions;
|
||||
}
|
||||
|
||||
bool McuPackage::automaticKitCreationEnabled() const
|
||||
{
|
||||
return m_automaticKitCreation;
|
||||
@@ -249,34 +261,59 @@ void McuPackage::updateStatus()
|
||||
bool validPath = !m_path.isEmpty() && FilePath::fromString(m_path).exists();
|
||||
const FilePath detectionPath = FilePath::fromString(basePath() + "/" + m_detectionPath);
|
||||
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_path.isEmpty() ? EmptyPath : InvalidPath;
|
||||
m_status = validPath ?
|
||||
( validPackage ?
|
||||
(validVersion ? ValidPackage : ValidPackageMismatchedVersion)
|
||||
: ValidPathInvalidPackage )
|
||||
: m_path.isEmpty() ? EmptyPath : InvalidPath;
|
||||
|
||||
emit statusChanged();
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
QString McuPackage::statusText() const
|
||||
{
|
||||
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;
|
||||
switch (m_status) {
|
||||
case ValidPackage:
|
||||
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.")
|
||||
.arg(displayPackagePath, displayDetectionPath);
|
||||
.arg(displayPackagePath, displayDetectedPath);
|
||||
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:
|
||||
response = tr("Path %1 exists, but does not contain %2.")
|
||||
.arg(displayPackagePath, displayDetectionPath);
|
||||
.arg(displayPackagePath, displayRequiredPath);
|
||||
break;
|
||||
case InvalidPath:
|
||||
response = tr("Path %1 does not exist.").arg(displayPackagePath);
|
||||
@@ -285,7 +322,7 @@ QString McuPackage::statusText() const
|
||||
response = m_detectionPath.isEmpty()
|
||||
? tr("Path is empty.")
|
||||
: tr("Path is empty, %1 not found.")
|
||||
.arg(displayDetectionPath);
|
||||
.arg(displayRequiredPath);
|
||||
break;
|
||||
}
|
||||
return response;
|
||||
@@ -295,8 +332,9 @@ McuToolChainPackage::McuToolChainPackage(const QString &label,
|
||||
const QString &defaultPath,
|
||||
const QString &detectionPath,
|
||||
const QString &settingsKey,
|
||||
McuToolChainPackage::Type type)
|
||||
: McuPackage(label, defaultPath, detectionPath, settingsKey)
|
||||
McuToolChainPackage::Type type,
|
||||
const McuPackageVersionDetector *versionDetector)
|
||||
: McuPackage(label, defaultPath, detectionPath, settingsKey, versionDetector)
|
||||
, m_type(type)
|
||||
{
|
||||
}
|
||||
@@ -484,9 +522,9 @@ McuTarget::Platform McuTarget::platform() const
|
||||
|
||||
bool McuTarget::isValid() const
|
||||
{
|
||||
return !Utils::anyOf(packages(), [](McuPackage *package) {
|
||||
return Utils::allOf(packages(), [](McuPackage *package) {
|
||||
package->updateStatus();
|
||||
return package->status() != McuPackage::ValidPackage;
|
||||
return package->validStatus();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -494,12 +532,18 @@ void McuTarget::printPackageProblems() const
|
||||
{
|
||||
for (auto package: packages()) {
|
||||
package->updateStatus();
|
||||
if (package->status() != McuPackage::ValidPackage)
|
||||
printMessage(QString("Error creating kit for target %1, package %2: %3").arg(
|
||||
if (!package->validStatus())
|
||||
printMessage(tr("Error creating kit for target %1, package %2: %3").arg(
|
||||
McuSupportOptions::kitName(this),
|
||||
package->label(),
|
||||
package->statusText()),
|
||||
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();
|
||||
qtForMCUsSdkPackage->updateStatus();
|
||||
if (qtForMCUsSdkPackage->status() == McuPackage::Status::ValidPackage)
|
||||
if (qtForMCUsSdkPackage->validStatus())
|
||||
Sdk::targetsAndPackages(dir, &packages, &mcuTargets);
|
||||
for (auto package : qAsConst(packages))
|
||||
connect(package, &McuPackage::changed, this, &McuSupportOptions::changed);
|
||||
@@ -858,7 +902,7 @@ void McuSupportOptions::createAutomaticKits()
|
||||
const auto createKits = [qtForMCUsPackage]() {
|
||||
if (qtForMCUsPackage->automaticKitCreationEnabled()) {
|
||||
qtForMCUsPackage->updateStatus();
|
||||
if (qtForMCUsPackage->status() != McuPackage::ValidPackage) {
|
||||
if (!qtForMCUsPackage->validStatus()) {
|
||||
switch (qtForMCUsPackage->status()) {
|
||||
case McuPackage::ValidPathInvalidPackage: {
|
||||
const QString displayPath = FilePath::fromString(qtForMCUsPackage->detectionPath())
|
||||
@@ -900,8 +944,7 @@ void McuSupportOptions::createAutomaticKits()
|
||||
if (existingKits(target).isEmpty()) {
|
||||
if (target->isValid())
|
||||
newKit(target, qtForMCUsPackage);
|
||||
else
|
||||
target->printPackageProblems();
|
||||
target->printPackageProblems();
|
||||
}
|
||||
|
||||
qDeleteAll(packages);
|
||||
|
@@ -25,6 +25,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mcusupportversiondetection.h"
|
||||
|
||||
#include <utils/id.h>
|
||||
|
||||
#include <QObject>
|
||||
@@ -58,11 +60,13 @@ public:
|
||||
EmptyPath,
|
||||
InvalidPath,
|
||||
ValidPathInvalidPackage,
|
||||
ValidPackageMismatchedVersion,
|
||||
ValidPackage
|
||||
};
|
||||
|
||||
McuPackage(const QString &label, const QString &defaultPath, const QString &detectionPath,
|
||||
const QString &settingsKey);
|
||||
McuPackage(const QString &label, const QString &defaultPath,
|
||||
const QString &detectionPath, const QString &settingsKey,
|
||||
const McuPackageVersionDetector *versionDetector = nullptr);
|
||||
virtual ~McuPackage() = default;
|
||||
|
||||
QString basePath() const;
|
||||
@@ -74,6 +78,7 @@ public:
|
||||
void updateStatus();
|
||||
|
||||
Status status() const;
|
||||
bool validStatus() const;
|
||||
void setDownloadUrl(const QString &url);
|
||||
void setEnvironmentVariableName(const QString &name);
|
||||
void setAddToPath(bool addToPath);
|
||||
@@ -81,6 +86,7 @@ public:
|
||||
void writeGeneralSettings() const;
|
||||
void writeToSettings() const;
|
||||
void setRelativePathModifier(const QString &path);
|
||||
void setVersions(const QVector<QString> &versions);
|
||||
|
||||
bool automaticKitCreationEnabled() const;
|
||||
void setAutomaticKitCreationEnabled(const bool enabled);
|
||||
@@ -105,9 +111,12 @@ private:
|
||||
const QString m_defaultPath;
|
||||
const QString m_detectionPath;
|
||||
const QString m_settingsKey;
|
||||
const McuPackageVersionDetector *m_versionDetector;
|
||||
|
||||
QString m_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_environmentVariableName;
|
||||
bool m_addToPath = false;
|
||||
@@ -133,7 +142,9 @@ public:
|
||||
const QString &defaultPath,
|
||||
const QString &detectionPath,
|
||||
const QString &settingsKey,
|
||||
Type type);
|
||||
Type type,
|
||||
const McuPackageVersionDetector *versionDetector = nullptr
|
||||
);
|
||||
|
||||
Type type() const;
|
||||
bool isDesktopToolchain() const;
|
||||
|
@@ -185,7 +185,7 @@ void McuSupportOptionsWidget::updateStatus()
|
||||
{
|
||||
m_qtForMCUsSdkGroupBox->setVisible(cMakeAvailable);
|
||||
const bool valid = cMakeAvailable &&
|
||||
m_options.qtForMCUsSdkPackage->status() == McuPackage::ValidPackage;
|
||||
m_options.qtForMCUsSdkPackage->validStatus();
|
||||
const bool ready = valid && mcuTarget;
|
||||
m_mcuTargetsGroupBox->setVisible(ready);
|
||||
m_packagesGroupBox->setVisible(ready && !mcuTarget->packages().isEmpty());
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include "mcusupportconstants.h"
|
||||
#include "mcusupportoptions.h"
|
||||
#include "mcusupportsdk.h"
|
||||
#include "mcusupportversiondetection.h"
|
||||
|
||||
#include <baremetal/baremetalconstants.h>
|
||||
#include <projectexplorer/toolchain.h>
|
||||
@@ -107,12 +108,20 @@ static McuToolChainPackage *createArmGccPackage()
|
||||
if (defaultPath.isEmpty())
|
||||
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(
|
||||
McuPackage::tr("GNU Arm Embedded Toolchain"),
|
||||
defaultPath,
|
||||
Utils::HostOsInfo::withExecutableSuffix("bin/arm-none-eabi-g++"),
|
||||
detectionPath,
|
||||
"GNUArmEmbeddedToolchain",
|
||||
McuToolChainPackage::TypeArmGcc);
|
||||
McuToolChainPackage::TypeArmGcc,
|
||||
versionDetector);
|
||||
result->setEnvironmentVariableName(envVar);
|
||||
return result;
|
||||
}
|
||||
@@ -124,12 +133,19 @@ static McuToolChainPackage *createGhsToolchainPackage()
|
||||
const QString defaultPath =
|
||||
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(
|
||||
"Green Hills Compiler",
|
||||
defaultPath,
|
||||
Utils::HostOsInfo::withExecutableSuffix("ccv850"),
|
||||
"GHSToolchain",
|
||||
McuToolChainPackage::TypeGHS);
|
||||
McuToolChainPackage::TypeGHS,
|
||||
versionDetector);
|
||||
result->setEnvironmentVariableName(envVar);
|
||||
return result;
|
||||
}
|
||||
@@ -154,12 +170,20 @@ static McuToolChainPackage *createIarToolChainPackage()
|
||||
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(
|
||||
"IAR ARM Compiler",
|
||||
defaultPath,
|
||||
Utils::HostOsInfo::withExecutableSuffix("bin/iccarm"),
|
||||
detectionPath,
|
||||
"IARToolchain",
|
||||
McuToolChainPackage::TypeIAR);
|
||||
McuToolChainPackage::TypeIAR,
|
||||
versionDetector);
|
||||
result->setEnvironmentVariableName(envVar);
|
||||
return result;
|
||||
}
|
||||
@@ -257,14 +281,30 @@ struct McuTargetDescription
|
||||
QString platformVendor;
|
||||
QVector<int> colorDepths;
|
||||
QString toolchainId;
|
||||
QVector<QString> toolchainVersions;
|
||||
QString boardSdkEnvVar;
|
||||
QString boardSdkName;
|
||||
QString boardSdkDefaultPath;
|
||||
QVector<QString> boardSdkVersions;
|
||||
QString freeRTOSEnvVar;
|
||||
QString freeRTOSBoardSdkSubDir;
|
||||
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)
|
||||
{
|
||||
const auto generateSdkName = [](const QString& envVar) {
|
||||
@@ -291,11 +331,14 @@ static McuPackage *createBoardSdkPackage(const McuTargetDescription& desc)
|
||||
return QDir::homePath();
|
||||
}();
|
||||
|
||||
const auto versionDetector = generatePackageVersionDetector(desc.boardSdkEnvVar);
|
||||
|
||||
auto result = new McuPackage(
|
||||
sdkName,
|
||||
defaultPath,
|
||||
{},
|
||||
desc.boardSdkEnvVar);
|
||||
desc.boardSdkEnvVar,
|
||||
versionDetector);
|
||||
result->setEnvironmentVariableName(desc.boardSdkEnvVar);
|
||||
return result;
|
||||
}
|
||||
@@ -429,7 +472,10 @@ protected:
|
||||
|
||||
QVector<McuTarget *> mcuTargets;
|
||||
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();
|
||||
for (int colorDepth : desc.colorDepths) {
|
||||
QVector<McuPackage*> required3rdPartyPkgs;
|
||||
@@ -451,6 +497,7 @@ protected:
|
||||
boardSdkPkgs.insert(desc.boardSdkEnvVar, boardSdkPkg);
|
||||
}
|
||||
auto boardSdkPkg = boardSdkPkgs.value(desc.boardSdkEnvVar);
|
||||
boardSdkPkg->setVersions(desc.boardSdkVersions);
|
||||
boardSdkDefaultPath = boardSdkPkg->defaultPath();
|
||||
required3rdPartyPkgs.append(boardSdkPkg);
|
||||
}
|
||||
@@ -537,6 +584,12 @@ static McuTargetDescription parseDescriptionJson(const QByteArray &data)
|
||||
const QVariantList colorDepths = target.value("colorDepths").toArray().toVariantList();
|
||||
const auto colorDepthsVector = Utils::transform<QVector<int> >(
|
||||
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 {
|
||||
target.value("qulVersion").toString(),
|
||||
@@ -545,9 +598,11 @@ static McuTargetDescription parseDescriptionJson(const QByteArray &data)
|
||||
target.value("platformVendor").toString(),
|
||||
colorDepthsVector,
|
||||
toolchain.value("id").toString(),
|
||||
toolchainVersionsVector,
|
||||
boardSdk.value("envVar").toString(),
|
||||
boardSdk.value("name").toString(),
|
||||
boardSdk.value("defaultPath").toString(),
|
||||
boardSdkVersionsVector,
|
||||
freeRTOS.value("envVar").toString(),
|
||||
freeRTOS.value("boardSdkSubDir").toString(),
|
||||
boardSdk.empty() ? McuTargetDescription::TargetType::Desktop : McuTargetDescription::TargetType::MCU
|
||||
|
135
src/plugins/mcusupport/mcusupportversiondetection.cpp
Normal file
135
src/plugins/mcusupport/mcusupportversiondetection.cpp
Normal 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
|
84
src/plugins/mcusupport/mcusupportversiondetection.h
Normal file
84
src/plugins/mcusupport/mcusupportversiondetection.h
Normal 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
|
Reference in New Issue
Block a user