2020-03-12 14:25:49 +01:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
2020-07-02 16:04:31 +02:00
|
|
|
** Copyright (C) 2020 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2020-03-12 14:25:49 +01: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"
|
|
|
|
|
#include "mcusupportsdk.h"
|
2021-02-15 16:20:38 +01:00
|
|
|
#include "mcusupportversiondetection.h"
|
2020-03-12 14:25:49 +01:00
|
|
|
|
2020-11-13 14:00:18 +01:00
|
|
|
#include <baremetal/baremetalconstants.h>
|
|
|
|
|
#include <projectexplorer/toolchain.h>
|
|
|
|
|
#include <projectexplorer/toolchainmanager.h>
|
2020-05-07 12:38:28 +02:00
|
|
|
#include <utils/algorithm.h>
|
2020-03-12 14:25:49 +01:00
|
|
|
#include <utils/hostosinfo.h>
|
|
|
|
|
#include <utils/fileutils.h>
|
|
|
|
|
|
|
|
|
|
#include <QDir>
|
2020-05-07 12:38:28 +02:00
|
|
|
#include <QDirIterator>
|
|
|
|
|
#include <QHash>
|
|
|
|
|
#include <QJsonArray>
|
|
|
|
|
#include <QJsonDocument>
|
|
|
|
|
#include <QJsonObject>
|
|
|
|
|
#include <QVariant>
|
2020-03-12 14:25:49 +01:00
|
|
|
|
2021-08-11 08:28:29 +02:00
|
|
|
using namespace Utils;
|
|
|
|
|
|
2020-03-12 14:25:49 +01:00
|
|
|
namespace McuSupport {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
namespace Sdk {
|
|
|
|
|
|
2021-09-30 18:30:02 +02:00
|
|
|
static FilePath findInProgramFiles(const QString &folder)
|
2020-03-12 14:25:49 +01:00
|
|
|
{
|
|
|
|
|
for (auto envVar : {"ProgramFiles", "ProgramFiles(x86)", "ProgramW6432"}) {
|
|
|
|
|
if (!qEnvironmentVariableIsSet(envVar))
|
|
|
|
|
continue;
|
2021-09-30 18:30:02 +02:00
|
|
|
const FilePath dir = FilePath::fromUserInput(qEnvironmentVariable(envVar)) / folder;
|
2020-03-12 14:25:49 +01:00
|
|
|
if (dir.exists())
|
2021-09-30 18:30:02 +02:00
|
|
|
return dir;
|
2020-03-12 14:25:49 +01:00
|
|
|
}
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
McuPackage *createQtForMCUsPackage()
|
|
|
|
|
{
|
|
|
|
|
auto result = new McuPackage(
|
2021-03-01 11:07:44 +01:00
|
|
|
McuPackage::tr("Qt for MCUs SDK"),
|
2021-09-30 18:30:02 +02:00
|
|
|
FileUtils::homePath(),
|
2021-08-11 08:28:29 +02:00
|
|
|
FilePath("bin/qmltocpp").withExecutableSuffix().toString(),
|
2020-03-24 18:58:29 +01:00
|
|
|
Constants::SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK);
|
2020-03-12 14:25:49 +01:00
|
|
|
result->setEnvironmentVariableName("Qul_DIR");
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-18 11:16:37 +02:00
|
|
|
static McuToolChainPackage *createMsvcToolChainPackage()
|
2020-04-07 18:19:32 +02:00
|
|
|
{
|
2020-09-18 11:16:37 +02:00
|
|
|
return new McuToolChainPackage({}, {}, {}, {}, McuToolChainPackage::TypeMSVC);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static McuToolChainPackage *createGccToolChainPackage()
|
|
|
|
|
{
|
|
|
|
|
return new McuToolChainPackage({}, {}, {}, {}, McuToolChainPackage::TypeGCC);
|
2020-04-07 18:19:32 +02:00
|
|
|
}
|
|
|
|
|
|
2020-11-13 14:00:18 +01:00
|
|
|
static McuToolChainPackage *createUnsupportedToolChainPackage()
|
|
|
|
|
{
|
|
|
|
|
return new McuToolChainPackage({}, {}, {}, {}, McuToolChainPackage::TypeUnsupported);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-12 14:25:49 +01:00
|
|
|
static McuToolChainPackage *createArmGccPackage()
|
|
|
|
|
{
|
|
|
|
|
const char envVar[] = "ARMGCC_DIR";
|
|
|
|
|
|
2021-09-30 18:30:02 +02:00
|
|
|
FilePath defaultPath;
|
2020-03-12 14:25:49 +01:00
|
|
|
if (qEnvironmentVariableIsSet(envVar))
|
2021-09-30 18:30:02 +02:00
|
|
|
defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar));
|
|
|
|
|
if (defaultPath.isEmpty() && HostOsInfo::isWindowsHost()) {
|
|
|
|
|
const FilePath installDir = findInProgramFiles("GNU Tools ARM Embedded");
|
2020-03-12 14:25:49 +01:00
|
|
|
if (installDir.exists()) {
|
|
|
|
|
// If GNU Tools installation dir has only one sub dir,
|
|
|
|
|
// select the sub dir, otherwise the installation dir.
|
2021-09-30 18:30:02 +02:00
|
|
|
const FilePaths subDirs = installDir.dirEntries(QDir::Dirs | QDir::NoDotAndDotDot);
|
2020-03-12 14:25:49 +01:00
|
|
|
if (subDirs.count() == 1)
|
2021-09-30 18:30:02 +02:00
|
|
|
defaultPath = subDirs.first();
|
2020-03-12 14:25:49 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-15 16:20:38 +01:00
|
|
|
const QString detectionPath = Utils::HostOsInfo::withExecutableSuffix("bin/arm-none-eabi-g++");
|
|
|
|
|
const auto versionDetector = new McuPackageExecutableVersionDetector(
|
|
|
|
|
detectionPath,
|
|
|
|
|
{ "--version" },
|
|
|
|
|
"\\b(\\d+\\.\\d+\\.\\d+)\\b"
|
|
|
|
|
);
|
|
|
|
|
|
2020-03-12 14:25:49 +01:00
|
|
|
auto result = new McuToolChainPackage(
|
|
|
|
|
McuPackage::tr("GNU Arm Embedded Toolchain"),
|
|
|
|
|
defaultPath,
|
2021-02-15 16:20:38 +01:00
|
|
|
detectionPath,
|
2020-03-12 14:25:49 +01:00
|
|
|
"GNUArmEmbeddedToolchain",
|
2021-02-15 16:20:38 +01:00
|
|
|
McuToolChainPackage::TypeArmGcc,
|
|
|
|
|
versionDetector);
|
2020-03-12 14:25:49 +01:00
|
|
|
result->setEnvironmentVariableName(envVar);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-09 23:50:03 +02:00
|
|
|
static McuToolChainPackage *createGhsToolchainPackage()
|
|
|
|
|
{
|
|
|
|
|
const char envVar[] = "GHS_COMPILER_DIR";
|
|
|
|
|
|
2021-11-23 16:20:52 +01:00
|
|
|
const FilePath defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar));
|
2020-04-09 23:50:03 +02:00
|
|
|
|
2021-02-15 16:20:38 +01:00
|
|
|
const auto versionDetector = new McuPackageExecutableVersionDetector(
|
|
|
|
|
Utils::HostOsInfo::withExecutableSuffix("as850"),
|
|
|
|
|
{"-V"},
|
|
|
|
|
"\\bv(\\d+\\.\\d+\\.\\d+)\\b"
|
|
|
|
|
);
|
|
|
|
|
|
2020-04-09 23:50:03 +02:00
|
|
|
auto result = new McuToolChainPackage(
|
|
|
|
|
"Green Hills Compiler",
|
|
|
|
|
defaultPath,
|
|
|
|
|
Utils::HostOsInfo::withExecutableSuffix("ccv850"),
|
|
|
|
|
"GHSToolchain",
|
2021-02-15 16:20:38 +01:00
|
|
|
McuToolChainPackage::TypeGHS,
|
|
|
|
|
versionDetector);
|
2020-04-09 23:50:03 +02:00
|
|
|
result->setEnvironmentVariableName(envVar);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-10 11:35:46 +02:00
|
|
|
static McuToolChainPackage *createGhsArmToolchainPackage()
|
|
|
|
|
{
|
|
|
|
|
const char envVar[] = "GHS_ARM_COMPILER_DIR";
|
|
|
|
|
|
2021-11-23 16:20:52 +01:00
|
|
|
const FilePath defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar));
|
2021-05-10 11:35:46 +02:00
|
|
|
|
|
|
|
|
const auto versionDetector = new McuPackageExecutableVersionDetector(
|
|
|
|
|
Utils::HostOsInfo::withExecutableSuffix("asarm"),
|
|
|
|
|
{"-V"},
|
|
|
|
|
"\\bv(\\d+\\.\\d+\\.\\d+)\\b"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
auto result = new McuToolChainPackage(
|
|
|
|
|
"Green Hills Compiler for ARM",
|
|
|
|
|
defaultPath,
|
|
|
|
|
Utils::HostOsInfo::withExecutableSuffix("cxarm"),
|
|
|
|
|
"GHSArmToolchain",
|
|
|
|
|
McuToolChainPackage::TypeGHSArm,
|
|
|
|
|
versionDetector);
|
|
|
|
|
result->setEnvironmentVariableName(envVar);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-13 14:00:18 +01:00
|
|
|
static McuToolChainPackage *createIarToolChainPackage()
|
|
|
|
|
{
|
|
|
|
|
const char envVar[] = "IAR_ARM_COMPILER_DIR";
|
|
|
|
|
|
2021-09-30 18:30:02 +02:00
|
|
|
FilePath defaultPath;
|
2020-11-13 14:00:18 +01:00
|
|
|
if (qEnvironmentVariableIsSet(envVar))
|
2021-09-30 18:30:02 +02:00
|
|
|
defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar));
|
2020-11-13 14:00:18 +01:00
|
|
|
else {
|
|
|
|
|
const ProjectExplorer::ToolChain *tc =
|
|
|
|
|
ProjectExplorer::ToolChainManager::toolChain([](const ProjectExplorer::ToolChain *t) {
|
|
|
|
|
return t->typeId() == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID;
|
|
|
|
|
});
|
|
|
|
|
if (tc) {
|
2021-09-30 18:30:02 +02:00
|
|
|
const FilePath compilerExecPath = tc->compilerCommand();
|
|
|
|
|
defaultPath = compilerExecPath.parentDir().parentDir();
|
2020-11-13 14:00:18 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-15 16:20:38 +01:00
|
|
|
const QString detectionPath = Utils::HostOsInfo::withExecutableSuffix("bin/iccarm");
|
|
|
|
|
const auto versionDetector = new McuPackageExecutableVersionDetector(
|
|
|
|
|
detectionPath,
|
|
|
|
|
{"--version"},
|
|
|
|
|
"\\bV(\\d+\\.\\d+\\.\\d+)\\.\\d+\\b"
|
|
|
|
|
);
|
|
|
|
|
|
2020-11-13 14:00:18 +01:00
|
|
|
auto result = new McuToolChainPackage(
|
|
|
|
|
"IAR ARM Compiler",
|
|
|
|
|
defaultPath,
|
2021-02-15 16:20:38 +01:00
|
|
|
detectionPath,
|
2020-11-13 14:00:18 +01:00
|
|
|
"IARToolchain",
|
2021-02-15 16:20:38 +01:00
|
|
|
McuToolChainPackage::TypeIAR,
|
|
|
|
|
versionDetector);
|
2020-11-13 14:00:18 +01:00
|
|
|
result->setEnvironmentVariableName(envVar);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-09 23:50:03 +02:00
|
|
|
static McuPackage *createRGLPackage()
|
|
|
|
|
{
|
|
|
|
|
const char envVar[] = "RGL_DIR";
|
|
|
|
|
|
2021-09-30 18:30:02 +02:00
|
|
|
FilePath defaultPath;
|
2020-04-09 23:50:03 +02:00
|
|
|
if (qEnvironmentVariableIsSet(envVar)) {
|
2021-09-30 18:30:02 +02:00
|
|
|
defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar));
|
2020-04-09 23:50:03 +02:00
|
|
|
} else if (Utils::HostOsInfo::isWindowsHost()) {
|
2021-11-23 16:20:52 +01:00
|
|
|
const FilePath rglPath = FilePath::fromString(QDir::rootPath()) / "Renesas_Electronics/D1x_RGL";
|
|
|
|
|
if (rglPath.exists()) {
|
|
|
|
|
defaultPath = rglPath;
|
2021-09-30 18:30:02 +02:00
|
|
|
const FilePaths subDirs =
|
|
|
|
|
defaultPath.dirEntries({QLatin1String("rgl_ghs_D1Mx_*")},
|
2020-04-09 23:50:03 +02:00
|
|
|
QDir::Dirs | QDir::NoDotAndDotDot);
|
|
|
|
|
if (subDirs.count() == 1)
|
2021-09-30 18:30:02 +02:00
|
|
|
defaultPath = subDirs.first();
|
2020-04-09 23:50:03 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto result = new McuPackage(
|
|
|
|
|
"Renesas Graphics Library",
|
|
|
|
|
defaultPath,
|
|
|
|
|
{},
|
|
|
|
|
"RGL");
|
|
|
|
|
result->setEnvironmentVariableName(envVar);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-12 14:25:49 +01:00
|
|
|
static McuPackage *createStm32CubeProgrammerPackage()
|
|
|
|
|
{
|
2021-11-23 16:20:52 +01:00
|
|
|
FilePath defaultPath;
|
2021-09-30 18:30:02 +02:00
|
|
|
const QString cubePath = "STMicroelectronics/STM32Cube/STM32CubeProgrammer";
|
|
|
|
|
if (HostOsInfo::isWindowsHost()) {
|
|
|
|
|
const FilePath programPath = findInProgramFiles(cubePath);
|
2020-03-12 14:25:49 +01:00
|
|
|
if (!programPath.isEmpty())
|
|
|
|
|
defaultPath = programPath;
|
2021-05-27 09:34:55 +02:00
|
|
|
} else {
|
2021-09-30 18:30:02 +02:00
|
|
|
const FilePath programPath = FileUtils::homePath() / cubePath;
|
|
|
|
|
if (programPath.exists())
|
2021-05-27 09:34:55 +02:00
|
|
|
defaultPath = programPath;
|
2020-03-12 14:25:49 +01:00
|
|
|
}
|
|
|
|
|
auto result = new McuPackage(
|
|
|
|
|
McuPackage::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;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-08 23:59:52 +02:00
|
|
|
static McuPackage *createMcuXpressoIdePackage()
|
2020-03-12 14:25:49 +01:00
|
|
|
{
|
2020-04-08 23:59:52 +02:00
|
|
|
const char envVar[] = "MCUXpressoIDE_PATH";
|
|
|
|
|
|
2021-09-30 18:30:02 +02:00
|
|
|
FilePath defaultPath;
|
2020-04-08 23:59:52 +02:00
|
|
|
if (qEnvironmentVariableIsSet(envVar)) {
|
2021-09-30 18:30:02 +02:00
|
|
|
defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar));
|
|
|
|
|
} else if (HostOsInfo::isWindowsHost()) {
|
2021-11-23 16:20:52 +01:00
|
|
|
const FilePath programPath = FilePath::fromString(QDir::rootPath()) / "nxp";
|
|
|
|
|
if (programPath.exists()) {
|
|
|
|
|
defaultPath = programPath;
|
2020-04-08 23:59:52 +02:00
|
|
|
// If default dir has exactly one sub dir that could be the IDE path, pre-select that.
|
2021-09-30 18:30:02 +02:00
|
|
|
const FilePaths subDirs =
|
|
|
|
|
defaultPath.dirEntries({QLatin1String("MCUXpressoIDE*")},
|
2020-04-08 23:59:52 +02:00
|
|
|
QDir::Dirs | QDir::NoDotAndDotDot);
|
|
|
|
|
if (subDirs.count() == 1)
|
2021-09-30 18:30:02 +02:00
|
|
|
defaultPath = subDirs.first();
|
2020-04-08 23:59:52 +02:00
|
|
|
}
|
|
|
|
|
} else {
|
2021-11-23 16:20:52 +01:00
|
|
|
const FilePath programPath = FilePath::fromString("/usr/local/mcuxpressoide/");
|
|
|
|
|
if (programPath.exists())
|
|
|
|
|
defaultPath = programPath;
|
2020-03-12 14:25:49 +01:00
|
|
|
}
|
2020-04-08 23:59:52 +02:00
|
|
|
|
2020-03-12 14:25:49 +01:00
|
|
|
auto result = new McuPackage(
|
2020-04-08 23:59:52 +02:00
|
|
|
"MCUXpresso IDE",
|
2020-03-12 14:25:49 +01:00
|
|
|
defaultPath,
|
2020-04-08 23:59:52 +02:00
|
|
|
Utils::HostOsInfo::withExecutableSuffix("ide/binaries/crt_emu_cm_redlink"),
|
|
|
|
|
"MCUXpressoIDE");
|
|
|
|
|
result->setDownloadUrl("https://www.nxp.com/mcuxpresso/ide");
|
|
|
|
|
result->setEnvironmentVariableName(envVar);
|
2020-03-12 14:25:49 +01:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-10 11:35:46 +02:00
|
|
|
static McuPackage *createCypressProgrammerPackage()
|
|
|
|
|
{
|
|
|
|
|
const char envVar[] = "CYPRESS_AUTO_FLASH_UTILITY_DIR";
|
|
|
|
|
|
2021-09-30 18:30:02 +02:00
|
|
|
FilePath defaultPath;
|
2021-05-10 11:35:46 +02:00
|
|
|
if (qEnvironmentVariableIsSet(envVar)) {
|
2021-09-30 18:30:02 +02:00
|
|
|
defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar));
|
|
|
|
|
} else if (HostOsInfo::isWindowsHost()) {
|
2021-11-23 16:20:52 +01:00
|
|
|
const FilePath candidate = findInProgramFiles("Cypress/Cypress Auto Flash Utility 1.0");
|
|
|
|
|
if (candidate.exists())
|
2021-05-10 11:35:46 +02:00
|
|
|
defaultPath = candidate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto result = new McuPackage(
|
|
|
|
|
"Cypress Auto Flash Utility",
|
|
|
|
|
defaultPath,
|
|
|
|
|
Utils::HostOsInfo::withExecutableSuffix("/bin/openocd"),
|
|
|
|
|
"CypressAutoFlashUtil");
|
|
|
|
|
result->setEnvironmentVariableName(envVar);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-17 11:25:59 +02:00
|
|
|
struct McuTargetDescription
|
2020-04-27 20:51:08 +02:00
|
|
|
{
|
2020-09-18 11:16:37 +02:00
|
|
|
enum class TargetType {
|
|
|
|
|
MCU,
|
|
|
|
|
Desktop
|
|
|
|
|
};
|
|
|
|
|
|
2020-08-17 11:25:59 +02:00
|
|
|
QString qulVersion;
|
2021-09-29 17:23:11 +02:00
|
|
|
QString compatVersion;
|
|
|
|
|
struct {
|
|
|
|
|
QString id;
|
|
|
|
|
QString name;
|
|
|
|
|
QString vendor;
|
|
|
|
|
QVector<int> colorDepths;
|
|
|
|
|
TargetType type;
|
|
|
|
|
} platform;
|
|
|
|
|
struct {
|
|
|
|
|
QString id;
|
2021-11-15 09:48:47 +01:00
|
|
|
QStringList versions;
|
2021-09-29 17:23:11 +02:00
|
|
|
} toolchain;
|
|
|
|
|
struct {
|
|
|
|
|
QString name;
|
|
|
|
|
QString defaultPath;
|
|
|
|
|
QString envVar;
|
2021-11-15 09:48:47 +01:00
|
|
|
QStringList versions;
|
2021-09-29 17:23:11 +02:00
|
|
|
} boardSdk;
|
|
|
|
|
struct {
|
|
|
|
|
QString envVar;
|
|
|
|
|
QString boardSdkSubDir;
|
|
|
|
|
} freeRTOS;
|
2020-08-17 11:25:59 +02:00
|
|
|
};
|
2020-04-27 20:51:08 +02:00
|
|
|
|
2021-02-15 16:20:38 +01:00
|
|
|
static McuPackageVersionDetector* generatePackageVersionDetector(QString envVar)
|
|
|
|
|
{
|
|
|
|
|
if (envVar.startsWith("EVK"))
|
|
|
|
|
return new McuPackageXmlVersionDetector("*_manifest_*.xml", "ksdk", "version", ".*");
|
|
|
|
|
|
|
|
|
|
if (envVar.startsWith("STM32"))
|
|
|
|
|
return new McuPackageXmlVersionDetector("package.xml", "PackDescription", "Release", "\\b(\\d+\\.\\d+\\.\\d+)\\b");
|
|
|
|
|
|
|
|
|
|
if (envVar.startsWith("RGL"))
|
|
|
|
|
return new McuPackageDirectoryVersionDetector("rgl_*_obj_*", "\\d+\\.\\d+\\.\\w+", false);
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-10 11:35:46 +02:00
|
|
|
/// Create the McuPackage by checking the "boardSdk" property in the JSON file for the board.
|
|
|
|
|
/// The name of the environment variable pointing to the the SDK for the board will be defined in the "envVar" property
|
|
|
|
|
/// inside the "boardSdk".
|
2020-08-17 11:25:59 +02:00
|
|
|
static McuPackage *createBoardSdkPackage(const McuTargetDescription& desc)
|
|
|
|
|
{
|
|
|
|
|
const auto generateSdkName = [](const QString& envVar) {
|
|
|
|
|
auto postfixPos = envVar.indexOf("_SDK_PATH");
|
|
|
|
|
if (postfixPos < 0) {
|
|
|
|
|
postfixPos = envVar.indexOf("_DIR");
|
|
|
|
|
}
|
|
|
|
|
auto sdkName = postfixPos > 0 ? envVar.left(postfixPos) : envVar;
|
|
|
|
|
return QString::fromLatin1("MCU SDK (%1)").arg(sdkName);
|
|
|
|
|
};
|
2021-09-29 17:23:11 +02:00
|
|
|
const QString sdkName = desc.boardSdk.name.isEmpty() ? generateSdkName(desc.boardSdk.envVar) : desc.boardSdk.name;
|
2020-08-17 11:25:59 +02:00
|
|
|
|
2021-09-30 18:30:02 +02:00
|
|
|
const FilePath defaultPath = [&] {
|
2021-09-29 17:23:11 +02:00
|
|
|
const auto envVar = desc.boardSdk.envVar.toLatin1();
|
2021-09-30 18:30:02 +02:00
|
|
|
if (qEnvironmentVariableIsSet(envVar))
|
|
|
|
|
return FilePath::fromUserInput(qEnvironmentVariable(envVar));
|
2021-09-29 17:23:11 +02:00
|
|
|
if (!desc.boardSdk.defaultPath.isEmpty()) {
|
|
|
|
|
FilePath defaultPath = FilePath::fromUserInput(QDir::rootPath() + desc.boardSdk.defaultPath);
|
2021-09-30 18:30:02 +02:00
|
|
|
if (defaultPath.exists())
|
2020-08-17 11:25:59 +02:00
|
|
|
return defaultPath;
|
|
|
|
|
}
|
2021-11-23 16:20:52 +01:00
|
|
|
return FilePath();
|
2020-08-17 11:25:59 +02:00
|
|
|
}();
|
2020-04-27 20:51:08 +02:00
|
|
|
|
2021-09-29 17:23:11 +02:00
|
|
|
const auto versionDetector = generatePackageVersionDetector(desc.boardSdk.envVar);
|
2021-02-15 16:20:38 +01:00
|
|
|
|
2020-06-29 23:21:22 +02:00
|
|
|
auto result = new McuPackage(
|
2020-08-17 11:25:59 +02:00
|
|
|
sdkName,
|
2020-06-29 23:21:22 +02:00
|
|
|
defaultPath,
|
|
|
|
|
{},
|
2021-09-29 17:23:11 +02:00
|
|
|
desc.boardSdk.envVar,
|
2021-02-15 16:20:38 +01:00
|
|
|
versionDetector);
|
2021-09-29 17:23:11 +02:00
|
|
|
result->setEnvironmentVariableName(desc.boardSdk.envVar);
|
2020-06-29 23:21:22 +02:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-30 18:30:02 +02:00
|
|
|
static McuPackage *createFreeRTOSSourcesPackage(const QString &envVar, const FilePath &boardSdkDir,
|
2020-07-03 09:46:44 +02:00
|
|
|
const QString &freeRTOSBoardSdkSubDir)
|
2020-04-27 20:51:08 +02:00
|
|
|
{
|
2020-09-18 11:16:37 +02:00
|
|
|
const QString envVarPrefix = envVar.chopped(int(strlen("_FREERTOS_DIR")));
|
2020-04-27 20:51:08 +02:00
|
|
|
|
2021-09-30 18:30:02 +02:00
|
|
|
FilePath defaultPath;
|
2020-07-03 09:46:44 +02:00
|
|
|
if (qEnvironmentVariableIsSet(envVar.toLatin1()))
|
2021-09-30 18:30:02 +02:00
|
|
|
defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar.toLatin1()));
|
2020-07-03 09:46:44 +02:00
|
|
|
else if (!boardSdkDir.isEmpty() && !freeRTOSBoardSdkSubDir.isEmpty())
|
2021-09-30 18:30:02 +02:00
|
|
|
defaultPath = boardSdkDir / freeRTOSBoardSdkSubDir;
|
2020-04-27 20:51:08 +02:00
|
|
|
|
|
|
|
|
auto result = new McuPackage(
|
|
|
|
|
QString::fromLatin1("FreeRTOS Sources (%1)").arg(envVarPrefix),
|
|
|
|
|
defaultPath,
|
|
|
|
|
{},
|
|
|
|
|
QString::fromLatin1("FreeRTOSSourcePackage_%1").arg(envVarPrefix));
|
|
|
|
|
result->setDownloadUrl("https://freertos.org");
|
|
|
|
|
result->setEnvironmentVariableName(envVar);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-13 13:10:52 +02:00
|
|
|
struct McuTargetFactory
|
2020-05-07 12:38:28 +02:00
|
|
|
{
|
2020-08-13 13:10:52 +02:00
|
|
|
McuTargetFactory(const QHash<QString, McuToolChainPackage *> &tcPkgs,
|
|
|
|
|
const QHash<QString, McuPackage *> &vendorPkgs)
|
|
|
|
|
: tcPkgs(tcPkgs)
|
|
|
|
|
, vendorPkgs(vendorPkgs)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
QVector<McuTarget *> createTargets(const McuTargetDescription& description)
|
|
|
|
|
{
|
|
|
|
|
auto qulVersion = QVersionNumber::fromString(description.qulVersion);
|
|
|
|
|
if (qulVersion <= QVersionNumber({1,3})) {
|
2021-09-29 17:23:11 +02:00
|
|
|
if (description.platform.type == McuTargetDescription::TargetType::Desktop)
|
2020-09-18 11:16:37 +02:00
|
|
|
return createDesktopTargetsLegacy(description);
|
|
|
|
|
|
2020-08-13 13:10:52 +02:00
|
|
|
// There was a platform backends related refactoring in Qul 1.4
|
|
|
|
|
// This requires different processing of McuTargetDescriptions
|
|
|
|
|
return createMcuTargetsLegacy(description);
|
|
|
|
|
}
|
2020-09-18 11:16:37 +02:00
|
|
|
return createTargetsImpl(description);
|
2020-08-13 13:10:52 +02:00
|
|
|
}
|
2020-03-18 03:17:35 +01:00
|
|
|
|
2020-08-13 13:10:52 +02:00
|
|
|
QVector<McuPackage *> getMcuPackages() const
|
|
|
|
|
{
|
|
|
|
|
QVector<McuPackage *> packages;
|
2020-12-08 15:41:46 +01:00
|
|
|
for (auto *package : qAsConst(boardSdkPkgs))
|
|
|
|
|
packages.append(package);
|
|
|
|
|
for (auto *package : qAsConst(freeRTOSPkgs))
|
|
|
|
|
packages.append(package);
|
2020-08-13 13:10:52 +02:00
|
|
|
return packages;
|
|
|
|
|
}
|
2020-05-07 12:38:28 +02:00
|
|
|
|
2020-08-13 13:10:52 +02:00
|
|
|
protected:
|
|
|
|
|
// Implementation for Qul version <= 1.3
|
2020-09-18 11:16:37 +02:00
|
|
|
QVector<McuTarget *> createMcuTargetsLegacy(const McuTargetDescription &desc)
|
2020-08-13 13:10:52 +02:00
|
|
|
{
|
|
|
|
|
QVector<McuTarget *> mcuTargets;
|
2021-09-29 17:23:11 +02:00
|
|
|
McuToolChainPackage *tcPkg = tcPkgs.value(desc.toolchain.id);
|
2020-11-13 14:00:18 +01:00
|
|
|
if (!tcPkg)
|
|
|
|
|
tcPkg = createUnsupportedToolChainPackage();
|
2020-05-07 12:38:28 +02:00
|
|
|
for (auto os : {McuTarget::OS::BareMetal, McuTarget::OS::FreeRTOS}) {
|
2021-09-29 17:23:11 +02:00
|
|
|
for (int colorDepth : desc.platform.colorDepths) {
|
2020-08-17 11:25:59 +02:00
|
|
|
QVector<McuPackage*> required3rdPartyPkgs = { tcPkg };
|
2021-09-29 17:23:11 +02:00
|
|
|
if (vendorPkgs.contains(desc.platform.vendor))
|
|
|
|
|
required3rdPartyPkgs.push_back(vendorPkgs.value(desc.platform.vendor));
|
2020-09-18 11:16:37 +02:00
|
|
|
|
2021-09-30 18:30:02 +02:00
|
|
|
FilePath boardSdkDefaultPath;
|
2021-09-29 17:23:11 +02:00
|
|
|
if (!desc.boardSdk.envVar.isEmpty()) {
|
|
|
|
|
if (!boardSdkPkgs.contains(desc.boardSdk.envVar)) {
|
|
|
|
|
auto boardSdkPkg = desc.boardSdk.envVar != "RGL_DIR"
|
2020-08-17 11:25:59 +02:00
|
|
|
? createBoardSdkPackage(desc)
|
|
|
|
|
: createRGLPackage();
|
2021-09-29 17:23:11 +02:00
|
|
|
boardSdkPkgs.insert(desc.boardSdk.envVar, boardSdkPkg);
|
2020-06-29 23:21:22 +02:00
|
|
|
}
|
2021-09-29 17:23:11 +02:00
|
|
|
auto boardSdkPkg = boardSdkPkgs.value(desc.boardSdk.envVar);
|
2020-07-03 09:46:44 +02:00
|
|
|
boardSdkDefaultPath = boardSdkPkg->defaultPath();
|
|
|
|
|
required3rdPartyPkgs.append(boardSdkPkg);
|
2020-06-29 23:21:22 +02:00
|
|
|
}
|
2020-05-05 06:48:26 +02:00
|
|
|
if (os == McuTarget::OS::FreeRTOS) {
|
2021-09-29 17:23:11 +02:00
|
|
|
if (desc.freeRTOS.envVar.isEmpty()) {
|
2020-05-05 06:48:26 +02:00
|
|
|
continue;
|
2020-05-07 12:38:28 +02:00
|
|
|
} else {
|
2021-09-29 17:23:11 +02:00
|
|
|
if (!freeRTOSPkgs.contains(desc.freeRTOS.envVar)) {
|
|
|
|
|
freeRTOSPkgs.insert(desc.freeRTOS.envVar, createFreeRTOSSourcesPackage(
|
|
|
|
|
desc.freeRTOS.envVar, boardSdkDefaultPath,
|
|
|
|
|
desc.freeRTOS.boardSdkSubDir));
|
2020-05-07 12:38:28 +02:00
|
|
|
}
|
2021-09-29 17:23:11 +02:00
|
|
|
required3rdPartyPkgs.append(freeRTOSPkgs.value(desc.freeRTOS.envVar));
|
2020-05-07 12:38:28 +02:00
|
|
|
}
|
2020-05-05 06:48:26 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-29 17:23:11 +02:00
|
|
|
const auto platform = McuTarget::Platform{ desc.platform.id, desc.platform.name, desc.platform.vendor };
|
2020-06-30 17:09:03 +02:00
|
|
|
auto mcuTarget = new McuTarget(QVersionNumber::fromString(desc.qulVersion),
|
2020-09-18 11:16:37 +02:00
|
|
|
platform, os, required3rdPartyPkgs, tcPkg);
|
2021-09-29 17:23:11 +02:00
|
|
|
if (desc.platform.colorDepths.count() > 1)
|
2020-05-05 06:48:26 +02:00
|
|
|
mcuTarget->setColorDepth(colorDepth);
|
2020-05-07 12:38:28 +02:00
|
|
|
mcuTargets.append(mcuTarget);
|
2020-05-05 06:48:26 +02:00
|
|
|
}
|
2020-03-18 03:17:35 +01:00
|
|
|
}
|
2020-08-13 13:10:52 +02:00
|
|
|
return mcuTargets;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-18 11:16:37 +02:00
|
|
|
QVector<McuTarget *> createDesktopTargetsLegacy(const McuTargetDescription& desc)
|
2020-08-13 13:10:52 +02:00
|
|
|
{
|
2021-09-29 17:23:11 +02:00
|
|
|
McuToolChainPackage *tcPkg = tcPkgs.value(desc.toolchain.id);
|
2020-11-13 14:00:18 +01:00
|
|
|
if (!tcPkg)
|
|
|
|
|
tcPkg = createUnsupportedToolChainPackage();
|
2021-09-29 17:23:11 +02:00
|
|
|
const auto platform = McuTarget::Platform{ desc.platform.id, desc.platform.name, desc.platform.vendor };
|
2020-09-18 11:16:37 +02:00
|
|
|
auto desktopTarget = new McuTarget(QVersionNumber::fromString(desc.qulVersion),
|
|
|
|
|
platform, McuTarget::OS::Desktop, {}, tcPkg);
|
|
|
|
|
return { desktopTarget };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QVector<McuTarget *> createTargetsImpl(const McuTargetDescription& desc)
|
|
|
|
|
{
|
|
|
|
|
// OS deduction
|
|
|
|
|
const auto os = [&] {
|
2021-09-29 17:23:11 +02:00
|
|
|
if (desc.platform.type == McuTargetDescription::TargetType::Desktop)
|
2020-09-18 11:16:37 +02:00
|
|
|
return McuTarget::OS::Desktop;
|
2021-09-29 17:23:11 +02:00
|
|
|
else if (!desc.freeRTOS.envVar.isEmpty())
|
2020-09-18 11:16:37 +02:00
|
|
|
return McuTarget::OS::FreeRTOS;
|
|
|
|
|
return McuTarget::OS::BareMetal;
|
|
|
|
|
}();
|
|
|
|
|
|
2020-08-13 13:10:52 +02:00
|
|
|
QVector<McuTarget *> mcuTargets;
|
2021-09-29 17:23:11 +02:00
|
|
|
McuToolChainPackage *tcPkg = tcPkgs.value(desc.toolchain.id);
|
2021-02-15 16:20:38 +01:00
|
|
|
if (tcPkg) {
|
|
|
|
|
if (QVersionNumber::fromString(desc.qulVersion) >= QVersionNumber({1,8}))
|
2021-09-29 17:23:11 +02:00
|
|
|
tcPkg->setVersions(desc.toolchain.versions);
|
2021-02-15 16:20:38 +01:00
|
|
|
} else
|
2020-11-13 14:00:18 +01:00
|
|
|
tcPkg = createUnsupportedToolChainPackage();
|
2021-09-29 17:23:11 +02:00
|
|
|
for (int colorDepth : desc.platform.colorDepths) {
|
2020-09-18 11:16:37 +02:00
|
|
|
QVector<McuPackage*> required3rdPartyPkgs;
|
|
|
|
|
// Desktop toolchains don't need any additional settings
|
2020-11-13 14:00:18 +01:00
|
|
|
if (tcPkg
|
|
|
|
|
&& !tcPkg->isDesktopToolchain()
|
|
|
|
|
&& tcPkg->type() != McuToolChainPackage::TypeUnsupported)
|
2020-09-18 11:16:37 +02:00
|
|
|
required3rdPartyPkgs.append(tcPkg);
|
|
|
|
|
|
|
|
|
|
// Add setting specific to platform IDE
|
2021-09-29 17:23:11 +02:00
|
|
|
if (vendorPkgs.contains(desc.platform.vendor))
|
|
|
|
|
required3rdPartyPkgs.push_back(vendorPkgs.value(desc.platform.vendor));
|
2020-09-18 11:16:37 +02:00
|
|
|
|
|
|
|
|
// Board SDK specific settings
|
2021-09-30 18:30:02 +02:00
|
|
|
FilePath boardSdkDefaultPath;
|
2021-09-29 17:23:11 +02:00
|
|
|
if (!desc.boardSdk.envVar.isEmpty()) {
|
|
|
|
|
if (!boardSdkPkgs.contains(desc.boardSdk.envVar)) {
|
2020-08-17 11:25:59 +02:00
|
|
|
auto boardSdkPkg = createBoardSdkPackage(desc);
|
2021-09-29 17:23:11 +02:00
|
|
|
boardSdkPkgs.insert(desc.boardSdk.envVar, boardSdkPkg);
|
2020-08-13 13:10:52 +02:00
|
|
|
}
|
2021-09-29 17:23:11 +02:00
|
|
|
auto boardSdkPkg = boardSdkPkgs.value(desc.boardSdk.envVar);
|
2021-03-01 11:07:44 +01:00
|
|
|
if (QVersionNumber::fromString(desc.qulVersion) >= QVersionNumber({1,8}))
|
2021-09-29 17:23:11 +02:00
|
|
|
boardSdkPkg->setVersions(desc.boardSdk.versions);
|
2020-08-13 13:10:52 +02:00
|
|
|
boardSdkDefaultPath = boardSdkPkg->defaultPath();
|
|
|
|
|
required3rdPartyPkgs.append(boardSdkPkg);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-18 11:16:37 +02:00
|
|
|
// Free RTOS specific settings
|
2021-09-29 17:23:11 +02:00
|
|
|
if (!desc.freeRTOS.envVar.isEmpty()) {
|
|
|
|
|
if (!freeRTOSPkgs.contains(desc.freeRTOS.envVar)) {
|
|
|
|
|
freeRTOSPkgs.insert(desc.freeRTOS.envVar, createFreeRTOSSourcesPackage(
|
|
|
|
|
desc.freeRTOS.envVar, boardSdkDefaultPath,
|
|
|
|
|
desc.freeRTOS.boardSdkSubDir));
|
2020-08-13 13:10:52 +02:00
|
|
|
}
|
2021-09-29 17:23:11 +02:00
|
|
|
required3rdPartyPkgs.append(freeRTOSPkgs.value(desc.freeRTOS.envVar));
|
2020-08-13 13:10:52 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-29 17:23:11 +02:00
|
|
|
const auto platform = McuTarget::Platform{ desc.platform.id, desc.platform.name, desc.platform.vendor };
|
2020-08-13 13:10:52 +02:00
|
|
|
auto mcuTarget = new McuTarget(QVersionNumber::fromString(desc.qulVersion),
|
2020-09-18 11:16:37 +02:00
|
|
|
platform, os, required3rdPartyPkgs, tcPkg);
|
2020-08-13 13:10:52 +02:00
|
|
|
mcuTarget->setColorDepth(colorDepth);
|
|
|
|
|
mcuTargets.append(mcuTarget);
|
|
|
|
|
}
|
|
|
|
|
return mcuTargets;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
const QHash<QString, McuToolChainPackage *> &tcPkgs;
|
|
|
|
|
const QHash<QString, McuPackage *> &vendorPkgs;
|
|
|
|
|
|
|
|
|
|
QHash<QString, McuPackage *> boardSdkPkgs;
|
|
|
|
|
QHash<QString, McuPackage *> freeRTOSPkgs;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static QVector<McuTarget *> targetsFromDescriptions(const QList<McuTargetDescription> &descriptions,
|
|
|
|
|
QVector<McuPackage *> *packages)
|
|
|
|
|
{
|
|
|
|
|
const QHash<QString, McuToolChainPackage *> tcPkgs = {
|
|
|
|
|
{{"armgcc"}, createArmGccPackage()},
|
|
|
|
|
{{"greenhills"}, createGhsToolchainPackage()},
|
2020-11-13 14:00:18 +01:00
|
|
|
{{"iar"}, createIarToolChainPackage()},
|
2020-09-18 11:16:37 +02:00
|
|
|
{{"msvc"}, createMsvcToolChainPackage()},
|
|
|
|
|
{{"gcc"}, createGccToolChainPackage()},
|
2021-05-10 11:35:46 +02:00
|
|
|
{{"arm-greenhills"}, createGhsArmToolchainPackage()},
|
2020-08-13 13:10:52 +02:00
|
|
|
};
|
|
|
|
|
|
2021-05-10 11:35:46 +02:00
|
|
|
// Note: the vendor name (the key of the hash) is case-sensitive. It has to match the "platformVendor" key in the
|
|
|
|
|
// json file.
|
2020-08-13 13:10:52 +02:00
|
|
|
const QHash<QString, McuPackage *> vendorPkgs = {
|
|
|
|
|
{{"ST"}, createStm32CubeProgrammerPackage()},
|
|
|
|
|
{{"NXP"}, createMcuXpressoIdePackage()},
|
2021-05-10 11:35:46 +02:00
|
|
|
{{"CYPRESS"}, createCypressProgrammerPackage()},
|
2020-08-13 13:10:52 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
McuTargetFactory targetFactory(tcPkgs, vendorPkgs);
|
|
|
|
|
QVector<McuTarget *> mcuTargets;
|
|
|
|
|
|
|
|
|
|
for (const auto &desc : descriptions) {
|
|
|
|
|
auto newTargets = targetFactory.createTargets(desc);
|
|
|
|
|
mcuTargets.append(newTargets);
|
2020-03-18 03:17:35 +01:00
|
|
|
}
|
2020-05-07 12:38:28 +02:00
|
|
|
|
|
|
|
|
packages->append(Utils::transform<QVector<McuPackage *> >(
|
|
|
|
|
tcPkgs.values(), [&](McuToolChainPackage *tcPkg) { return tcPkg; }));
|
2020-12-08 15:41:46 +01:00
|
|
|
for (auto *package : vendorPkgs)
|
|
|
|
|
packages->append(package);
|
2020-08-13 13:10:52 +02:00
|
|
|
packages->append(targetFactory.getMcuPackages());
|
2020-05-07 12:38:28 +02:00
|
|
|
|
|
|
|
|
return mcuTargets;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-04 16:32:34 +01:00
|
|
|
Utils::FilePath kitsPath(const Utils::FilePath &dir)
|
|
|
|
|
{
|
2021-11-23 16:20:52 +01:00
|
|
|
return dir / "kits/";
|
2020-12-04 16:32:34 +01:00
|
|
|
}
|
|
|
|
|
|
2020-05-07 12:38:28 +02:00
|
|
|
static QFileInfoList targetDescriptionFiles(const Utils::FilePath &dir)
|
|
|
|
|
{
|
2020-12-04 16:32:34 +01:00
|
|
|
const QDir kitsDir(kitsPath(dir).toString(), "*.json");
|
2020-05-15 16:17:15 +02:00
|
|
|
return kitsDir.entryInfoList();
|
2020-05-07 12:38:28 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-29 17:23:11 +02:00
|
|
|
static McuTargetDescription parseDescriptionJsonCommon(const QString &qulVersion, const QJsonObject &target)
|
|
|
|
|
{
|
|
|
|
|
const QString compatVersion = target.value("compatVersion").toString();
|
2020-05-07 12:38:28 +02:00
|
|
|
const QJsonObject toolchain = target.value("toolchain").toObject();
|
|
|
|
|
const QJsonObject boardSdk = target.value("boardSdk").toObject();
|
2020-07-02 16:05:53 +02:00
|
|
|
const QJsonObject freeRTOS = target.value("freeRTOS").toObject();
|
2020-05-07 12:38:28 +02:00
|
|
|
|
2021-02-15 16:20:38 +01:00
|
|
|
const QVariantList toolchainVersions = toolchain.value("versions").toArray().toVariantList();
|
2021-11-15 09:48:47 +01:00
|
|
|
const auto toolchainVersionsList = Utils::transform<QStringList>(
|
2021-02-15 16:20:38 +01:00
|
|
|
toolchainVersions, [&](const QVariant &version) { return version.toString(); });
|
|
|
|
|
const QVariantList boardSdkVersions = boardSdk.value("versions").toArray().toVariantList();
|
2021-11-15 09:48:47 +01:00
|
|
|
const auto boardSdkVersionsList = Utils::transform<QStringList>(
|
2021-02-15 16:20:38 +01:00
|
|
|
boardSdkVersions, [&](const QVariant &version) { return version.toString(); });
|
2020-05-07 12:38:28 +02:00
|
|
|
|
|
|
|
|
return {
|
2021-09-29 17:23:11 +02:00
|
|
|
qulVersion,
|
|
|
|
|
compatVersion,
|
|
|
|
|
{},
|
|
|
|
|
{
|
|
|
|
|
toolchain.value("id").toString(),
|
2021-11-15 09:48:47 +01:00
|
|
|
toolchainVersionsList,
|
2021-09-29 17:23:11 +02:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
boardSdk.value("name").toString(),
|
|
|
|
|
boardSdk.value("defaultPath").toString(),
|
|
|
|
|
boardSdk.value("envVar").toString(),
|
2021-11-15 09:48:47 +01:00
|
|
|
boardSdkVersionsList,
|
2021-09-29 17:23:11 +02:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
freeRTOS.value("envVar").toString(),
|
|
|
|
|
freeRTOS.value("boardSdkSubDir").toString(),
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static McuTargetDescription parseDescriptionJsonV1x(const QString &qulVersion, const QJsonObject &target)
|
|
|
|
|
{
|
|
|
|
|
auto description = parseDescriptionJsonCommon(qulVersion, target);
|
|
|
|
|
|
|
|
|
|
const QVariantList colorDepths = target.value("colorDepths").toArray().toVariantList();
|
|
|
|
|
const auto colorDepthsVector = Utils::transform<QVector<int> >(
|
|
|
|
|
colorDepths, [&](const QVariant &colorDepth) { return colorDepth.toInt(); });
|
|
|
|
|
|
|
|
|
|
description.platform = {
|
|
|
|
|
target.value("platform").toString(),
|
|
|
|
|
target.value("platformName").toString(),
|
|
|
|
|
target.value("platformVendor").toString(),
|
|
|
|
|
colorDepthsVector,
|
|
|
|
|
description.boardSdk.envVar.isEmpty() ? McuTargetDescription::TargetType::Desktop : McuTargetDescription::TargetType::MCU
|
|
|
|
|
};
|
|
|
|
|
return description;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static McuTargetDescription parseDescriptionJsonV2x(const QString &qulVersion, const QJsonObject &target)
|
|
|
|
|
{
|
|
|
|
|
const QJsonObject platform = target.value("platform").toObject();
|
|
|
|
|
|
|
|
|
|
const QVariantList colorDepths = platform.value("colorDepths").toArray().toVariantList();
|
|
|
|
|
const auto colorDepthsVector = Utils::transform<QVector<int> >(
|
|
|
|
|
colorDepths, [&](const QVariant &colorDepth) { return colorDepth.toInt(); });
|
|
|
|
|
const QString platformName = platform.value("platformName").toString();
|
|
|
|
|
McuTargetDescription description = parseDescriptionJsonCommon(qulVersion, target);
|
|
|
|
|
description.platform = {
|
|
|
|
|
platform.value("id").toString(),
|
|
|
|
|
platformName,
|
|
|
|
|
platform.value("vendor").toString(),
|
2020-05-07 12:38:28 +02:00
|
|
|
colorDepthsVector,
|
2021-09-29 17:23:11 +02:00
|
|
|
platformName == "Desktop" ? McuTargetDescription::TargetType::Desktop : McuTargetDescription::TargetType::MCU,
|
2020-05-07 12:38:28 +02:00
|
|
|
};
|
2021-09-29 17:23:11 +02:00
|
|
|
|
|
|
|
|
return description;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static McuTargetDescription parseDescriptionJson(const QByteArray &data)
|
|
|
|
|
{
|
|
|
|
|
const QJsonDocument document = QJsonDocument::fromJson(data);
|
|
|
|
|
const QJsonObject target = document.object();
|
|
|
|
|
|
|
|
|
|
const QString qulVersion = target.value("qulVersion").toString();
|
|
|
|
|
|
|
|
|
|
switch (QVersionNumber::fromString(qulVersion).majorVersion()) {
|
|
|
|
|
case 1: return parseDescriptionJsonV1x(qulVersion, target);
|
|
|
|
|
case 2: return parseDescriptionJsonV2x(qulVersion, target);
|
|
|
|
|
default: return { qulVersion };
|
|
|
|
|
}
|
2020-05-07 12:38:28 +02:00
|
|
|
}
|
|
|
|
|
|
2021-03-04 17:07:49 +01:00
|
|
|
// https://doc.qt.io/qtcreator/creator-developing-mcu.html#supported-qt-for-mcus-sdks
|
2021-03-01 11:07:44 +01:00
|
|
|
const QHash<QString, QString> oldSdkQtcRequiredVersion = {
|
|
|
|
|
{{"1.0"}, {"4.11.x"}},
|
|
|
|
|
{{"1.1"}, {"4.12.0 or 4.12.1"}},
|
|
|
|
|
{{"1.2"}, {"4.12.2 or 4.12.3"}},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
bool checkDeprecatedSdkError(const Utils::FilePath &qulDir, QString &message)
|
|
|
|
|
{
|
|
|
|
|
const McuPackagePathVersionDetector versionDetector("(?<=\\bQtMCUs.)(\\d+\\.\\d+)");
|
|
|
|
|
const QString sdkDetectedVersion = versionDetector.parseVersion(qulDir.toString());
|
|
|
|
|
|
|
|
|
|
if (oldSdkQtcRequiredVersion.contains(sdkDetectedVersion)) {
|
|
|
|
|
message = McuTarget::tr("Qt for MCUs SDK version %1 detected, "
|
2021-03-04 17:07:49 +01:00
|
|
|
"only supported by Qt Creator version %2. "
|
|
|
|
|
"This version of Qt Creator requires Qt for MCUs %3 or greater."
|
2021-03-01 11:07:44 +01:00
|
|
|
).arg(sdkDetectedVersion,
|
|
|
|
|
oldSdkQtcRequiredVersion.value(sdkDetectedVersion),
|
|
|
|
|
McuSupportOptions::minimalQulVersion().toString());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-29 17:23:11 +02:00
|
|
|
void targetsAndPackages(const Utils::FilePath &dir, McuSdkRepository *repo)
|
2020-05-07 12:38:28 +02:00
|
|
|
{
|
|
|
|
|
QList<McuTargetDescription> descriptions;
|
|
|
|
|
|
2020-12-04 16:32:34 +01:00
|
|
|
auto descriptionFiles = targetDescriptionFiles(dir);
|
|
|
|
|
for (const QFileInfo &fileInfo : descriptionFiles) {
|
2020-05-07 12:38:28 +02:00
|
|
|
QFile file(fileInfo.absoluteFilePath());
|
|
|
|
|
if (!file.open(QFile::ReadOnly))
|
|
|
|
|
continue;
|
|
|
|
|
const McuTargetDescription desc = parseDescriptionJson(file.readAll());
|
2021-09-29 17:23:11 +02:00
|
|
|
const auto pth = Utils::FilePath::fromString(fileInfo.filePath());
|
|
|
|
|
bool ok = false;
|
|
|
|
|
const int compatVersion = desc.compatVersion.toInt(&ok);
|
|
|
|
|
if (!desc.compatVersion.isEmpty() && ok && compatVersion > MAX_COMPATIBILITY_VERSION) {
|
|
|
|
|
printMessage(McuTarget::tr("Skipped %1. Unsupported version \"%2\".").arg(
|
|
|
|
|
QDir::toNativeSeparators(pth.fileNameWithPathComponents(1)),
|
|
|
|
|
desc.qulVersion),
|
|
|
|
|
false);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2020-12-04 16:32:34 +01:00
|
|
|
if (QVersionNumber::fromString(desc.qulVersion) < McuSupportOptions::minimalQulVersion()) {
|
2021-03-01 11:07:44 +01:00
|
|
|
const QString qtcSupportText = oldSdkQtcRequiredVersion.contains(desc.qulVersion) ?
|
|
|
|
|
McuTarget::tr("Detected version \"%1\", only supported by Qt Creator %2.")
|
|
|
|
|
.arg(desc.qulVersion, oldSdkQtcRequiredVersion.value(desc.qulVersion))
|
|
|
|
|
: McuTarget::tr("Unsupported version \"%1\".")
|
|
|
|
|
.arg(desc.qulVersion);
|
|
|
|
|
printMessage(McuTarget::tr("Skipped %1. %2 Qt for MCUs version >= %3 required.")
|
2020-12-04 16:32:34 +01:00
|
|
|
.arg(
|
|
|
|
|
QDir::toNativeSeparators(pth.fileNameWithPathComponents(1)),
|
2021-03-01 11:07:44 +01:00
|
|
|
qtcSupportText,
|
2020-12-04 16:32:34 +01:00
|
|
|
McuSupportOptions::minimalQulVersion().toString()),
|
|
|
|
|
false);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2020-05-07 12:38:28 +02:00
|
|
|
descriptions.append(desc);
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-01 11:07:44 +01:00
|
|
|
// No valid description means invalid or old SDK installation.
|
|
|
|
|
if (descriptions.empty()) {
|
|
|
|
|
if (kitsPath(dir).exists()) {
|
|
|
|
|
printMessage(McuTarget::tr("No valid kit descriptions found at %1.")
|
|
|
|
|
.arg(kitsPath(dir).toUserOutput()), true);
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
QString deprecationMessage;
|
|
|
|
|
if (checkDeprecatedSdkError(dir, deprecationMessage)) {
|
|
|
|
|
printMessage(deprecationMessage, true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-12-04 16:32:34 +01:00
|
|
|
}
|
|
|
|
|
|
2020-09-18 11:16:37 +02:00
|
|
|
// Workaround for missing JSON file for Desktop target.
|
|
|
|
|
// Desktop JSON file is shipped starting from Qul 1.5.
|
|
|
|
|
// This whole section could be removed when minimalQulVersion will reach 1.5 or above
|
|
|
|
|
{
|
2021-12-08 14:17:27 +01:00
|
|
|
const bool hasDesktopDescription = contains(descriptions, [](const McuTargetDescription &desc) {
|
2021-09-29 17:23:11 +02:00
|
|
|
return desc.platform.type == McuTargetDescription::TargetType::Desktop;
|
2020-09-18 11:16:37 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!hasDesktopDescription) {
|
2021-12-08 14:17:27 +01:00
|
|
|
QVector<FilePath> desktopLibs;
|
|
|
|
|
if (HostOsInfo::isWindowsHost()) {
|
2021-03-15 09:02:09 +01:00
|
|
|
desktopLibs << dir / "lib/QulQuickUltralite_QT_32bpp_Windows_Release.lib"; // older versions of QUL (<1.5?)
|
|
|
|
|
desktopLibs << dir / "lib/QulQuickUltralitePlatform_QT_32bpp_Windows_msvc_Release.lib"; // newer versions of QUL
|
|
|
|
|
} else {
|
|
|
|
|
desktopLibs << dir / "lib/libQulQuickUltralite_QT_32bpp_Linux_Debug.a"; // older versions of QUL (<1.5?)
|
|
|
|
|
desktopLibs << dir / "lib/libQulQuickUltralitePlatform_QT_32bpp_Linux_gnu_Debug.a"; // newer versions of QUL
|
|
|
|
|
}
|
2020-09-18 11:16:37 +02:00
|
|
|
|
2021-12-08 14:17:27 +01:00
|
|
|
if (anyOf(desktopLibs, [](const FilePath &desktopLib) {
|
2021-03-15 09:02:09 +01:00
|
|
|
return desktopLib.exists(); })
|
|
|
|
|
) {
|
2020-09-18 11:16:37 +02:00
|
|
|
McuTargetDescription desktopDescription;
|
|
|
|
|
desktopDescription.qulVersion = descriptions.empty() ?
|
|
|
|
|
McuSupportOptions::minimalQulVersion().toString()
|
|
|
|
|
: descriptions.first().qulVersion;
|
2021-09-29 17:23:11 +02:00
|
|
|
desktopDescription.platform.id = "Qt";
|
|
|
|
|
desktopDescription.platform.name = "Desktop";
|
|
|
|
|
desktopDescription.platform.vendor = "Qt";
|
|
|
|
|
desktopDescription.platform.colorDepths = {32};
|
2021-12-08 14:17:27 +01:00
|
|
|
desktopDescription.toolchain.id = HostOsInfo::isWindowsHost() ? QString("msvc") : QString("gcc");
|
2021-09-29 17:23:11 +02:00
|
|
|
desktopDescription.platform.type = McuTargetDescription::TargetType::Desktop;
|
2020-09-18 11:16:37 +02:00
|
|
|
descriptions.prepend(desktopDescription);
|
2020-12-04 16:32:34 +01:00
|
|
|
} else {
|
2021-12-08 14:17:27 +01:00
|
|
|
// show error only on 1.x SDKs, but skip on 2.x
|
|
|
|
|
const FilePath desktopLibV2 = HostOsInfo::isWindowsHost() ?
|
|
|
|
|
dir / "lib/QulPlatform_qt_32bpp_Windows_msvc_Release.lib"
|
|
|
|
|
: dir / "lib/libQulPlatform_qt_32bpp_Linux_gnu_Release.a";
|
|
|
|
|
if (dir.exists() && !desktopLibV2.exists())
|
2021-03-15 09:02:09 +01:00
|
|
|
printMessage(McuTarget::tr("Skipped creating fallback desktop kit: Could not find any of %1.")
|
2021-12-08 14:17:27 +01:00
|
|
|
.arg(transform(desktopLibs, [](const auto &path) {
|
2021-03-15 09:02:09 +01:00
|
|
|
return QDir::toNativeSeparators(path.fileNameWithPathComponents(1));
|
|
|
|
|
}).toList().join(" or ")),
|
2020-12-04 16:32:34 +01:00
|
|
|
false);
|
2020-09-18 11:16:37 +02:00
|
|
|
}
|
|
|
|
|
}
|
2020-05-07 12:38:28 +02:00
|
|
|
}
|
2020-06-18 19:03:44 +02:00
|
|
|
|
2021-09-29 17:23:11 +02:00
|
|
|
repo->mcuTargets.append(targetsFromDescriptions(descriptions, &(repo->packages)));
|
2020-09-18 11:16:37 +02:00
|
|
|
|
|
|
|
|
// Keep targets sorted lexicographically
|
2021-09-29 17:23:11 +02:00
|
|
|
std::sort(repo->mcuTargets.begin(), repo->mcuTargets.end(), [] (const McuTarget* lhs, const McuTarget* rhs) {
|
2020-09-18 11:16:37 +02:00
|
|
|
return McuSupportOptions::kitName(lhs) < McuSupportOptions::kitName(rhs);
|
|
|
|
|
});
|
2020-03-12 14:25:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Sdk
|
|
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace McuSupport
|