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
|
mcusupportplugin.cpp mcusupportplugin.h
|
||||||
mcusupportsdk.cpp mcusupportsdk.h
|
mcusupportsdk.cpp mcusupportsdk.h
|
||||||
mcusupportrunconfiguration.cpp mcusupportrunconfiguration.h
|
mcusupportrunconfiguration.cpp mcusupportrunconfiguration.h
|
||||||
|
mcusupportversiondetection.cpp mcusupportversiondetection.h
|
||||||
)
|
)
|
||||||
|
@@ -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
|
||||||
|
@@ -30,5 +30,7 @@ QtcPlugin {
|
|||||||
"mcusupportsdk.h",
|
"mcusupportsdk.h",
|
||||||
"mcusupportrunconfiguration.cpp",
|
"mcusupportrunconfiguration.cpp",
|
||||||
"mcusupportrunconfiguration.h",
|
"mcusupportrunconfiguration.h",
|
||||||
|
"mcusupportversiondetection.cpp",
|
||||||
|
"mcusupportversiondetection.h",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
|
@@ -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;
|
||||||
|
@@ -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());
|
||||||
|
@@ -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
|
||||||
|
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