forked from qt-creator/qt-creator
McuSupport: Split up McuSupportOptionsPage
Move the non-OptionsPage code into a new file for comprehensibility. Change-Id: I306ae669ec9fdd941f777426420859ee2eb89e95 Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
@@ -6,6 +6,7 @@ add_qtc_plugin(McuSupport
|
|||||||
mcusupport_global.h
|
mcusupport_global.h
|
||||||
mcusupportconstants.h
|
mcusupportconstants.h
|
||||||
mcusupportdevice.cpp mcusupportdevice.h
|
mcusupportdevice.cpp mcusupportdevice.h
|
||||||
|
mcusupportoptions.cpp mcusupportoptions.h
|
||||||
mcusupportoptionspage.cpp mcusupportoptionspage.h
|
mcusupportoptionspage.cpp mcusupportoptionspage.h
|
||||||
mcusupportplugin.cpp mcusupportplugin.h
|
mcusupportplugin.cpp mcusupportplugin.h
|
||||||
mcusupportrunconfiguration.cpp mcusupportrunconfiguration.h
|
mcusupportrunconfiguration.cpp mcusupportrunconfiguration.h
|
||||||
|
@@ -8,12 +8,14 @@ HEADERS += \
|
|||||||
mcusupport_global.h \
|
mcusupport_global.h \
|
||||||
mcusupportconstants.h \
|
mcusupportconstants.h \
|
||||||
mcusupportdevice.h \
|
mcusupportdevice.h \
|
||||||
|
mcusupportoptions.h \
|
||||||
mcusupportoptionspage.h \
|
mcusupportoptionspage.h \
|
||||||
mcusupportplugin.h \
|
mcusupportplugin.h \
|
||||||
mcusupportrunconfiguration.h
|
mcusupportrunconfiguration.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
mcusupportdevice.cpp \
|
mcusupportdevice.cpp \
|
||||||
|
mcusupportoptions.cpp \
|
||||||
mcusupportoptionspage.cpp \
|
mcusupportoptionspage.cpp \
|
||||||
mcusupportplugin.cpp \
|
mcusupportplugin.cpp \
|
||||||
mcusupportrunconfiguration.cpp
|
mcusupportrunconfiguration.cpp
|
||||||
|
@@ -18,6 +18,8 @@ QtcPlugin {
|
|||||||
"mcusupportconstants.h",
|
"mcusupportconstants.h",
|
||||||
"mcusupportdevice.cpp",
|
"mcusupportdevice.cpp",
|
||||||
"mcusupportdevice.h",
|
"mcusupportdevice.h",
|
||||||
|
"mcusupportoptions.cpp",
|
||||||
|
"mcusupportoptions.h",
|
||||||
"mcusupportoptionspage.cpp",
|
"mcusupportoptionspage.cpp",
|
||||||
"mcusupportoptionspage.h",
|
"mcusupportoptionspage.h",
|
||||||
"mcusupportplugin.cpp",
|
"mcusupportplugin.cpp",
|
||||||
|
503
src/plugins/mcusupport/mcusupportoptions.cpp
Normal file
503
src/plugins/mcusupport/mcusupportoptions.cpp
Normal file
@@ -0,0 +1,503 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 BlackBerry Limited. All rights reserved.
|
||||||
|
** Contact: BlackBerry (qt@blackberry.com)
|
||||||
|
**
|
||||||
|
** 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 "mcusupportconstants.h"
|
||||||
|
#include "mcusupportoptions.h"
|
||||||
|
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
#include <cmakeprojectmanager/cmakekitinformation.h>
|
||||||
|
#include <debugger/debuggeritem.h>
|
||||||
|
#include <debugger/debuggeritemmanager.h>
|
||||||
|
#include <debugger/debuggerkitinformation.h>
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
#include <projectexplorer/toolchain.h>
|
||||||
|
#include <projectexplorer/toolchainmanager.h>
|
||||||
|
#include <projectexplorer/kitmanager.h>
|
||||||
|
#include <projectexplorer/kitinformation.h>
|
||||||
|
#include <projectexplorer/devicesupport/devicemanager.h>
|
||||||
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
#include <utils/pathchooser.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QToolButton>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
namespace McuSupport {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
PackageOptions::PackageOptions(const QString &label, const QString &defaultPath,
|
||||||
|
const QString &detectionPath, const QString &settingsKey)
|
||||||
|
: m_label(label)
|
||||||
|
, m_defaultPath(defaultPath)
|
||||||
|
, m_detectionPath(detectionPath)
|
||||||
|
, m_settingsKey(settingsKey)
|
||||||
|
{
|
||||||
|
QSettings *s = Core::ICore::settings();
|
||||||
|
s->beginGroup(Constants::SETTINGS_GROUP);
|
||||||
|
m_path = s->value(QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey,
|
||||||
|
m_defaultPath).toString();
|
||||||
|
s->endGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PackageOptions::path() const
|
||||||
|
{
|
||||||
|
return QFileInfo(m_fileChooser->path() + m_relativePathModifier).absoluteFilePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PackageOptions::label() const
|
||||||
|
{
|
||||||
|
return m_label;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PackageOptions::detectionPath() const
|
||||||
|
{
|
||||||
|
return m_detectionPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *PackageOptions::widget()
|
||||||
|
{
|
||||||
|
if (m_widget)
|
||||||
|
return m_widget;
|
||||||
|
|
||||||
|
m_widget = new QWidget;
|
||||||
|
m_fileChooser = new Utils::PathChooser;
|
||||||
|
QObject::connect(m_fileChooser, &Utils::PathChooser::pathChanged,
|
||||||
|
[this](){
|
||||||
|
updateStatus();
|
||||||
|
emit changed();
|
||||||
|
});
|
||||||
|
|
||||||
|
auto layout = new QGridLayout(m_widget);
|
||||||
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
m_statusIcon = new QLabel;
|
||||||
|
m_statusIcon->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::MinimumExpanding);
|
||||||
|
m_statusIcon->setAlignment(Qt::AlignTop);
|
||||||
|
m_statusLabel = new QLabel;
|
||||||
|
m_statusLabel->setWordWrap(true);
|
||||||
|
m_statusLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
|
||||||
|
|
||||||
|
if (!m_downloadUrl.isEmpty()) {
|
||||||
|
auto downLoadButton = new QToolButton;
|
||||||
|
downLoadButton->setIcon(Utils::Icons::DOWNLOAD.icon());
|
||||||
|
downLoadButton->setToolTip(tr("Download from \"%1\"").arg(m_downloadUrl));
|
||||||
|
QObject::connect(downLoadButton, &QToolButton::pressed, [this]{
|
||||||
|
QDesktopServices::openUrl(m_downloadUrl);
|
||||||
|
});
|
||||||
|
layout->addWidget(downLoadButton, 0, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
layout->addWidget(m_fileChooser, 0, 0, 1, 2);
|
||||||
|
layout->addWidget(m_statusIcon, 1, 0);
|
||||||
|
layout->addWidget(m_statusLabel, 1, 1, 1, -1);
|
||||||
|
|
||||||
|
m_fileChooser->setPath(m_path); // Triggers updateStatus() call
|
||||||
|
return m_widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
PackageOptions::Status PackageOptions::status() const
|
||||||
|
{
|
||||||
|
return m_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PackageOptions::setDownloadUrl(const QString &url)
|
||||||
|
{
|
||||||
|
m_downloadUrl = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PackageOptions::setEnvironmentVariableName(const QString &name)
|
||||||
|
{
|
||||||
|
m_environmentVariableName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PackageOptions::environmentVariableName() const
|
||||||
|
{
|
||||||
|
return m_environmentVariableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PackageOptions::setAddToPath(bool addToPath)
|
||||||
|
{
|
||||||
|
m_addToPath = addToPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PackageOptions::addToPath() const
|
||||||
|
{
|
||||||
|
return m_addToPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PackageOptions::writeToSettings() const
|
||||||
|
{
|
||||||
|
if (m_path.compare(m_defaultPath) == 0)
|
||||||
|
return;
|
||||||
|
QSettings *s = Core::ICore::settings();
|
||||||
|
s->beginGroup(Constants::SETTINGS_GROUP);
|
||||||
|
s->setValue(QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey, m_path);
|
||||||
|
s->endGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PackageOptions::setRelativePathModifier(const QString &path)
|
||||||
|
{
|
||||||
|
m_relativePathModifier = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PackageOptions::updateStatus()
|
||||||
|
{
|
||||||
|
m_path = m_fileChooser->rawPath();
|
||||||
|
const bool validPath = m_fileChooser->isValid();
|
||||||
|
const Utils::FilePath detectionPath = Utils::FilePath::fromString(
|
||||||
|
m_fileChooser->path() + "/" + m_detectionPath);
|
||||||
|
const QString displayDetectionPath = Utils::FilePath::fromString(m_detectionPath).toUserOutput();
|
||||||
|
const bool validPackage = detectionPath.exists();
|
||||||
|
|
||||||
|
m_status = validPath ? (validPackage ? ValidPackage : ValidPathInvalidPackage) : InvalidPath;
|
||||||
|
|
||||||
|
static const QPixmap okIcon = Utils::Icons::OK.pixmap();
|
||||||
|
static const QPixmap notOkIcon = Utils::Icons::BROKEN.pixmap();
|
||||||
|
m_statusIcon->setPixmap(m_status == ValidPackage ? okIcon : notOkIcon);
|
||||||
|
|
||||||
|
QString statusText;
|
||||||
|
switch (m_status) {
|
||||||
|
case ValidPackage:
|
||||||
|
statusText = tr("Path is valid, \"%1\" was found.").arg(displayDetectionPath);
|
||||||
|
break;
|
||||||
|
case ValidPathInvalidPackage:
|
||||||
|
statusText = tr("Path exists, but does not contain \"%1\".").arg(displayDetectionPath);
|
||||||
|
break;
|
||||||
|
case InvalidPath:
|
||||||
|
statusText = tr("Path does not exist.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_statusLabel->setText(statusText);
|
||||||
|
}
|
||||||
|
|
||||||
|
BoardOptions::BoardOptions(const QString &model, const QString &toolChainFileName,
|
||||||
|
const QVector<PackageOptions*> &packages)
|
||||||
|
: m_model(model)
|
||||||
|
, m_toolChainFile(toolChainFileName)
|
||||||
|
, m_packages(packages)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString BoardOptions::model() const
|
||||||
|
{
|
||||||
|
return m_model;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString BoardOptions::toolChainFile() const
|
||||||
|
{
|
||||||
|
return m_toolChainFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<PackageOptions *> BoardOptions::packages() const
|
||||||
|
{
|
||||||
|
return m_packages;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PackageOptions *createQulPackage()
|
||||||
|
{
|
||||||
|
auto result = new PackageOptions(
|
||||||
|
PackageOptions::tr("Qt MCU SDK"),
|
||||||
|
QDir::homePath(),
|
||||||
|
Utils::HostOsInfo::withExecutableSuffix("bin/qmltocpp"),
|
||||||
|
"qulSdk");
|
||||||
|
result->setEnvironmentVariableName("Qul_DIR");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PackageOptions *createArmGccPackage()
|
||||||
|
{
|
||||||
|
const QString defaultPath =
|
||||||
|
Utils::HostOsInfo::isWindowsHost() ?
|
||||||
|
QDir::fromNativeSeparators(qEnvironmentVariable("ProgramFiles(x86)"))
|
||||||
|
+ "/GNU Tools ARM Embedded/"
|
||||||
|
: QString("%{Env:ARMGCC_DIR}");
|
||||||
|
auto result = new PackageOptions(
|
||||||
|
PackageOptions::tr("GNU Arm Embedded Toolchain"),
|
||||||
|
defaultPath,
|
||||||
|
Utils::HostOsInfo::withExecutableSuffix("bin/arm-none-eabi-g++"),
|
||||||
|
Constants::SETTINGS_KEY_PACKAGE_ARMGCC);
|
||||||
|
result->setDownloadUrl(
|
||||||
|
"https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads");
|
||||||
|
result->setEnvironmentVariableName("ARMGCC_DIR");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PackageOptions *createStm32CubeFwF7SdkPackage()
|
||||||
|
{
|
||||||
|
auto result = new PackageOptions(
|
||||||
|
PackageOptions::tr("STM32Cube SDK"),
|
||||||
|
"%{Env:STM32Cube_FW_F7_SDK_PATH}",
|
||||||
|
"Drivers/STM32F7xx_HAL_Driver",
|
||||||
|
"stm32CubeFwF7Sdk");
|
||||||
|
result->setDownloadUrl(
|
||||||
|
"https://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32cube-mcu-packages/stm32cubef7.html");
|
||||||
|
result->setEnvironmentVariableName("STM32Cube_FW_F7_SDK_PATH");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PackageOptions *createStm32CubeProgrammerPackage()
|
||||||
|
{
|
||||||
|
const QString defaultPath =
|
||||||
|
Utils::HostOsInfo::isWindowsHost() ?
|
||||||
|
QDir::fromNativeSeparators(qEnvironmentVariable("ProgramFiles"))
|
||||||
|
+ "/STMicroelectronics/STM32Cube/STM32CubeProgrammer/"
|
||||||
|
: QDir::homePath();
|
||||||
|
auto result = new PackageOptions(
|
||||||
|
PackageOptions::tr("STM32CubeProgrammer"),
|
||||||
|
defaultPath,
|
||||||
|
QLatin1String(Utils::HostOsInfo::isWindowsHost() ? "/bin/STM32_Programmer_CLI.exe"
|
||||||
|
: "/bin/STM32_Programmer.sh"),
|
||||||
|
"stm32CubeProgrammer");
|
||||||
|
result->setRelativePathModifier("/bin");
|
||||||
|
result->setDownloadUrl(
|
||||||
|
"https://www.st.com/en/development-tools/stm32cubeprog.html");
|
||||||
|
result->setAddToPath(true);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PackageOptions *createEvkbImxrt1050SdkPackage()
|
||||||
|
{
|
||||||
|
auto result = new PackageOptions(
|
||||||
|
PackageOptions::tr("NXP EVKB-IMXRT1050 SDK"),
|
||||||
|
"%{Env:EVKB_IMXRT1050_SDK_PATH}",
|
||||||
|
"EVKB-IMXRT1050_manifest_v3_5.xml",
|
||||||
|
"evkbImxrt1050Sdk");
|
||||||
|
result->setDownloadUrl("https://mcuxpresso.nxp.com/en/welcome");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PackageOptions *createSeggerJLinkPackage()
|
||||||
|
{
|
||||||
|
const QString defaultPath =
|
||||||
|
Utils::HostOsInfo::isWindowsHost() ?
|
||||||
|
QDir::fromNativeSeparators(qEnvironmentVariable("ProgramFiles")) + "/SEGGER/JLink"
|
||||||
|
: QString("%{Env:SEGGER_JLINK_SOFTWARE_AND_DOCUMENTATION_PATH}");
|
||||||
|
auto result = new PackageOptions(
|
||||||
|
PackageOptions::tr("SEGGER JLink"),
|
||||||
|
defaultPath,
|
||||||
|
Utils::HostOsInfo::withExecutableSuffix("JLink"),
|
||||||
|
"seggerJLink");
|
||||||
|
result->setDownloadUrl("https://www.segger.com/downloads/jlink");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
McuSupportOptions::McuSupportOptions(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
PackageOptions* qulPackage = createQulPackage();
|
||||||
|
PackageOptions* armGccPackage = createArmGccPackage();
|
||||||
|
PackageOptions* stm32CubeFwF7SdkPackage = createStm32CubeFwF7SdkPackage();
|
||||||
|
PackageOptions* stm32CubeProgrammerPackage = createStm32CubeProgrammerPackage();
|
||||||
|
PackageOptions* evkbImxrt1050SdkPackage = createEvkbImxrt1050SdkPackage();
|
||||||
|
PackageOptions* seggerJLinkPackage = createSeggerJLinkPackage();
|
||||||
|
|
||||||
|
toolchainPackage = armGccPackage;
|
||||||
|
|
||||||
|
|
||||||
|
auto stmPackages = {armGccPackage, stm32CubeFwF7SdkPackage, stm32CubeProgrammerPackage,
|
||||||
|
qulPackage};
|
||||||
|
auto nxpPackages = {armGccPackage, evkbImxrt1050SdkPackage, seggerJLinkPackage,
|
||||||
|
qulPackage};
|
||||||
|
packages = {armGccPackage, stm32CubeFwF7SdkPackage, stm32CubeProgrammerPackage,
|
||||||
|
evkbImxrt1050SdkPackage, seggerJLinkPackage, qulPackage};
|
||||||
|
|
||||||
|
boards.append(new BoardOptions(
|
||||||
|
"stm32f7508", "CMake/stm32f7508-discovery.cmake", stmPackages));
|
||||||
|
boards.append(new BoardOptions(
|
||||||
|
"stm32f769i", "CMake/stm32f769i-discovery.cmake", stmPackages));
|
||||||
|
boards.append(new BoardOptions(
|
||||||
|
"evkbimxrt1050", "CMake/evkbimxrt1050-toolchain.cmake", nxpPackages));
|
||||||
|
|
||||||
|
for (auto package : packages)
|
||||||
|
connect(package, &PackageOptions::changed, [this](){
|
||||||
|
emit changed();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
McuSupportOptions::~McuSupportOptions()
|
||||||
|
{
|
||||||
|
qDeleteAll(packages);
|
||||||
|
packages.clear();
|
||||||
|
qDeleteAll(boards);
|
||||||
|
boards.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<BoardOptions *> McuSupportOptions::validBoards() const
|
||||||
|
{
|
||||||
|
return Utils::filtered(boards, [](BoardOptions *board){
|
||||||
|
return !Utils::anyOf(board->packages(), [](PackageOptions *package){
|
||||||
|
return package->status() != PackageOptions::ValidPackage;});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static ProjectExplorer::ToolChain* armGccToolchain(const Utils::FilePath &path, Core::Id language)
|
||||||
|
{
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
ToolChain *toolChain = ToolChainManager::toolChain([&path, language](const ToolChain *t){
|
||||||
|
return t->compilerCommand() == path && t->language() == language;
|
||||||
|
});
|
||||||
|
if (!toolChain) {
|
||||||
|
ToolChainFactory *gccFactory =
|
||||||
|
Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), [](ToolChainFactory *f){
|
||||||
|
return f->supportedToolChainType() == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID;
|
||||||
|
});
|
||||||
|
if (gccFactory) {
|
||||||
|
const QList<ToolChain*> detected = gccFactory->detectForImport({path, language});
|
||||||
|
if (!detected.isEmpty()) {
|
||||||
|
toolChain = detected.first();
|
||||||
|
toolChain->setDetection(ToolChain::ManualDetection);
|
||||||
|
toolChain->setDisplayName("Arm GCC");
|
||||||
|
ToolChainManager::registerToolChain(toolChain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return toolChain;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setKitProperties(ProjectExplorer::Kit *k, const BoardOptions* board)
|
||||||
|
{
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
k->setUnexpandedDisplayName("Qt MCU - " + board->model());
|
||||||
|
k->setValue(Constants::KIT_BOARD_MODEL_KEY, board->model());
|
||||||
|
k->setAutoDetected(false);
|
||||||
|
k->setIrrelevantAspects({
|
||||||
|
SysRootKitAspect::id(),
|
||||||
|
"QtSupport.QtInformation" // QtKitAspect::id()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setKitToolchains(ProjectExplorer::Kit *k, const QString &armGccPath)
|
||||||
|
{
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
const QString compileNameScheme = Utils::HostOsInfo::withExecutableSuffix(
|
||||||
|
armGccPath + "/bin/arm-none-eabi-%1");
|
||||||
|
ToolChain *cTc = armGccToolchain(
|
||||||
|
Utils::FilePath::fromUserInput(compileNameScheme.arg("gcc")),
|
||||||
|
ProjectExplorer::Constants::C_LANGUAGE_ID);
|
||||||
|
ToolChain *cxxTc = armGccToolchain(
|
||||||
|
Utils::FilePath::fromUserInput(compileNameScheme.arg("g++")),
|
||||||
|
ProjectExplorer::Constants::CXX_LANGUAGE_ID);
|
||||||
|
ToolChainKitAspect::setToolChain(k, cTc);
|
||||||
|
ToolChainKitAspect::setToolChain(k, cxxTc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setKitDebugger(ProjectExplorer::Kit *k, const QString &armGccPath)
|
||||||
|
{
|
||||||
|
using namespace Debugger;
|
||||||
|
|
||||||
|
const Utils::FilePath command = Utils::FilePath::fromUserInput(
|
||||||
|
Utils::HostOsInfo::withExecutableSuffix(armGccPath + "/bin/arm-none-eabi-gdb-py"));
|
||||||
|
const DebuggerItem *debugger = DebuggerItemManager::findByCommand(command);
|
||||||
|
QVariant debuggerId;
|
||||||
|
if (!debugger) {
|
||||||
|
DebuggerItem newDebugger;
|
||||||
|
newDebugger.setCommand(command);
|
||||||
|
newDebugger.setUnexpandedDisplayName(
|
||||||
|
PackageOptions::tr("Arm GDB at %1").arg(command.toUserOutput()));
|
||||||
|
debuggerId = DebuggerItemManager::registerDebugger(newDebugger);
|
||||||
|
} else {
|
||||||
|
debuggerId = debugger->id();
|
||||||
|
}
|
||||||
|
|
||||||
|
DebuggerKitAspect::setDebugger(k, debuggerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setKitDevice(ProjectExplorer::Kit *k)
|
||||||
|
{
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DEVICE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setKitEnvironment(ProjectExplorer::Kit *k, const BoardOptions* board)
|
||||||
|
{
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
Utils::EnvironmentItems changes;
|
||||||
|
QStringList pathAdditions;
|
||||||
|
for (auto package : board->packages()) {
|
||||||
|
if (package->addToPath())
|
||||||
|
pathAdditions.append(QDir::toNativeSeparators(package->path()));
|
||||||
|
if (!package->environmentVariableName().isEmpty())
|
||||||
|
changes.append({package->environmentVariableName(),
|
||||||
|
QDir::toNativeSeparators(package->path())});
|
||||||
|
}
|
||||||
|
if (!pathAdditions.isEmpty()) {
|
||||||
|
pathAdditions.append("${Path}");
|
||||||
|
changes.append({"Path", pathAdditions.join(Utils::HostOsInfo::pathListSeparator())});
|
||||||
|
}
|
||||||
|
EnvironmentKitAspect::setEnvironmentChanges(k, changes);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setKitCMakeOptions(ProjectExplorer::Kit *k, const BoardOptions* board)
|
||||||
|
{
|
||||||
|
using namespace CMakeProjectManager;
|
||||||
|
|
||||||
|
CMakeConfig config = CMakeConfigurationKitAspect::configuration(k);
|
||||||
|
config.append(CMakeConfigItem("CMAKE_TOOLCHAIN_FILE",
|
||||||
|
("%{CurrentBuild:Env:Qul_DIR}/" +
|
||||||
|
board->toolChainFile()).toUtf8()));
|
||||||
|
CMakeConfigurationKitAspect::setConfiguration(k, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectExplorer::Kit *McuSupportOptions::kit(const BoardOptions* board)
|
||||||
|
{
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
Kit *kit = KitManager::kit([board](const Kit *k){
|
||||||
|
return board->model() == k->value(Constants::KIT_BOARD_MODEL_KEY).toString();
|
||||||
|
});
|
||||||
|
if (!kit) {
|
||||||
|
const QString armGccPath = toolchainPackage->path();
|
||||||
|
const auto init = [board, &armGccPath](Kit *k) {
|
||||||
|
KitGuard kitGuard(k);
|
||||||
|
|
||||||
|
setKitProperties(k, board);
|
||||||
|
setKitToolchains(k, armGccPath);
|
||||||
|
setKitDebugger(k, armGccPath);
|
||||||
|
setKitDevice(k);
|
||||||
|
setKitEnvironment(k, board);
|
||||||
|
setKitCMakeOptions(k, board);
|
||||||
|
|
||||||
|
k->setup();
|
||||||
|
k->fix();
|
||||||
|
};
|
||||||
|
kit = KitManager::registerKit(init);
|
||||||
|
}
|
||||||
|
return kit;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Internal
|
||||||
|
} // McuSupport
|
137
src/plugins/mcusupport/mcusupportoptions.h
Normal file
137
src/plugins/mcusupport/mcusupportoptions.h
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 BlackBerry Limited. All rights reserved.
|
||||||
|
** Contact: BlackBerry (qt@blackberry.com)
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
QT_FORWARD_DECLARE_CLASS(QWidget)
|
||||||
|
QT_FORWARD_DECLARE_CLASS(QLabel)
|
||||||
|
|
||||||
|
namespace Utils {
|
||||||
|
class PathChooser;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ProjectExplorer {
|
||||||
|
class Kit;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace McuSupport {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class PackageOptions : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Status {
|
||||||
|
InvalidPath,
|
||||||
|
ValidPathInvalidPackage,
|
||||||
|
ValidPackage
|
||||||
|
};
|
||||||
|
|
||||||
|
PackageOptions(const QString &label, const QString &defaultPath, const QString &detectionPath,
|
||||||
|
const QString &settingsKey);
|
||||||
|
|
||||||
|
QString path() const;
|
||||||
|
QString label() const;
|
||||||
|
QString detectionPath() const;
|
||||||
|
Status status() const;
|
||||||
|
void setDownloadUrl(const QString &url);
|
||||||
|
void setEnvironmentVariableName(const QString &name);
|
||||||
|
void setAddToPath(bool addToPath);
|
||||||
|
bool addToPath() const;
|
||||||
|
void writeToSettings() const;
|
||||||
|
void setRelativePathModifier(const QString &path);
|
||||||
|
|
||||||
|
QWidget *widget();
|
||||||
|
|
||||||
|
QString environmentVariableName() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void changed();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateStatus();
|
||||||
|
|
||||||
|
QWidget *m_widget = nullptr;
|
||||||
|
Utils::PathChooser *m_fileChooser = nullptr;
|
||||||
|
QLabel *m_statusIcon = nullptr;
|
||||||
|
QLabel *m_statusLabel = nullptr;
|
||||||
|
|
||||||
|
const QString m_label;
|
||||||
|
const QString m_defaultPath;
|
||||||
|
const QString m_detectionPath;
|
||||||
|
const QString m_settingsKey;
|
||||||
|
|
||||||
|
QString m_path;
|
||||||
|
QString m_relativePathModifier; // relative path to m_path to be returned by path()
|
||||||
|
QString m_downloadUrl;
|
||||||
|
QString m_environmentVariableName;
|
||||||
|
bool m_addToPath = false;
|
||||||
|
|
||||||
|
Status m_status = InvalidPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BoardOptions : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
BoardOptions(const QString &model, const QString &toolChainFile,
|
||||||
|
const QVector<PackageOptions *> &packages);
|
||||||
|
|
||||||
|
QString model() const;
|
||||||
|
QString toolChainFile() const;
|
||||||
|
QVector<PackageOptions *> packages() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QString m_model;
|
||||||
|
const QString m_toolChainFile;
|
||||||
|
const QVector<PackageOptions*> m_packages;
|
||||||
|
};
|
||||||
|
|
||||||
|
class McuSupportOptions : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
McuSupportOptions(QObject *parent = nullptr);
|
||||||
|
~McuSupportOptions() override;
|
||||||
|
|
||||||
|
QVector<BoardOptions*> validBoards() const;
|
||||||
|
|
||||||
|
QVector<PackageOptions*> packages;
|
||||||
|
QVector<BoardOptions*> boards;
|
||||||
|
PackageOptions *toolchainPackage = nullptr;
|
||||||
|
|
||||||
|
ProjectExplorer::Kit *kit(const BoardOptions* board);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void changed();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace McuSupport
|
@@ -25,441 +25,24 @@
|
|||||||
|
|
||||||
#include "mcusupportconstants.h"
|
#include "mcusupportconstants.h"
|
||||||
#include "mcusupportoptionspage.h"
|
#include "mcusupportoptionspage.h"
|
||||||
|
#include "mcusupportoptions.h"
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <cmakeprojectmanager/cmakekitinformation.h>
|
|
||||||
#include <debugger/debuggeritem.h>
|
|
||||||
#include <debugger/debuggeritemmanager.h>
|
|
||||||
#include <debugger/debuggerkitinformation.h>
|
|
||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
#include <projectexplorer/toolchain.h>
|
|
||||||
#include <projectexplorer/toolchainmanager.h>
|
|
||||||
#include <projectexplorer/kitmanager.h>
|
|
||||||
#include <projectexplorer/kitinformation.h>
|
|
||||||
#include <projectexplorer/devicesupport/devicemanager.h>
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/fileutils.h>
|
|
||||||
#include <utils/pathchooser.h>
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
#include <QAction>
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QDebug>
|
|
||||||
#include <QDesktopServices>
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QSizePolicy>
|
|
||||||
#include <QToolButton>
|
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QVariant>
|
|
||||||
|
|
||||||
namespace McuSupport {
|
namespace McuSupport {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class PackageOptions : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum Status {
|
|
||||||
InvalidPath,
|
|
||||||
ValidPathInvalidPackage,
|
|
||||||
ValidPackage
|
|
||||||
};
|
|
||||||
|
|
||||||
PackageOptions(const QString &label, const QString &defaultPath, const QString &detectionPath,
|
|
||||||
const QString &settingsKey);
|
|
||||||
|
|
||||||
QString path() const;
|
|
||||||
QString label() const;
|
|
||||||
QString detectionPath() const;
|
|
||||||
Status status() const;
|
|
||||||
void setDownloadUrl(const QUrl &url);
|
|
||||||
void setEnvironmentVariableName(const QString &name);
|
|
||||||
void setAddToPath(bool addToPath);
|
|
||||||
bool addToPath() const;
|
|
||||||
void writeToSettings() const;
|
|
||||||
void setRelativePathModifier(const QString &path);
|
|
||||||
|
|
||||||
QWidget *widget();
|
|
||||||
|
|
||||||
|
|
||||||
QString environmentVariableName() const;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void changed();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void updateStatus();
|
|
||||||
|
|
||||||
QWidget *m_widget = nullptr;
|
|
||||||
Utils::PathChooser *m_fileChooser = nullptr;
|
|
||||||
QLabel *m_statusIcon = nullptr;
|
|
||||||
QLabel *m_statusLabel = nullptr;
|
|
||||||
|
|
||||||
const QString m_label;
|
|
||||||
const QString m_defaultPath;
|
|
||||||
const QString m_detectionPath;
|
|
||||||
const QString m_settingsKey;
|
|
||||||
|
|
||||||
QString m_path;
|
|
||||||
QString m_relativePathModifier; // relative path to m_path to be returned by path()
|
|
||||||
QUrl m_downloadUrl;
|
|
||||||
QString m_environmentVariableName;
|
|
||||||
bool m_addToPath = false;
|
|
||||||
|
|
||||||
Status m_status = InvalidPath;
|
|
||||||
};
|
|
||||||
|
|
||||||
PackageOptions::PackageOptions(const QString &label, const QString &defaultPath,
|
|
||||||
const QString &detectionPath, const QString &settingsKey)
|
|
||||||
: m_label(label)
|
|
||||||
, m_defaultPath(defaultPath)
|
|
||||||
, m_detectionPath(detectionPath)
|
|
||||||
, m_settingsKey(settingsKey)
|
|
||||||
{
|
|
||||||
QSettings *s = Core::ICore::settings();
|
|
||||||
s->beginGroup(Constants::SETTINGS_GROUP);
|
|
||||||
m_path = s->value(QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey,
|
|
||||||
m_defaultPath).toString();
|
|
||||||
s->endGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString PackageOptions::path() const
|
|
||||||
{
|
|
||||||
return QFileInfo(m_fileChooser->path() + m_relativePathModifier).absoluteFilePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString PackageOptions::label() const
|
|
||||||
{
|
|
||||||
return m_label;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString PackageOptions::detectionPath() const
|
|
||||||
{
|
|
||||||
return m_detectionPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget *PackageOptions::widget()
|
|
||||||
{
|
|
||||||
if (m_widget)
|
|
||||||
return m_widget;
|
|
||||||
|
|
||||||
m_widget = new QWidget;
|
|
||||||
m_fileChooser = new Utils::PathChooser;
|
|
||||||
QObject::connect(m_fileChooser, &Utils::PathChooser::pathChanged,
|
|
||||||
[this](){
|
|
||||||
updateStatus();
|
|
||||||
emit changed();
|
|
||||||
});
|
|
||||||
|
|
||||||
auto layout = new QGridLayout(m_widget);
|
|
||||||
layout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
m_statusIcon = new QLabel;
|
|
||||||
m_statusIcon->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::MinimumExpanding);
|
|
||||||
m_statusIcon->setAlignment(Qt::AlignTop);
|
|
||||||
m_statusLabel = new QLabel;
|
|
||||||
m_statusLabel->setWordWrap(true);
|
|
||||||
m_statusLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
|
|
||||||
|
|
||||||
if (!m_downloadUrl.isEmpty()) {
|
|
||||||
auto downLoadButton = new QToolButton;
|
|
||||||
downLoadButton->setIcon(Utils::Icons::DOWNLOAD.icon());
|
|
||||||
downLoadButton->setToolTip(McuSupportOptionsPage::tr("Download from \"%1\"")
|
|
||||||
.arg(m_downloadUrl.toString()));
|
|
||||||
QObject::connect(downLoadButton, &QToolButton::pressed, [this]{
|
|
||||||
QDesktopServices::openUrl(m_downloadUrl);
|
|
||||||
});
|
|
||||||
layout->addWidget(downLoadButton, 0, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
layout->addWidget(m_fileChooser, 0, 0, 1, 2);
|
|
||||||
layout->addWidget(m_statusIcon, 1, 0);
|
|
||||||
layout->addWidget(m_statusLabel, 1, 1, 1, -1);
|
|
||||||
|
|
||||||
m_fileChooser->setPath(m_path); // Triggers updateStatus() call
|
|
||||||
return m_widget;
|
|
||||||
}
|
|
||||||
|
|
||||||
PackageOptions::Status PackageOptions::status() const
|
|
||||||
{
|
|
||||||
return m_status;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PackageOptions::setDownloadUrl(const QUrl &url)
|
|
||||||
{
|
|
||||||
m_downloadUrl = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PackageOptions::setEnvironmentVariableName(const QString &name)
|
|
||||||
{
|
|
||||||
m_environmentVariableName = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString PackageOptions::environmentVariableName() const
|
|
||||||
{
|
|
||||||
return m_environmentVariableName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PackageOptions::setAddToPath(bool addToPath)
|
|
||||||
{
|
|
||||||
m_addToPath = addToPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PackageOptions::addToPath() const
|
|
||||||
{
|
|
||||||
return m_addToPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PackageOptions::writeToSettings() const
|
|
||||||
{
|
|
||||||
if (m_path.compare(m_defaultPath) == 0)
|
|
||||||
return;
|
|
||||||
QSettings *s = Core::ICore::settings();
|
|
||||||
s->beginGroup(Constants::SETTINGS_GROUP);
|
|
||||||
s->setValue(QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey, m_path);
|
|
||||||
s->endGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PackageOptions::setRelativePathModifier(const QString &path)
|
|
||||||
{
|
|
||||||
m_relativePathModifier = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PackageOptions::updateStatus()
|
|
||||||
{
|
|
||||||
m_path = m_fileChooser->rawPath();
|
|
||||||
const bool validPath = m_fileChooser->isValid();
|
|
||||||
const Utils::FilePath detectionPath = Utils::FilePath::fromString(
|
|
||||||
m_fileChooser->path() + "/" + m_detectionPath);
|
|
||||||
const QString displayDetectionPath = Utils::FilePath::fromString(m_detectionPath).toUserOutput();
|
|
||||||
const bool validPackage = detectionPath.exists();
|
|
||||||
|
|
||||||
m_status = validPath ? (validPackage ? ValidPackage : ValidPathInvalidPackage) : InvalidPath;
|
|
||||||
|
|
||||||
static const QPixmap okIcon = Utils::Icons::OK.pixmap();
|
|
||||||
static const QPixmap notOkIcon = Utils::Icons::BROKEN.pixmap();
|
|
||||||
m_statusIcon->setPixmap(m_status == ValidPackage ? okIcon : notOkIcon);
|
|
||||||
|
|
||||||
QString statusText;
|
|
||||||
switch (m_status) {
|
|
||||||
case ValidPackage:
|
|
||||||
statusText = McuSupportOptionsPage::tr(
|
|
||||||
"Path is valid, \"%1\" was found.").arg(displayDetectionPath);
|
|
||||||
break;
|
|
||||||
case ValidPathInvalidPackage:
|
|
||||||
statusText = McuSupportOptionsPage::tr(
|
|
||||||
"Path exists, but does not contain \"%1\".").arg(displayDetectionPath);
|
|
||||||
break;
|
|
||||||
case InvalidPath:
|
|
||||||
statusText = McuSupportOptionsPage::tr("Path does not exist.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
m_statusLabel->setText(statusText);
|
|
||||||
}
|
|
||||||
|
|
||||||
class BoardOptions : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
BoardOptions(const QString &model, const QString &toolChainFile,
|
|
||||||
const QVector<PackageOptions *> &packages);
|
|
||||||
|
|
||||||
QString model() const;
|
|
||||||
QString toolChainFile() const;
|
|
||||||
QVector<PackageOptions *> packages() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const QString m_model;
|
|
||||||
const QString m_toolChainFile;
|
|
||||||
const QVector<PackageOptions*> m_packages;
|
|
||||||
};
|
|
||||||
|
|
||||||
BoardOptions::BoardOptions(const QString &model, const QString &toolChainFileName,
|
|
||||||
const QVector<PackageOptions*> &packages)
|
|
||||||
: m_model(model)
|
|
||||||
, m_toolChainFile(toolChainFileName)
|
|
||||||
, m_packages(packages)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QString BoardOptions::model() const
|
|
||||||
{
|
|
||||||
return m_model;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString BoardOptions::toolChainFile() const
|
|
||||||
{
|
|
||||||
return m_toolChainFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector<PackageOptions *> BoardOptions::packages() const
|
|
||||||
{
|
|
||||||
return m_packages;
|
|
||||||
}
|
|
||||||
|
|
||||||
class McuSupportOptions : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
McuSupportOptions(QObject *parent = nullptr);
|
|
||||||
~McuSupportOptions() override;
|
|
||||||
|
|
||||||
QVector<BoardOptions*> validBoards() const;
|
|
||||||
|
|
||||||
QVector<PackageOptions*> packages;
|
|
||||||
QVector<BoardOptions*> boards;
|
|
||||||
PackageOptions* toolchainPackage = nullptr;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void changed();
|
|
||||||
};
|
|
||||||
|
|
||||||
static PackageOptions* createQulPackage()
|
|
||||||
{
|
|
||||||
auto result = new PackageOptions(
|
|
||||||
McuSupportOptionsPage::tr("Qt MCU SDK"),
|
|
||||||
QDir::homePath(),
|
|
||||||
Utils::HostOsInfo::withExecutableSuffix("bin/qmltocpp"),
|
|
||||||
"qulSdk");
|
|
||||||
result->setEnvironmentVariableName("Qul_DIR");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PackageOptions* createArmGccPackage()
|
|
||||||
{
|
|
||||||
const QString defaultPath =
|
|
||||||
Utils::HostOsInfo::isWindowsHost() ?
|
|
||||||
QDir::fromNativeSeparators(qEnvironmentVariable("ProgramFiles(x86)"))
|
|
||||||
+ "/GNU Tools ARM Embedded/"
|
|
||||||
: QString("%{Env:ARMGCC_DIR}");
|
|
||||||
auto result = new PackageOptions(
|
|
||||||
McuSupportOptionsPage::tr("GNU Arm Embedded Toolchain"),
|
|
||||||
defaultPath,
|
|
||||||
Utils::HostOsInfo::withExecutableSuffix("bin/arm-none-eabi-g++"),
|
|
||||||
Constants::SETTINGS_KEY_PACKAGE_ARMGCC);
|
|
||||||
result->setDownloadUrl(
|
|
||||||
QUrl::fromUserInput("https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads"));
|
|
||||||
result->setEnvironmentVariableName("ARMGCC_DIR");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PackageOptions* createStm32CubeFwF7SdkPackage()
|
|
||||||
{
|
|
||||||
auto result = new PackageOptions(
|
|
||||||
McuSupportOptionsPage::tr("STM32Cube SDK"),
|
|
||||||
"%{Env:STM32Cube_FW_F7_SDK_PATH}",
|
|
||||||
"Drivers/STM32F7xx_HAL_Driver",
|
|
||||||
"stm32CubeFwF7Sdk");
|
|
||||||
result->setDownloadUrl(
|
|
||||||
QUrl::fromUserInput("https://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32cube-mcu-packages/stm32cubef7.html"));
|
|
||||||
result->setEnvironmentVariableName("STM32Cube_FW_F7_SDK_PATH");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PackageOptions* createStm32CubeProgrammerPackage()
|
|
||||||
{
|
|
||||||
const QString defaultPath =
|
|
||||||
Utils::HostOsInfo::isWindowsHost() ?
|
|
||||||
QDir::fromNativeSeparators(qEnvironmentVariable("ProgramFiles"))
|
|
||||||
+ "/STMicroelectronics/STM32Cube/STM32CubeProgrammer/"
|
|
||||||
: QDir::homePath();
|
|
||||||
auto result = new PackageOptions(
|
|
||||||
McuSupportOptionsPage::tr("STM32CubeProgrammer"),
|
|
||||||
defaultPath,
|
|
||||||
QLatin1String(Utils::HostOsInfo::isWindowsHost() ? "/bin/STM32_Programmer_CLI.exe"
|
|
||||||
: "/bin/STM32_Programmer.sh"),
|
|
||||||
"stm32CubeProgrammer");
|
|
||||||
result->setRelativePathModifier("/bin");
|
|
||||||
result->setDownloadUrl(
|
|
||||||
QUrl::fromUserInput("https://www.st.com/en/development-tools/stm32cubeprog.html"));
|
|
||||||
result->setAddToPath(true);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PackageOptions* createEvkbImxrt1050SdkPackage()
|
|
||||||
{
|
|
||||||
auto result = new PackageOptions(
|
|
||||||
McuSupportOptionsPage::tr("NXP EVKB-IMXRT1050 SDK"),
|
|
||||||
"%{Env:EVKB_IMXRT1050_SDK_PATH}",
|
|
||||||
"EVKB-IMXRT1050_manifest_v3_5.xml",
|
|
||||||
"evkbImxrt1050Sdk");
|
|
||||||
result->setDownloadUrl(
|
|
||||||
QUrl::fromUserInput("https://mcuxpresso.nxp.com/en/welcome"));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PackageOptions* createSeggerJLinkPackage()
|
|
||||||
{
|
|
||||||
const QString defaultPath =
|
|
||||||
Utils::HostOsInfo::isWindowsHost() ?
|
|
||||||
QDir::fromNativeSeparators(qEnvironmentVariable("ProgramFiles")) + "/SEGGER/JLink"
|
|
||||||
: QString("%{Env:SEGGER_JLINK_SOFTWARE_AND_DOCUMENTATION_PATH}");
|
|
||||||
auto result = new PackageOptions(
|
|
||||||
McuSupportOptionsPage::tr("SEGGER JLink"),
|
|
||||||
defaultPath,
|
|
||||||
Utils::HostOsInfo::withExecutableSuffix("JLink"),
|
|
||||||
"seggerJLink");
|
|
||||||
result->setDownloadUrl(
|
|
||||||
QUrl::fromUserInput("https://www.segger.com/downloads/jlink"));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
McuSupportOptions::McuSupportOptions(QObject *parent)
|
|
||||||
: QObject(parent)
|
|
||||||
{
|
|
||||||
PackageOptions* qulPackage = createQulPackage();
|
|
||||||
PackageOptions* armGccPackage = createArmGccPackage();
|
|
||||||
PackageOptions* stm32CubeFwF7SdkPackage = createStm32CubeFwF7SdkPackage();
|
|
||||||
PackageOptions* stm32CubeProgrammerPackage = createStm32CubeProgrammerPackage();
|
|
||||||
PackageOptions* evkbImxrt1050SdkPackage = createEvkbImxrt1050SdkPackage();
|
|
||||||
PackageOptions* seggerJLinkPackage = createSeggerJLinkPackage();
|
|
||||||
|
|
||||||
toolchainPackage = armGccPackage;
|
|
||||||
|
|
||||||
|
|
||||||
auto stmPackages = {armGccPackage, stm32CubeFwF7SdkPackage, stm32CubeProgrammerPackage,
|
|
||||||
qulPackage};
|
|
||||||
auto nxpPackages = {armGccPackage, evkbImxrt1050SdkPackage, seggerJLinkPackage,
|
|
||||||
qulPackage};
|
|
||||||
packages = {armGccPackage, stm32CubeFwF7SdkPackage, stm32CubeProgrammerPackage,
|
|
||||||
evkbImxrt1050SdkPackage, seggerJLinkPackage, qulPackage};
|
|
||||||
|
|
||||||
boards.append(new BoardOptions(
|
|
||||||
"stm32f7508", "CMake/stm32f7508-discovery.cmake", stmPackages));
|
|
||||||
boards.append(new BoardOptions(
|
|
||||||
"stm32f769i", "CMake/stm32f769i-discovery.cmake", stmPackages));
|
|
||||||
boards.append(new BoardOptions(
|
|
||||||
"evkbimxrt1050", "CMake/evkbimxrt1050-toolchain.cmake", nxpPackages));
|
|
||||||
|
|
||||||
for (auto package : packages)
|
|
||||||
connect(package, &PackageOptions::changed, [this](){
|
|
||||||
emit changed();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
McuSupportOptions::~McuSupportOptions()
|
|
||||||
{
|
|
||||||
qDeleteAll(packages);
|
|
||||||
packages.clear();
|
|
||||||
qDeleteAll(boards);
|
|
||||||
boards.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector<BoardOptions *> McuSupportOptions::validBoards() const
|
|
||||||
{
|
|
||||||
return Utils::filtered(boards, [](BoardOptions *board){
|
|
||||||
return !Utils::anyOf(board->packages(), [](PackageOptions *package){
|
|
||||||
return package->status() != PackageOptions::ValidPackage;});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
class McuSupportOptionsWidget : public QWidget
|
class McuSupportOptionsWidget : public QWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -571,146 +154,6 @@ QWidget* McuSupportOptionsPage::widget()
|
|||||||
return m_widget;
|
return m_widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ProjectExplorer::ToolChain* armGccToolchain(const Utils::FilePath &path, Core::Id language)
|
|
||||||
{
|
|
||||||
using namespace ProjectExplorer;
|
|
||||||
|
|
||||||
ToolChain *toolChain = ToolChainManager::toolChain([&path, language](const ToolChain *t){
|
|
||||||
return t->compilerCommand() == path && t->language() == language;
|
|
||||||
});
|
|
||||||
if (!toolChain) {
|
|
||||||
ToolChainFactory *gccFactory =
|
|
||||||
Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), [](ToolChainFactory *f){
|
|
||||||
return f->supportedToolChainType() == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID;
|
|
||||||
});
|
|
||||||
if (gccFactory) {
|
|
||||||
const QList<ToolChain*> detected = gccFactory->detectForImport({path, language});
|
|
||||||
if (!detected.isEmpty()) {
|
|
||||||
toolChain = detected.first();
|
|
||||||
toolChain->setDetection(ToolChain::ManualDetection);
|
|
||||||
toolChain->setDisplayName("Arm GCC");
|
|
||||||
ToolChainManager::registerToolChain(toolChain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return toolChain;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setKitProperties(ProjectExplorer::Kit *k, const BoardOptions* board)
|
|
||||||
{
|
|
||||||
using namespace ProjectExplorer;
|
|
||||||
|
|
||||||
k->setUnexpandedDisplayName("Qt MCU - " + board->model());
|
|
||||||
k->setValue(Constants::KIT_BOARD_MODEL_KEY, board->model());
|
|
||||||
k->setAutoDetected(false);
|
|
||||||
k->setIrrelevantAspects({
|
|
||||||
SysRootKitAspect::id(),
|
|
||||||
"QtSupport.QtInformation" // QtKitAspect::id()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setKitToolchains(ProjectExplorer::Kit *k, const QString &armGccPath)
|
|
||||||
{
|
|
||||||
using namespace ProjectExplorer;
|
|
||||||
|
|
||||||
const QString compileNameScheme = Utils::HostOsInfo::withExecutableSuffix(
|
|
||||||
armGccPath + "/bin/arm-none-eabi-%1");
|
|
||||||
ToolChain *cTc = armGccToolchain(
|
|
||||||
Utils::FilePath::fromUserInput(compileNameScheme.arg("gcc")),
|
|
||||||
ProjectExplorer::Constants::C_LANGUAGE_ID);
|
|
||||||
ToolChain *cxxTc = armGccToolchain(
|
|
||||||
Utils::FilePath::fromUserInput(compileNameScheme.arg("g++")),
|
|
||||||
ProjectExplorer::Constants::CXX_LANGUAGE_ID);
|
|
||||||
ToolChainKitAspect::setToolChain(k, cTc);
|
|
||||||
ToolChainKitAspect::setToolChain(k, cxxTc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setKitDebugger(ProjectExplorer::Kit *k, const QString &armGccPath)
|
|
||||||
{
|
|
||||||
using namespace Debugger;
|
|
||||||
|
|
||||||
const Utils::FilePath command = Utils::FilePath::fromUserInput(
|
|
||||||
Utils::HostOsInfo::withExecutableSuffix(armGccPath + "/bin/arm-none-eabi-gdb-py"));
|
|
||||||
const DebuggerItem *debugger = DebuggerItemManager::findByCommand(command);
|
|
||||||
QVariant debuggerId;
|
|
||||||
if (!debugger) {
|
|
||||||
DebuggerItem newDebugger;
|
|
||||||
newDebugger.setCommand(command);
|
|
||||||
newDebugger.setUnexpandedDisplayName(
|
|
||||||
McuSupportOptionsPage::tr("Arm GDB at %1").arg(command.toUserOutput()));
|
|
||||||
debuggerId = DebuggerItemManager::registerDebugger(newDebugger);
|
|
||||||
} else {
|
|
||||||
debuggerId = debugger->id();
|
|
||||||
}
|
|
||||||
|
|
||||||
DebuggerKitAspect::setDebugger(k, debuggerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setKitDevice(ProjectExplorer::Kit *k)
|
|
||||||
{
|
|
||||||
using namespace ProjectExplorer;
|
|
||||||
|
|
||||||
DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DEVICE_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setKitEnvironment(ProjectExplorer::Kit *k, const BoardOptions* board)
|
|
||||||
{
|
|
||||||
using namespace ProjectExplorer;
|
|
||||||
|
|
||||||
Utils::EnvironmentItems changes;
|
|
||||||
QStringList pathAdditions;
|
|
||||||
for (auto package : board->packages()) {
|
|
||||||
if (package->addToPath())
|
|
||||||
pathAdditions.append(QDir::toNativeSeparators(package->path()));
|
|
||||||
if (!package->environmentVariableName().isEmpty())
|
|
||||||
changes.append({package->environmentVariableName(),
|
|
||||||
QDir::toNativeSeparators(package->path())});
|
|
||||||
}
|
|
||||||
if (!pathAdditions.isEmpty()) {
|
|
||||||
pathAdditions.append("${Path}");
|
|
||||||
changes.append({"Path", pathAdditions.join(Utils::HostOsInfo::pathListSeparator())});
|
|
||||||
}
|
|
||||||
EnvironmentKitAspect::setEnvironmentChanges(k, changes);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setKitCMakeOptions(ProjectExplorer::Kit *k, const BoardOptions* board)
|
|
||||||
{
|
|
||||||
using namespace CMakeProjectManager;
|
|
||||||
|
|
||||||
CMakeConfig config = CMakeConfigurationKitAspect::configuration(k);
|
|
||||||
config.append(CMakeConfigItem("CMAKE_TOOLCHAIN_FILE",
|
|
||||||
("%{CurrentBuild:Env:Qul_DIR}/" +
|
|
||||||
board->toolChainFile()).toUtf8()));
|
|
||||||
CMakeConfigurationKitAspect::setConfiguration(k, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ProjectExplorer::Kit* boardKit(const BoardOptions* board, const QString &armGccPath)
|
|
||||||
{
|
|
||||||
using namespace ProjectExplorer;
|
|
||||||
|
|
||||||
Kit *kit = KitManager::kit([board](const Kit *k){
|
|
||||||
return board->model() == k->value(Constants::KIT_BOARD_MODEL_KEY).toString();
|
|
||||||
});
|
|
||||||
if (!kit) {
|
|
||||||
const auto init = [board, &armGccPath](Kit *k) {
|
|
||||||
KitGuard kitGuard(k);
|
|
||||||
|
|
||||||
setKitProperties(k, board);
|
|
||||||
setKitToolchains(k, armGccPath);
|
|
||||||
setKitDebugger(k, armGccPath);
|
|
||||||
setKitDevice(k);
|
|
||||||
setKitEnvironment(k, board);
|
|
||||||
setKitCMakeOptions(k, board);
|
|
||||||
|
|
||||||
k->setup();
|
|
||||||
k->fix();
|
|
||||||
};
|
|
||||||
kit = KitManager::registerKit(init);
|
|
||||||
}
|
|
||||||
return kit;
|
|
||||||
}
|
|
||||||
|
|
||||||
void McuSupportOptionsPage::apply()
|
void McuSupportOptionsPage::apply()
|
||||||
{
|
{
|
||||||
for (auto package : m_options->packages)
|
for (auto package : m_options->packages)
|
||||||
@@ -723,7 +166,7 @@ void McuSupportOptionsPage::apply()
|
|||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
for (auto board : validBoards)
|
for (auto board : validBoards)
|
||||||
boardKit(board, m_options->toolchainPackage->path());
|
m_options->kit(board);
|
||||||
}
|
}
|
||||||
|
|
||||||
void McuSupportOptionsPage::finish()
|
void McuSupportOptionsPage::finish()
|
||||||
|
Reference in New Issue
Block a user