2019-10-22 14:33:31 +02:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
2020-07-02 16:04:31 +02:00
|
|
|
** Copyright (C) 2020 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2019-10-22 14:33:31 +02:00
|
|
|
**
|
|
|
|
|
** 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"
|
2020-03-12 14:25:49 +01:00
|
|
|
#include "mcusupportsdk.h"
|
2019-10-22 14:33:31 +02:00
|
|
|
|
2020-11-13 14:00:18 +01:00
|
|
|
#include <baremetal/baremetalconstants.h>
|
2020-04-07 18:19:32 +02:00
|
|
|
#include <cmakeprojectmanager/cmaketoolmanager.h>
|
2019-10-22 14:33:31 +02:00
|
|
|
#include <coreplugin/icore.h>
|
2020-03-24 18:58:29 +01:00
|
|
|
#include <coreplugin/helpmanager.h>
|
2020-12-04 16:32:34 +01:00
|
|
|
#include <coreplugin/messagemanager.h>
|
2019-10-22 14:33:31 +02:00
|
|
|
#include <cmakeprojectmanager/cmakekitinformation.h>
|
|
|
|
|
#include <debugger/debuggeritem.h>
|
|
|
|
|
#include <debugger/debuggeritemmanager.h>
|
|
|
|
|
#include <debugger/debuggerkitinformation.h>
|
2020-04-07 18:19:32 +02:00
|
|
|
#include <projectexplorer/abi.h>
|
2019-10-22 14:33:31 +02:00
|
|
|
#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>
|
2020-04-07 18:19:32 +02:00
|
|
|
#include <qtsupport/qtkitinformation.h>
|
2020-04-02 19:31:52 +02:00
|
|
|
#include <qtsupport/qtversionmanager.h>
|
2019-10-22 14:33:31 +02:00
|
|
|
#include <utils/algorithm.h>
|
|
|
|
|
#include <utils/fileutils.h>
|
2019-12-11 21:17:53 +01:00
|
|
|
#include <utils/infolabel.h>
|
2019-10-22 14:33:31 +02:00
|
|
|
#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>
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
using namespace ProjectExplorer;
|
|
|
|
|
using namespace Utils;
|
|
|
|
|
|
2019-10-22 14:33:31 +02:00
|
|
|
namespace McuSupport {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2020-12-07 10:46:13 +01:00
|
|
|
static const int KIT_VERSION = 8; // Bumps up whenever details in Kit creation change
|
2020-04-22 23:24:54 +02:00
|
|
|
|
2020-06-05 00:33:06 +02:00
|
|
|
static QString packagePathFromSettings(const QString &settingsKey,
|
|
|
|
|
QSettings::Scope scope = QSettings::UserScope,
|
|
|
|
|
const QString &defaultPath = {})
|
2020-03-24 18:58:29 +01:00
|
|
|
{
|
2020-10-16 15:10:17 +02:00
|
|
|
QSettings *settings = Core::ICore::settings(scope);
|
|
|
|
|
const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' +
|
|
|
|
|
QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + settingsKey;
|
|
|
|
|
const QString path = settings->value(key, defaultPath).toString();
|
2020-11-20 16:08:08 +01:00
|
|
|
return FilePath::fromUserInput(path).toString();
|
2020-03-24 18:58:29 +01:00
|
|
|
}
|
|
|
|
|
|
2020-10-16 15:10:17 +02:00
|
|
|
static bool automaticKitCreationFromSettings(QSettings::Scope scope = QSettings::UserScope)
|
|
|
|
|
{
|
|
|
|
|
QSettings *settings = Core::ICore::settings(scope);
|
|
|
|
|
const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' +
|
|
|
|
|
QLatin1String(Constants::SETTINGS_KEY_AUTOMATIC_KIT_CREATION);
|
|
|
|
|
bool automaticKitCreation = settings->value(key, true).toBool();
|
|
|
|
|
return automaticKitCreation;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-31 00:05:50 +02:00
|
|
|
static bool kitNeedsQtVersion()
|
|
|
|
|
{
|
|
|
|
|
// Only on Windows, Qt is linked into the distributed qul Desktop libs. Also, the host tools
|
|
|
|
|
// are missing the Qt runtime libraries on non-Windows.
|
2020-09-17 11:05:28 +02:00
|
|
|
return !HostOsInfo::isWindowsHost();
|
2020-08-31 00:05:50 +02:00
|
|
|
}
|
|
|
|
|
|
2019-11-15 08:38:55 +01:00
|
|
|
McuPackage::McuPackage(const QString &label, const QString &defaultPath,
|
|
|
|
|
const QString &detectionPath, const QString &settingsKey)
|
2019-10-22 14:33:31 +02:00
|
|
|
: m_label(label)
|
2020-06-05 00:33:06 +02:00
|
|
|
, m_defaultPath(packagePathFromSettings(settingsKey, QSettings::SystemScope, defaultPath))
|
2019-10-22 14:33:31 +02:00
|
|
|
, m_detectionPath(detectionPath)
|
|
|
|
|
, m_settingsKey(settingsKey)
|
|
|
|
|
{
|
2020-06-05 00:33:06 +02:00
|
|
|
m_path = packagePathFromSettings(settingsKey, QSettings::UserScope, m_defaultPath);
|
2020-10-16 15:10:17 +02:00
|
|
|
m_automaticKitCreation = automaticKitCreationFromSettings(QSettings::UserScope);
|
2019-10-22 14:33:31 +02:00
|
|
|
}
|
|
|
|
|
|
2020-12-04 16:32:34 +01:00
|
|
|
QString McuPackage::basePath() const
|
|
|
|
|
{
|
|
|
|
|
return m_fileChooser != nullptr ? m_fileChooser->filePath().toString() : m_path;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-15 08:38:55 +01:00
|
|
|
QString McuPackage::path() const
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
2020-12-04 16:32:34 +01:00
|
|
|
return QFileInfo(basePath() + m_relativePathModifier).absoluteFilePath();
|
2019-10-22 14:33:31 +02:00
|
|
|
}
|
|
|
|
|
|
2019-11-15 08:38:55 +01:00
|
|
|
QString McuPackage::label() const
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
|
|
|
|
return m_label;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-03 09:46:44 +02:00
|
|
|
QString McuPackage::defaultPath() const
|
|
|
|
|
{
|
|
|
|
|
return m_defaultPath;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-15 08:38:55 +01:00
|
|
|
QString McuPackage::detectionPath() const
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
|
|
|
|
return m_detectionPath;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-15 08:38:55 +01:00
|
|
|
QWidget *McuPackage::widget()
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
|
|
|
|
if (m_widget)
|
|
|
|
|
return m_widget;
|
|
|
|
|
|
|
|
|
|
m_widget = new QWidget;
|
2020-09-17 11:05:28 +02:00
|
|
|
m_fileChooser = new PathChooser;
|
|
|
|
|
m_fileChooser->lineEdit()->setButtonIcon(FancyLineEdit::Right,
|
|
|
|
|
Icons::RESET.icon());
|
|
|
|
|
m_fileChooser->lineEdit()->setButtonVisible(FancyLineEdit::Right, true);
|
|
|
|
|
connect(m_fileChooser->lineEdit(), &FancyLineEdit::rightButtonClicked, this, [&] {
|
2020-06-05 00:33:06 +02:00
|
|
|
m_fileChooser->setPath(m_defaultPath);
|
|
|
|
|
});
|
2019-10-22 14:33:31 +02:00
|
|
|
|
|
|
|
|
auto layout = new QGridLayout(m_widget);
|
|
|
|
|
layout->setContentsMargins(0, 0, 0, 0);
|
2020-09-17 11:05:28 +02:00
|
|
|
m_infoLabel = new InfoLabel();
|
2019-10-22 14:33:31 +02:00
|
|
|
|
|
|
|
|
if (!m_downloadUrl.isEmpty()) {
|
|
|
|
|
auto downLoadButton = new QToolButton;
|
2020-09-17 11:05:28 +02:00
|
|
|
downLoadButton->setIcon(Icons::ONLINE.icon());
|
2019-10-22 14:33:31 +02:00
|
|
|
downLoadButton->setToolTip(tr("Download from \"%1\"").arg(m_downloadUrl));
|
2020-09-17 11:05:28 +02:00
|
|
|
QObject::connect(downLoadButton, &QToolButton::pressed, this, [this] {
|
2019-10-22 14:33:31 +02:00
|
|
|
QDesktopServices::openUrl(m_downloadUrl);
|
|
|
|
|
});
|
|
|
|
|
layout->addWidget(downLoadButton, 0, 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
layout->addWidget(m_fileChooser, 0, 0, 1, 2);
|
2019-12-11 21:17:53 +01:00
|
|
|
layout->addWidget(m_infoLabel, 1, 0, 1, -1);
|
2019-10-22 14:33:31 +02:00
|
|
|
|
2019-11-13 18:37:27 +01:00
|
|
|
m_fileChooser->setPath(m_path);
|
|
|
|
|
|
2020-12-04 16:32:34 +01:00
|
|
|
QObject::connect(this, &McuPackage::statusChanged, this, [this] {
|
|
|
|
|
updateStatusUi();
|
|
|
|
|
});
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
QObject::connect(m_fileChooser, &PathChooser::pathChanged, this, [this] {
|
2020-12-04 16:32:34 +01:00
|
|
|
updatePath();
|
2019-11-13 18:37:27 +01:00
|
|
|
emit changed();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
updateStatus();
|
2019-10-22 14:33:31 +02:00
|
|
|
return m_widget;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-15 08:38:55 +01:00
|
|
|
McuPackage::Status McuPackage::status() const
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
|
|
|
|
return m_status;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-15 08:38:55 +01:00
|
|
|
void McuPackage::setDownloadUrl(const QString &url)
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
|
|
|
|
m_downloadUrl = url;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-15 08:38:55 +01:00
|
|
|
void McuPackage::setEnvironmentVariableName(const QString &name)
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
|
|
|
|
m_environmentVariableName = name;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-15 08:38:55 +01:00
|
|
|
QString McuPackage::environmentVariableName() const
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
|
|
|
|
return m_environmentVariableName;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-15 08:38:55 +01:00
|
|
|
void McuPackage::setAddToPath(bool addToPath)
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
|
|
|
|
m_addToPath = addToPath;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-15 08:38:55 +01:00
|
|
|
bool McuPackage::addToPath() const
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
|
|
|
|
return m_addToPath;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-16 15:10:17 +02:00
|
|
|
void McuPackage::writeGeneralSettings() const
|
|
|
|
|
{
|
|
|
|
|
const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' +
|
|
|
|
|
QLatin1String(Constants::SETTINGS_KEY_AUTOMATIC_KIT_CREATION);
|
|
|
|
|
QSettings *settings = Core::ICore::settings();
|
|
|
|
|
settings->setValue(key, m_automaticKitCreation);
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-15 08:38:55 +01:00
|
|
|
void McuPackage::writeToSettings() const
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
2020-06-03 09:28:47 +02:00
|
|
|
const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' +
|
|
|
|
|
QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey;
|
2020-11-19 15:34:59 +01:00
|
|
|
Core::ICore::settings()->setValueWithDefault(key, m_path, m_defaultPath);
|
2019-10-22 14:33:31 +02:00
|
|
|
}
|
|
|
|
|
|
2019-11-15 08:38:55 +01:00
|
|
|
void McuPackage::setRelativePathModifier(const QString &path)
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
|
|
|
|
m_relativePathModifier = path;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-16 15:10:17 +02:00
|
|
|
bool McuPackage::automaticKitCreationEnabled() const
|
|
|
|
|
{
|
|
|
|
|
return m_automaticKitCreation;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void McuPackage::setAutomaticKitCreationEnabled(const bool enabled)
|
|
|
|
|
{
|
|
|
|
|
m_automaticKitCreation = enabled;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-04 16:32:34 +01:00
|
|
|
void McuPackage::updatePath()
|
|
|
|
|
{
|
|
|
|
|
m_path = m_fileChooser->rawPath();
|
|
|
|
|
m_fileChooser->lineEdit()->button(FancyLineEdit::Right)->setEnabled(m_path != m_defaultPath);
|
|
|
|
|
updateStatus();
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-15 08:38:55 +01:00
|
|
|
void McuPackage::updateStatus()
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
2020-12-04 16:32:34 +01:00
|
|
|
bool validPath = !m_path.isEmpty() && FilePath::fromString(m_path).exists();
|
|
|
|
|
const FilePath detectionPath = FilePath::fromString(basePath() + "/" + m_detectionPath);
|
2020-04-09 23:50:03 +02:00
|
|
|
const bool validPackage = m_detectionPath.isEmpty() || detectionPath.exists();
|
2019-10-22 14:33:31 +02:00
|
|
|
|
2020-12-04 16:32:34 +01:00
|
|
|
m_status = validPath ? (validPackage ? ValidPackage : ValidPathInvalidPackage) :
|
|
|
|
|
m_path.isEmpty() ? EmptyPath : InvalidPath;
|
|
|
|
|
|
|
|
|
|
emit statusChanged();
|
|
|
|
|
}
|
2019-10-22 14:33:31 +02:00
|
|
|
|
2020-12-04 16:32:34 +01:00
|
|
|
void McuPackage::updateStatusUi()
|
|
|
|
|
{
|
2020-09-17 11:05:28 +02:00
|
|
|
m_infoLabel->setType(m_status == ValidPackage ? InfoLabel::Ok : InfoLabel::NotOk);
|
2020-12-04 16:32:34 +01:00
|
|
|
m_infoLabel->setText(statusText());
|
|
|
|
|
}
|
2019-10-22 14:33:31 +02:00
|
|
|
|
2020-12-04 16:32:34 +01:00
|
|
|
QString McuPackage::statusText() const
|
|
|
|
|
{
|
|
|
|
|
const QString displayPackagePath = FilePath::fromString(m_path).toUserOutput();
|
|
|
|
|
const QString displayDetectionPath = FilePath::fromString(m_detectionPath).toUserOutput();
|
|
|
|
|
QString response;
|
2019-10-22 14:33:31 +02:00
|
|
|
switch (m_status) {
|
|
|
|
|
case ValidPackage:
|
2020-12-04 16:32:34 +01:00
|
|
|
response = m_detectionPath.isEmpty()
|
|
|
|
|
? tr("Path %1 exists.").arg(displayPackagePath)
|
|
|
|
|
: tr("Path %1 is valid, %2 was found.")
|
|
|
|
|
.arg(displayPackagePath, displayDetectionPath);
|
2019-10-22 14:33:31 +02:00
|
|
|
break;
|
|
|
|
|
case ValidPathInvalidPackage:
|
2020-12-04 16:32:34 +01:00
|
|
|
response = tr("Path %1 exists, but does not contain %2.")
|
|
|
|
|
.arg(displayPackagePath, displayDetectionPath);
|
2019-10-22 14:33:31 +02:00
|
|
|
break;
|
|
|
|
|
case InvalidPath:
|
2020-12-04 16:32:34 +01:00
|
|
|
response = tr("Path %1 does not exist.").arg(displayPackagePath);
|
|
|
|
|
break;
|
|
|
|
|
case EmptyPath:
|
|
|
|
|
response = m_detectionPath.isEmpty()
|
|
|
|
|
? tr("Path is empty.")
|
|
|
|
|
: tr("Path is empty, %1 not found.")
|
|
|
|
|
.arg(displayDetectionPath);
|
2019-10-22 14:33:31 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2020-12-04 16:32:34 +01:00
|
|
|
return response;
|
2019-10-22 14:33:31 +02:00
|
|
|
}
|
|
|
|
|
|
2020-09-18 11:16:37 +02:00
|
|
|
McuToolChainPackage::McuToolChainPackage(const QString &label,
|
|
|
|
|
const QString &defaultPath,
|
|
|
|
|
const QString &detectionPath,
|
|
|
|
|
const QString &settingsKey,
|
2020-02-26 16:41:52 +01:00
|
|
|
McuToolChainPackage::Type type)
|
|
|
|
|
: McuPackage(label, defaultPath, detectionPath, settingsKey)
|
|
|
|
|
, m_type(type)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
McuToolChainPackage::Type McuToolChainPackage::type() const
|
|
|
|
|
{
|
|
|
|
|
return m_type;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-18 11:16:37 +02:00
|
|
|
bool McuToolChainPackage::isDesktopToolchain() const
|
|
|
|
|
{
|
|
|
|
|
return m_type == TypeMSVC || m_type == TypeGCC;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-23 10:11:44 +02:00
|
|
|
static ToolChain *msvcToolChain(Id language)
|
2020-09-18 11:16:37 +02:00
|
|
|
{
|
|
|
|
|
ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) {
|
|
|
|
|
const Abi abi = t->targetAbi();
|
|
|
|
|
return (abi.osFlavor() == Abi::WindowsMsvc2017Flavor || abi.osFlavor() == Abi::WindowsMsvc2019Flavor)
|
|
|
|
|
&& abi.architecture() == Abi::X86Architecture
|
|
|
|
|
&& abi.wordWidth() == 64
|
|
|
|
|
&& t->language() == language;
|
|
|
|
|
});
|
|
|
|
|
return toolChain;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-23 10:11:44 +02:00
|
|
|
static ToolChain *gccToolChain(Id language)
|
2020-04-07 18:19:32 +02:00
|
|
|
{
|
|
|
|
|
ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) {
|
|
|
|
|
const Abi abi = t->targetAbi();
|
2020-09-18 11:16:37 +02:00
|
|
|
return abi.os() != Abi::WindowsOS
|
2020-04-07 18:19:32 +02:00
|
|
|
&& abi.architecture() == Abi::X86Architecture
|
|
|
|
|
&& abi.wordWidth() == 64
|
|
|
|
|
&& t->language() == language;
|
|
|
|
|
});
|
|
|
|
|
return toolChain;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
static ToolChain *armGccToolChain(const FilePath &path, Id language)
|
2020-02-26 16:41:52 +01:00
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-13 14:00:18 +01:00
|
|
|
static ToolChain *iarToolChain(Id language)
|
|
|
|
|
{
|
|
|
|
|
ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t){
|
|
|
|
|
return t->typeId() == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID
|
|
|
|
|
&& t->language() == language;
|
|
|
|
|
});
|
|
|
|
|
if (!toolChain) {
|
|
|
|
|
ToolChainFactory *iarFactory =
|
|
|
|
|
Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), [](ToolChainFactory *f){
|
|
|
|
|
return f->supportedToolChainType() == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID;
|
|
|
|
|
});
|
|
|
|
|
if (iarFactory) {
|
|
|
|
|
const QList<ToolChain*> detected = iarFactory->autoDetect(QList<ToolChain*>());
|
|
|
|
|
for (auto tc: detected) {
|
|
|
|
|
if (tc->language() == language) {
|
|
|
|
|
toolChain = tc;
|
|
|
|
|
toolChain->setDetection(ToolChain::ManualDetection);
|
|
|
|
|
toolChain->setDisplayName("IAREW");
|
|
|
|
|
ToolChainManager::registerToolChain(toolChain);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return toolChain;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
ToolChain *McuToolChainPackage::toolChain(Id language) const
|
2020-02-26 16:41:52 +01:00
|
|
|
{
|
2020-09-17 11:05:28 +02:00
|
|
|
ToolChain *tc = nullptr;
|
2020-09-18 11:16:37 +02:00
|
|
|
if (m_type == TypeMSVC)
|
|
|
|
|
tc = msvcToolChain(language);
|
|
|
|
|
else if (m_type == TypeGCC)
|
|
|
|
|
tc = gccToolChain(language);
|
2020-11-13 14:00:18 +01:00
|
|
|
else if (m_type == TypeIAR) {
|
|
|
|
|
tc = iarToolChain(language);
|
|
|
|
|
}
|
2020-09-18 11:16:37 +02:00
|
|
|
else {
|
2020-04-07 18:19:32 +02:00
|
|
|
const QLatin1String compilerName(
|
|
|
|
|
language == ProjectExplorer::Constants::C_LANGUAGE_ID ? "gcc" : "g++");
|
2020-09-17 11:05:28 +02:00
|
|
|
const FilePath compiler = FilePath::fromUserInput(
|
|
|
|
|
HostOsInfo::withExecutableSuffix(
|
2020-04-07 18:19:32 +02:00
|
|
|
path() + (
|
|
|
|
|
m_type == TypeArmGcc
|
2020-11-13 14:00:18 +01:00
|
|
|
? "/bin/arm-none-eabi-%1" : "/bar/foo-keil-%1")).arg(compilerName));
|
2020-04-07 18:19:32 +02:00
|
|
|
|
|
|
|
|
tc = armGccToolChain(compiler, language);
|
|
|
|
|
}
|
2020-02-26 16:41:52 +01:00
|
|
|
return tc;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-13 14:00:18 +01:00
|
|
|
QString McuToolChainPackage::toolChainName() const
|
2020-02-26 16:41:52 +01:00
|
|
|
{
|
|
|
|
|
return QLatin1String(m_type == TypeArmGcc
|
2020-04-09 23:50:03 +02:00
|
|
|
? "armgcc" : m_type == McuToolChainPackage::TypeIAR
|
|
|
|
|
? "iar" : m_type == McuToolChainPackage::TypeKEIL
|
2020-11-13 14:00:18 +01:00
|
|
|
? "keil" : m_type == McuToolChainPackage::TypeGHS
|
|
|
|
|
? "ghs" : "unsupported");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString McuToolChainPackage::cmakeToolChainFileName() const
|
|
|
|
|
{
|
|
|
|
|
return toolChainName() + QLatin1String(".cmake");
|
2020-02-26 16:41:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QVariant McuToolChainPackage::debuggerId() const
|
|
|
|
|
{
|
|
|
|
|
using namespace Debugger;
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
const FilePath command = FilePath::fromUserInput(
|
|
|
|
|
HostOsInfo::withExecutableSuffix(path() + (
|
2020-02-26 16:41:52 +01:00
|
|
|
m_type == TypeArmGcc
|
|
|
|
|
? "/bin/arm-none-eabi-gdb-py" : m_type == TypeIAR
|
2020-11-13 14:00:18 +01:00
|
|
|
? "../common/bin/CSpyBat" : "/bar/foo-keil-gdb")));
|
2020-02-26 16:41:52 +01:00
|
|
|
const DebuggerItem *debugger = DebuggerItemManager::findByCommand(command);
|
|
|
|
|
QVariant debuggerId;
|
|
|
|
|
if (!debugger) {
|
|
|
|
|
DebuggerItem newDebugger;
|
|
|
|
|
newDebugger.setCommand(command);
|
2020-03-12 13:46:25 +01:00
|
|
|
const QString displayName = m_type == TypeArmGcc
|
|
|
|
|
? McuPackage::tr("Arm GDB at %1")
|
2020-11-13 14:00:18 +01:00
|
|
|
: m_type == TypeIAR ? QLatin1String("CSpy")
|
2020-03-12 13:46:25 +01:00
|
|
|
: QLatin1String("/bar/foo-keil-gdb");
|
2020-02-26 16:41:52 +01:00
|
|
|
newDebugger.setUnexpandedDisplayName(displayName.arg(command.toUserOutput()));
|
|
|
|
|
debuggerId = DebuggerItemManager::registerDebugger(newDebugger);
|
|
|
|
|
} else {
|
|
|
|
|
debuggerId = debugger->id();
|
|
|
|
|
}
|
|
|
|
|
return debuggerId;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-18 11:16:37 +02:00
|
|
|
McuTarget::McuTarget(const QVersionNumber &qulVersion,
|
|
|
|
|
const Platform &platform, OS os,
|
2020-04-23 23:30:40 +02:00
|
|
|
const QVector<McuPackage *> &packages,
|
|
|
|
|
const McuToolChainPackage *toolChainPackage)
|
2020-06-30 17:09:03 +02:00
|
|
|
: m_qulVersion(qulVersion)
|
2020-09-18 11:16:37 +02:00
|
|
|
, m_platform(platform)
|
2020-04-27 20:51:08 +02:00
|
|
|
, m_os(os)
|
2019-10-22 14:33:31 +02:00
|
|
|
, m_packages(packages)
|
2020-02-26 16:41:52 +01:00
|
|
|
, m_toolChainPackage(toolChainPackage)
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-20 13:32:10 +01:00
|
|
|
QVector<McuPackage *> McuTarget::packages() const
|
|
|
|
|
{
|
|
|
|
|
return m_packages;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-23 23:30:40 +02:00
|
|
|
const McuToolChainPackage *McuTarget::toolChainPackage() const
|
2019-11-20 13:32:10 +01:00
|
|
|
{
|
2020-02-26 16:41:52 +01:00
|
|
|
return m_toolChainPackage;
|
2019-10-22 14:33:31 +02:00
|
|
|
}
|
|
|
|
|
|
2020-04-27 20:51:08 +02:00
|
|
|
McuTarget::OS McuTarget::os() const
|
|
|
|
|
{
|
|
|
|
|
return m_os;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-18 11:16:37 +02:00
|
|
|
McuTarget::Platform McuTarget::platform() const
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
2020-09-18 11:16:37 +02:00
|
|
|
return m_platform;
|
2019-10-22 14:33:31 +02:00
|
|
|
}
|
|
|
|
|
|
2019-11-15 08:38:55 +01:00
|
|
|
bool McuTarget::isValid() const
|
2019-11-13 18:37:27 +01:00
|
|
|
{
|
2019-11-15 08:38:55 +01:00
|
|
|
return !Utils::anyOf(packages(), [](McuPackage *package) {
|
2020-12-04 16:32:34 +01:00
|
|
|
package->updateStatus();
|
2019-11-15 08:38:55 +01:00
|
|
|
return package->status() != McuPackage::ValidPackage;
|
2019-11-13 18:37:27 +01:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-04 16:32:34 +01:00
|
|
|
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(
|
|
|
|
|
McuSupportOptions::kitName(this),
|
|
|
|
|
package->label(),
|
|
|
|
|
package->statusText()),
|
|
|
|
|
true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-30 17:09:03 +02:00
|
|
|
QVersionNumber McuTarget::qulVersion() const
|
|
|
|
|
{
|
|
|
|
|
return m_qulVersion;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-21 01:22:28 +01:00
|
|
|
int McuTarget::colorDepth() const
|
|
|
|
|
{
|
|
|
|
|
return m_colorDepth;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void McuTarget::setColorDepth(int colorDepth)
|
|
|
|
|
{
|
|
|
|
|
m_colorDepth = colorDepth;
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-22 14:33:31 +02:00
|
|
|
McuSupportOptions::McuSupportOptions(QObject *parent)
|
|
|
|
|
: QObject(parent)
|
2020-03-12 14:25:49 +01:00
|
|
|
, qtForMCUsSdkPackage(Sdk::createQtForMCUsPackage())
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
2020-03-18 03:17:35 +01:00
|
|
|
connect(qtForMCUsSdkPackage, &McuPackage::changed,
|
|
|
|
|
this, &McuSupportOptions::populatePackagesAndTargets);
|
2019-10-22 14:33:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
McuSupportOptions::~McuSupportOptions()
|
2020-03-18 03:17:35 +01:00
|
|
|
{
|
|
|
|
|
deletePackagesAndTargets();
|
|
|
|
|
delete qtForMCUsSdkPackage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void McuSupportOptions::populatePackagesAndTargets()
|
|
|
|
|
{
|
2020-09-17 11:05:28 +02:00
|
|
|
setQulDir(FilePath::fromUserInput(qtForMCUsSdkPackage->path()));
|
2020-03-18 03:17:35 +01:00
|
|
|
}
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
static FilePath qulDocsDir()
|
2020-04-02 19:31:52 +02:00
|
|
|
{
|
2020-09-17 11:05:28 +02:00
|
|
|
const FilePath qulDir = McuSupportOptions::qulDirFromSettings();
|
2020-04-02 19:31:52 +02:00
|
|
|
if (qulDir.isEmpty() || !qulDir.exists())
|
|
|
|
|
return {};
|
2020-09-17 11:05:28 +02:00
|
|
|
const FilePath docsDir = qulDir.pathAppended("docs");
|
|
|
|
|
return docsDir.exists() ? docsDir : FilePath();
|
2020-04-02 19:31:52 +02:00
|
|
|
}
|
|
|
|
|
|
2020-03-24 18:58:29 +01:00
|
|
|
void McuSupportOptions::registerQchFiles()
|
|
|
|
|
{
|
2020-04-02 19:31:52 +02:00
|
|
|
const QString docsDir = qulDocsDir().toString();
|
|
|
|
|
if (docsDir.isEmpty())
|
2020-03-24 18:58:29 +01:00
|
|
|
return;
|
|
|
|
|
|
2020-12-04 08:47:55 +01:00
|
|
|
const QFileInfoList qchFiles = QDir(docsDir, "*.qch").entryInfoList();
|
2020-09-17 13:47:30 +02:00
|
|
|
Core::HelpManager::registerDocumentation(
|
2020-12-04 08:47:55 +01:00
|
|
|
Utils::transform<QStringList>(qchFiles, [](const QFileInfo &fi){
|
|
|
|
|
return fi.absoluteFilePath();
|
|
|
|
|
}));
|
2020-03-24 18:58:29 +01:00
|
|
|
}
|
|
|
|
|
|
2020-04-02 19:31:52 +02:00
|
|
|
void McuSupportOptions::registerExamples()
|
|
|
|
|
{
|
2020-09-17 11:05:28 +02:00
|
|
|
const FilePath docsDir = qulDocsDir();
|
2020-04-02 19:31:52 +02:00
|
|
|
if (docsDir.isEmpty())
|
|
|
|
|
return;
|
|
|
|
|
|
2021-02-09 17:06:24 +01:00
|
|
|
auto examples = {
|
|
|
|
|
std::make_pair(QStringLiteral("demos"), tr("Qt for MCUs Demos")),
|
|
|
|
|
std::make_pair(QStringLiteral("examples"), tr("Qt for MCUs Examples"))
|
|
|
|
|
};
|
|
|
|
|
for (const auto &dir : examples) {
|
|
|
|
|
const FilePath examplesDir =
|
|
|
|
|
McuSupportOptions::qulDirFromSettings().pathAppended(dir.first);
|
|
|
|
|
if (!examplesDir.exists())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
QtSupport::QtVersionManager::registerExampleSet(dir.second, docsDir.toString(),
|
|
|
|
|
examplesDir.toString());
|
|
|
|
|
}
|
2020-04-02 19:31:52 +02:00
|
|
|
}
|
|
|
|
|
|
2020-03-18 03:17:35 +01:00
|
|
|
void McuSupportOptions::deletePackagesAndTargets()
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
|
|
|
|
qDeleteAll(packages);
|
|
|
|
|
packages.clear();
|
2019-11-15 08:38:55 +01:00
|
|
|
qDeleteAll(mcuTargets);
|
|
|
|
|
mcuTargets.clear();
|
2019-10-22 14:33:31 +02:00
|
|
|
}
|
|
|
|
|
|
2020-06-30 17:09:03 +02:00
|
|
|
const QVersionNumber &McuSupportOptions::minimalQulVersion()
|
2020-03-25 15:09:02 +01:00
|
|
|
{
|
2020-06-29 23:27:16 +02:00
|
|
|
static const QVersionNumber v({1, 3});
|
2020-03-25 15:09:02 +01:00
|
|
|
return v;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
void McuSupportOptions::setQulDir(const FilePath &dir)
|
2020-03-18 03:17:35 +01:00
|
|
|
{
|
|
|
|
|
deletePackagesAndTargets();
|
2020-12-04 16:32:34 +01:00
|
|
|
qtForMCUsSdkPackage->updateStatus();
|
|
|
|
|
if (qtForMCUsSdkPackage->status() == McuPackage::Status::ValidPackage)
|
|
|
|
|
Sdk::targetsAndPackages(dir, &packages, &mcuTargets);
|
2021-02-09 17:27:02 +01:00
|
|
|
for (auto package : qAsConst(packages))
|
2020-09-17 11:05:28 +02:00
|
|
|
connect(package, &McuPackage::changed, this, &McuSupportOptions::changed);
|
|
|
|
|
|
2020-03-18 03:17:35 +01:00
|
|
|
emit changed();
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
FilePath McuSupportOptions::qulDirFromSettings()
|
2020-03-24 18:58:29 +01:00
|
|
|
{
|
2020-09-17 11:05:28 +02:00
|
|
|
return FilePath::fromUserInput(
|
2020-06-05 00:33:06 +02:00
|
|
|
packagePathFromSettings(Constants::SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK,
|
|
|
|
|
QSettings::UserScope));
|
2020-03-24 18:58:29 +01:00
|
|
|
}
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
static void setKitProperties(const QString &kitName, Kit *k, const McuTarget *mcuTarget)
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
2020-04-23 23:30:40 +02:00
|
|
|
using namespace Constants;
|
2019-10-22 14:33:31 +02:00
|
|
|
|
2019-11-12 10:39:18 +01:00
|
|
|
k->setUnexpandedDisplayName(kitName);
|
2020-09-18 11:16:37 +02:00
|
|
|
k->setValue(KIT_MCUTARGET_VENDOR_KEY, mcuTarget->platform().vendor);
|
|
|
|
|
k->setValue(KIT_MCUTARGET_MODEL_KEY, mcuTarget->platform().name);
|
2020-04-23 23:30:40 +02:00
|
|
|
k->setValue(KIT_MCUTARGET_COLORDEPTH_KEY, mcuTarget->colorDepth());
|
2020-06-30 17:09:03 +02:00
|
|
|
k->setValue(KIT_MCUTARGET_SDKVERSION_KEY, mcuTarget->qulVersion().toString());
|
2020-04-23 23:30:40 +02:00
|
|
|
k->setValue(KIT_MCUTARGET_KITVERSION_KEY, KIT_VERSION);
|
2020-04-27 20:51:08 +02:00
|
|
|
k->setValue(KIT_MCUTARGET_OS_KEY, static_cast<int>(mcuTarget->os()));
|
2020-12-07 10:46:13 +01:00
|
|
|
k->setValue(KIT_MCUTARGET_TOOCHAIN_KEY, mcuTarget->toolChainPackage()->toolChainName());
|
2019-11-13 18:37:27 +01:00
|
|
|
k->setAutoDetected(true);
|
|
|
|
|
k->makeSticky();
|
2020-09-18 11:16:37 +02:00
|
|
|
if (mcuTarget->toolChainPackage()->isDesktopToolchain())
|
2020-04-23 23:30:40 +02:00
|
|
|
k->setDeviceTypeForIcon(DEVICE_TYPE);
|
2021-02-09 17:27:02 +01:00
|
|
|
k->setValue(QtSupport::SuppliesQtQuickImportPath::id(), true);
|
|
|
|
|
QSet<Id> irrelevant = { SysRootKitAspect::id(), QtSupport::SuppliesQtQuickImportPath::id() };
|
2020-08-31 00:05:50 +02:00
|
|
|
if (!kitNeedsQtVersion())
|
|
|
|
|
irrelevant.insert(QtSupport::QtKitAspect::id());
|
2020-04-07 18:19:32 +02:00
|
|
|
k->setIrrelevantAspects(irrelevant);
|
2019-10-22 14:33:31 +02:00
|
|
|
}
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
static void setKitToolchains(Kit *k, const McuToolChainPackage *tcPackage)
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
2020-04-09 23:50:03 +02:00
|
|
|
// No Green Hills toolchain, because support for it is missing.
|
2020-11-13 14:00:18 +01:00
|
|
|
if (tcPackage->type() == McuToolChainPackage::TypeUnsupported
|
|
|
|
|
|| tcPackage->type() == McuToolChainPackage::TypeGHS)
|
2020-04-09 23:50:03 +02:00
|
|
|
return;
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
ToolChainKitAspect::setToolChain(k, tcPackage->toolChain(
|
|
|
|
|
ProjectExplorer::Constants::C_LANGUAGE_ID));
|
|
|
|
|
ToolChainKitAspect::setToolChain(k, tcPackage->toolChain(
|
|
|
|
|
ProjectExplorer::Constants::CXX_LANGUAGE_ID));
|
2019-10-22 14:33:31 +02:00
|
|
|
}
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
static void setKitDebugger(Kit *k, const McuToolChainPackage *tcPackage)
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
2020-04-07 18:19:32 +02:00
|
|
|
// Qt Creator seems to be smart enough to deduce the right Kit debugger from the ToolChain
|
2020-04-09 23:50:03 +02:00
|
|
|
// We rely on that at least in the Desktop case.
|
2020-09-18 11:16:37 +02:00
|
|
|
if (tcPackage->isDesktopToolchain()
|
2020-11-13 14:00:18 +01:00
|
|
|
// No Green Hills and IAR debugger, because support for it is missing.
|
|
|
|
|
|| tcPackage->type() == McuToolChainPackage::TypeUnsupported
|
|
|
|
|
|| tcPackage->type() == McuToolChainPackage::TypeGHS
|
|
|
|
|
|| tcPackage->type() == McuToolChainPackage::TypeIAR)
|
2020-04-07 18:19:32 +02:00
|
|
|
return;
|
|
|
|
|
|
2020-02-26 16:41:52 +01:00
|
|
|
Debugger::DebuggerKitAspect::setDebugger(k, tcPackage->debuggerId());
|
2019-10-22 14:33:31 +02:00
|
|
|
}
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
static void setKitDevice(Kit *k, const McuTarget* mcuTarget)
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
2020-04-07 18:19:32 +02:00
|
|
|
// "Device Type" Desktop is the default. We use that for the Qt for MCUs Desktop Kit
|
2020-09-18 11:16:37 +02:00
|
|
|
if (mcuTarget->toolChainPackage()->isDesktopToolchain())
|
2020-04-07 18:19:32 +02:00
|
|
|
return;
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DEVICE_TYPE);
|
2019-10-22 14:33:31 +02:00
|
|
|
}
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
static void setKitEnvironment(Kit *k, const McuTarget *mcuTarget,
|
2020-04-23 23:30:40 +02:00
|
|
|
const McuPackage *qtForMCUsSdkPackage)
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
2020-09-17 11:05:28 +02:00
|
|
|
EnvironmentItems changes;
|
2019-10-22 14:33:31 +02:00
|
|
|
QStringList pathAdditions;
|
2020-03-04 19:59:50 +01:00
|
|
|
|
2020-04-07 18:19:32 +02:00
|
|
|
// The Desktop version depends on the Qt shared libs in Qul_DIR/bin.
|
|
|
|
|
// If CMake's fileApi is avaialble, we can rely on the "Add library search path to PATH"
|
|
|
|
|
// feature of the run configuration. Otherwise, we just prepend the path, here.
|
2020-09-18 11:16:37 +02:00
|
|
|
if (mcuTarget->toolChainPackage()->isDesktopToolchain()
|
2020-04-07 18:19:32 +02:00
|
|
|
&& !CMakeProjectManager::CMakeToolManager::defaultCMakeTool()->hasFileApi())
|
|
|
|
|
pathAdditions.append(QDir::toNativeSeparators(qtForMCUsSdkPackage->path() + "/bin"));
|
|
|
|
|
|
2020-04-23 23:30:40 +02:00
|
|
|
auto processPackage = [&pathAdditions, &changes](const McuPackage *package) {
|
2019-10-22 14:33:31 +02:00
|
|
|
if (package->addToPath())
|
|
|
|
|
pathAdditions.append(QDir::toNativeSeparators(package->path()));
|
|
|
|
|
if (!package->environmentVariableName().isEmpty())
|
|
|
|
|
changes.append({package->environmentVariableName(),
|
|
|
|
|
QDir::toNativeSeparators(package->path())});
|
2020-04-23 23:30:40 +02:00
|
|
|
};
|
|
|
|
|
for (auto package : mcuTarget->packages())
|
|
|
|
|
processPackage(package);
|
|
|
|
|
processPackage(qtForMCUsSdkPackage);
|
|
|
|
|
|
2021-01-26 12:08:52 +01:00
|
|
|
// Clang not needed in version 1.7+
|
|
|
|
|
if (mcuTarget->qulVersion() < QVersionNumber{1,7}) {
|
2021-02-02 12:20:00 +01:00
|
|
|
const QString path = QLatin1String(HostOsInfo::isWindowsHost() ? "Path" : "PATH");
|
2021-01-26 12:08:52 +01:00
|
|
|
pathAdditions.append("${" + path + "}");
|
|
|
|
|
pathAdditions.append(QDir::toNativeSeparators(Core::ICore::libexecPath() + "/clang/bin"));
|
|
|
|
|
changes.append({path, pathAdditions.join(HostOsInfo::pathListSeparator())});
|
|
|
|
|
}
|
2020-08-31 00:05:50 +02:00
|
|
|
|
|
|
|
|
if (kitNeedsQtVersion())
|
|
|
|
|
changes.append({QLatin1String("LD_LIBRARY_PATH"), "%{Qt:QT_INSTALL_LIBS}"});
|
|
|
|
|
|
2019-10-22 14:33:31 +02:00
|
|
|
EnvironmentKitAspect::setEnvironmentChanges(k, changes);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
static void setKitCMakeOptions(Kit *k, const McuTarget* mcuTarget, const QString &qulDir)
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
|
|
|
|
using namespace CMakeProjectManager;
|
|
|
|
|
|
|
|
|
|
CMakeConfig config = CMakeConfigurationKitAspect::configuration(k);
|
2020-04-09 23:50:03 +02:00
|
|
|
// CMake ToolChain file for ghs handles CMAKE_*_COMPILER autonomously
|
|
|
|
|
if (mcuTarget->toolChainPackage()->type() != McuToolChainPackage::TypeGHS) {
|
|
|
|
|
config.append(CMakeConfigItem("CMAKE_CXX_COMPILER", "%{Compiler:Executable:Cxx}"));
|
|
|
|
|
config.append(CMakeConfigItem("CMAKE_C_COMPILER", "%{Compiler:Executable:C}"));
|
|
|
|
|
}
|
2020-12-04 16:32:34 +01:00
|
|
|
|
|
|
|
|
if (!mcuTarget->toolChainPackage()->isDesktopToolchain()) {
|
|
|
|
|
const FilePath cMakeToolchainFile = FilePath::fromString(qulDir + "/lib/cmake/Qul/toolchain/"
|
|
|
|
|
+ mcuTarget->toolChainPackage()->cmakeToolChainFileName());
|
|
|
|
|
|
2020-02-26 16:41:52 +01:00
|
|
|
config.append(CMakeConfigItem(
|
|
|
|
|
"CMAKE_TOOLCHAIN_FILE",
|
2020-12-04 16:32:34 +01:00
|
|
|
cMakeToolchainFile.toString().toUtf8()));
|
|
|
|
|
if (!cMakeToolchainFile.exists()) {
|
|
|
|
|
printMessage(McuTarget::tr("Warning for target %1: missing CMake Toolchain File expected at %2.")
|
|
|
|
|
.arg(McuSupportOptions::kitName(mcuTarget), cMakeToolchainFile.toUserOutput()), false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const FilePath generatorsPath = FilePath::fromString(qulDir + "/lib/cmake/Qul/QulGenerators.cmake");
|
2020-02-06 00:17:04 +01:00
|
|
|
config.append(CMakeConfigItem("QUL_GENERATORS",
|
2020-12-04 16:32:34 +01:00
|
|
|
generatorsPath.toString().toUtf8()));
|
|
|
|
|
if (!generatorsPath.exists()) {
|
|
|
|
|
printMessage(McuTarget::tr("Warning for target %1: missing QulGenerators expected at %2.")
|
|
|
|
|
.arg(McuSupportOptions::kitName(mcuTarget), generatorsPath.toUserOutput()), false);
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-06 00:17:04 +01:00
|
|
|
config.append(CMakeConfigItem("QUL_PLATFORM",
|
2020-09-18 11:16:37 +02:00
|
|
|
mcuTarget->platform().name.toUtf8()));
|
2020-08-13 13:10:52 +02:00
|
|
|
|
|
|
|
|
if (mcuTarget->qulVersion() <= QVersionNumber{1,3} // OS variable was removed in Qul 1.4
|
|
|
|
|
&& mcuTarget->os() == McuTarget::OS::FreeRTOS)
|
2020-04-27 20:51:08 +02:00
|
|
|
config.append(CMakeConfigItem("OS", "FreeRTOS"));
|
2019-11-21 01:22:28 +01:00
|
|
|
if (mcuTarget->colorDepth() >= 0)
|
|
|
|
|
config.append(CMakeConfigItem("QUL_COLOR_DEPTH",
|
|
|
|
|
QString::number(mcuTarget->colorDepth()).toLatin1()));
|
2020-08-31 00:05:50 +02:00
|
|
|
if (kitNeedsQtVersion())
|
|
|
|
|
config.append(CMakeConfigItem("CMAKE_PREFIX_PATH", "%{Qt:QT_INSTALL_PREFIX}"));
|
2019-12-06 17:58:38 +01:00
|
|
|
CMakeConfigurationKitAspect::setConfiguration(k, config);
|
2019-10-22 14:33:31 +02:00
|
|
|
}
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
static void setKitQtVersionOptions(Kit *k)
|
2020-04-07 18:19:32 +02:00
|
|
|
{
|
2020-08-31 00:05:50 +02:00
|
|
|
if (!kitNeedsQtVersion())
|
|
|
|
|
QtSupport::QtKitAspect::setQtVersion(k, nullptr);
|
|
|
|
|
// else: auto-select a Qt version
|
2020-04-07 18:19:32 +02:00
|
|
|
}
|
|
|
|
|
|
2020-04-23 23:30:40 +02:00
|
|
|
QString McuSupportOptions::kitName(const McuTarget *mcuTarget)
|
2019-11-12 15:14:20 +01:00
|
|
|
{
|
2020-08-13 13:10:52 +02:00
|
|
|
QString os;
|
2020-09-18 11:16:37 +02:00
|
|
|
if (mcuTarget->qulVersion() <= QVersionNumber{1,3} && mcuTarget->os() == McuTarget::OS::FreeRTOS)
|
2020-08-13 13:10:52 +02:00
|
|
|
// Starting from Qul 1.4 each OS is a separate platform
|
|
|
|
|
os = QLatin1String(" FreeRTOS");
|
|
|
|
|
|
2020-11-13 14:00:18 +01:00
|
|
|
const McuToolChainPackage *tcPkg = mcuTarget->toolChainPackage();
|
|
|
|
|
const QString compilerName = tcPkg && !tcPkg->isDesktopToolchain()
|
|
|
|
|
? QString::fromLatin1(" (%1)").arg(tcPkg->toolChainName().toUpper())
|
|
|
|
|
: "";
|
2019-11-21 01:22:28 +01:00
|
|
|
const QString colorDepth = mcuTarget->colorDepth() > 0
|
|
|
|
|
? QString::fromLatin1(" %1bpp").arg(mcuTarget->colorDepth())
|
|
|
|
|
: "";
|
2020-09-18 11:16:37 +02:00
|
|
|
const QString targetName = mcuTarget->platform().displayName.isEmpty()
|
|
|
|
|
? mcuTarget->platform().name
|
|
|
|
|
: mcuTarget->platform().displayName;
|
2020-11-13 14:00:18 +01:00
|
|
|
return QString::fromLatin1("Qt for MCUs %1.%2 - %3%4%5%6")
|
2020-08-13 13:10:52 +02:00
|
|
|
.arg(QString::number(mcuTarget->qulVersion().majorVersion()),
|
|
|
|
|
QString::number(mcuTarget->qulVersion().minorVersion()),
|
|
|
|
|
targetName,
|
|
|
|
|
os,
|
2020-11-13 14:00:18 +01:00
|
|
|
colorDepth,
|
|
|
|
|
compilerName);
|
2019-11-12 15:14:20 +01:00
|
|
|
}
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
QList<Kit *> McuSupportOptions::existingKits(const McuTarget *mcuTarget)
|
2019-10-22 14:33:31 +02:00
|
|
|
{
|
2020-04-23 23:30:40 +02:00
|
|
|
using namespace Constants;
|
|
|
|
|
return Utils::filtered(KitManager::kits(), [mcuTarget](Kit *kit) {
|
|
|
|
|
return kit->isAutoDetected()
|
|
|
|
|
&& kit->value(KIT_MCUTARGET_KITVERSION_KEY) == KIT_VERSION
|
|
|
|
|
&& (!mcuTarget || (
|
2020-09-18 11:16:37 +02:00
|
|
|
kit->value(KIT_MCUTARGET_VENDOR_KEY) == mcuTarget->platform().vendor
|
|
|
|
|
&& kit->value(KIT_MCUTARGET_MODEL_KEY) == mcuTarget->platform().name
|
2020-04-23 23:30:40 +02:00
|
|
|
&& kit->value(KIT_MCUTARGET_COLORDEPTH_KEY) == mcuTarget->colorDepth()
|
2020-04-27 20:51:08 +02:00
|
|
|
&& kit->value(KIT_MCUTARGET_OS_KEY).toInt()
|
|
|
|
|
== static_cast<int>(mcuTarget->os())
|
2020-12-07 10:46:13 +01:00
|
|
|
&& kit->value(KIT_MCUTARGET_TOOCHAIN_KEY)
|
|
|
|
|
== mcuTarget->toolChainPackage()->toolChainName()
|
2020-04-23 23:30:40 +02:00
|
|
|
));
|
2019-10-22 14:33:31 +02:00
|
|
|
});
|
2019-11-13 18:37:27 +01:00
|
|
|
}
|
2019-10-22 14:33:31 +02:00
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
QList<Kit *> McuSupportOptions::outdatedKits()
|
2020-04-22 23:24:54 +02:00
|
|
|
{
|
2020-09-17 11:05:28 +02:00
|
|
|
return Utils::filtered(KitManager::kits(), [](Kit *kit) {
|
2020-04-22 23:24:54 +02:00
|
|
|
return kit->isAutoDetected()
|
|
|
|
|
&& !kit->value(Constants::KIT_MCUTARGET_VENDOR_KEY).isNull()
|
|
|
|
|
&& kit->value(Constants::KIT_MCUTARGET_KITVERSION_KEY) != KIT_VERSION;
|
2019-10-22 14:33:31 +02:00
|
|
|
});
|
2019-11-13 18:37:27 +01:00
|
|
|
}
|
2019-10-22 14:33:31 +02:00
|
|
|
|
2020-04-22 23:24:54 +02:00
|
|
|
void McuSupportOptions::removeOutdatedKits()
|
|
|
|
|
{
|
|
|
|
|
for (auto kit : McuSupportOptions::outdatedKits())
|
2020-09-17 11:05:28 +02:00
|
|
|
KitManager::deregisterKit(kit);
|
2020-04-22 23:24:54 +02:00
|
|
|
}
|
|
|
|
|
|
2020-09-17 11:05:28 +02:00
|
|
|
Kit *McuSupportOptions::newKit(const McuTarget *mcuTarget, const McuPackage *qtForMCUsSdk)
|
2019-11-13 18:37:27 +01:00
|
|
|
{
|
2020-04-23 23:30:40 +02:00
|
|
|
const auto init = [mcuTarget, qtForMCUsSdk](Kit *k) {
|
2019-11-13 18:37:27 +01:00
|
|
|
KitGuard kitGuard(k);
|
|
|
|
|
|
2019-11-15 08:38:55 +01:00
|
|
|
setKitProperties(kitName(mcuTarget), k, mcuTarget);
|
2020-04-07 18:19:32 +02:00
|
|
|
setKitDevice(k, mcuTarget);
|
|
|
|
|
setKitToolchains(k, mcuTarget->toolChainPackage());
|
|
|
|
|
setKitDebugger(k, mcuTarget->toolChainPackage());
|
2020-04-23 23:30:40 +02:00
|
|
|
setKitEnvironment(k, mcuTarget, qtForMCUsSdk);
|
|
|
|
|
setKitCMakeOptions(k, mcuTarget, qtForMCUsSdk->path());
|
2020-04-07 18:19:32 +02:00
|
|
|
setKitQtVersionOptions(k);
|
2019-11-13 18:37:27 +01:00
|
|
|
|
|
|
|
|
k->setup();
|
|
|
|
|
k->fix();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return KitManager::registerKit(init);
|
2019-10-22 14:33:31 +02:00
|
|
|
}
|
|
|
|
|
|
2020-12-04 16:32:34 +01:00
|
|
|
void printMessage(const QString &message, bool important)
|
2020-10-16 15:10:17 +02:00
|
|
|
{
|
2020-12-04 16:32:34 +01:00
|
|
|
const QString displayMessage = QCoreApplication::translate("QtForMCUs", "Qt for MCUs: %1").arg(message);
|
|
|
|
|
if (important)
|
|
|
|
|
Core::MessageManager::writeFlashing(displayMessage);
|
|
|
|
|
else
|
|
|
|
|
Core::MessageManager::writeSilently(displayMessage);
|
|
|
|
|
}
|
2020-10-16 15:10:17 +02:00
|
|
|
|
2020-12-04 16:32:34 +01:00
|
|
|
void McuSupportOptions::createAutomaticKits()
|
|
|
|
|
{
|
2020-10-16 15:10:17 +02:00
|
|
|
auto qtForMCUsPackage = Sdk::createQtForMCUsPackage();
|
|
|
|
|
|
2020-12-04 16:32:34 +01:00
|
|
|
const auto createKits = [qtForMCUsPackage]() {
|
2020-10-16 15:10:17 +02:00
|
|
|
if (qtForMCUsPackage->automaticKitCreationEnabled()) {
|
2020-12-04 16:32:34 +01:00
|
|
|
qtForMCUsPackage->updateStatus();
|
|
|
|
|
if (qtForMCUsPackage->status() != McuPackage::ValidPackage) {
|
|
|
|
|
switch (qtForMCUsPackage->status()) {
|
|
|
|
|
case McuPackage::ValidPathInvalidPackage: {
|
|
|
|
|
const QString displayPath = FilePath::fromString(qtForMCUsPackage->detectionPath())
|
|
|
|
|
.toUserOutput();
|
|
|
|
|
printMessage(tr("Path %1 exists, but does not contain %2.")
|
|
|
|
|
.arg(qtForMCUsPackage->path(), displayPath),
|
|
|
|
|
true);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case McuPackage::InvalidPath: {
|
|
|
|
|
printMessage(tr("Path %1 does not exist. Add the path in Tools > Options > Devices > MCU.")
|
|
|
|
|
.arg(qtForMCUsPackage->path()),
|
|
|
|
|
true);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case McuPackage::EmptyPath: {
|
|
|
|
|
printMessage(tr("Missing %1. Add the path in Tools > Options > Devices > MCU.")
|
|
|
|
|
.arg(qtForMCUsPackage->detectionPath()),
|
|
|
|
|
true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (CMakeProjectManager::CMakeToolManager::cmakeTools().isEmpty()) {
|
|
|
|
|
printMessage(tr("No CMake tool was detected. Add a CMake tool in Tools > Options > Kits > CMake."),
|
|
|
|
|
true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-16 15:10:17 +02:00
|
|
|
auto dir = FilePath::fromUserInput(qtForMCUsPackage->path());
|
|
|
|
|
QVector<McuPackage*> packages;
|
|
|
|
|
QVector<McuTarget*> mcuTargets;
|
|
|
|
|
Sdk::targetsAndPackages(dir, &packages, &mcuTargets);
|
|
|
|
|
|
|
|
|
|
for (auto target: qAsConst(mcuTargets))
|
2020-12-04 16:32:34 +01:00
|
|
|
if (existingKits(target).isEmpty()) {
|
|
|
|
|
if (target->isValid())
|
|
|
|
|
newKit(target, qtForMCUsPackage);
|
|
|
|
|
else
|
|
|
|
|
target->printPackageProblems();
|
|
|
|
|
}
|
2020-10-16 15:10:17 +02:00
|
|
|
|
|
|
|
|
qDeleteAll(packages);
|
|
|
|
|
qDeleteAll(mcuTargets);
|
|
|
|
|
}
|
2020-12-04 16:32:34 +01:00
|
|
|
};
|
2020-10-16 15:10:17 +02:00
|
|
|
|
2020-12-04 16:32:34 +01:00
|
|
|
createKits();
|
2020-10-16 15:10:17 +02:00
|
|
|
delete qtForMCUsPackage;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-09 17:27:02 +01:00
|
|
|
/**
|
|
|
|
|
* @brief Fix/update existing kits if needed
|
|
|
|
|
*/
|
|
|
|
|
void McuSupportOptions::fixExistingKits()
|
|
|
|
|
{
|
|
|
|
|
for (Kit *kit : KitManager::kits()) {
|
|
|
|
|
if (!kit->hasValue(Constants::KIT_MCUTARGET_KITVERSION_KEY) )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// Check if the MCU kits are flagged as supplying a QtQuick import path, in order
|
|
|
|
|
// to tell the QMLJS code-model that it won't need to add a fall-back import
|
|
|
|
|
// path.
|
|
|
|
|
const auto bringsQtQuickImportPath = QtSupport::SuppliesQtQuickImportPath::id();
|
|
|
|
|
auto irrelevantAspects = kit->irrelevantAspects();
|
|
|
|
|
if (!irrelevantAspects.contains(bringsQtQuickImportPath)) {
|
|
|
|
|
irrelevantAspects.insert(bringsQtQuickImportPath);
|
|
|
|
|
kit->setIrrelevantAspects(irrelevantAspects);
|
|
|
|
|
}
|
|
|
|
|
if (!kit->hasValue(bringsQtQuickImportPath)) {
|
|
|
|
|
kit->setValue(bringsQtQuickImportPath, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-22 14:33:31 +02:00
|
|
|
} // Internal
|
|
|
|
|
} // McuSupport
|