McuSupport: Separate toolchain file and compiler packages

Toolchain package represents information about compiler and toolchain
file (.cmake). This information is parsed from JSON and used for Kit
creation. This includes cmake variables, path to compiler. This patch
extracts information about toolchain file into separate McuPackage.

Change-Id: Id165bdc5afa5d7cf5b5c96620e11cb878254c181
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
Piotr Mućko
2022-04-25 19:52:29 +02:00
parent 9770b1d025
commit 3c3ea74ca2
24 changed files with 893 additions and 293 deletions

View File

@@ -24,19 +24,23 @@
****************************************************************************/
#include "unittest.h"
#include "armgcc_nxp_1050_json.h"
#include "armgcc_nxp_mimxrt1170_evk_freertos_json.h"
#include "armgcc_stm32f769i_freertos_json.h"
#include "armgcc_stm32h750b_metal_json.h"
#include "gcc_desktop_json.h"
#include "ghs_rh850_d1m1a_baremetal_json.h"
#include "iar_nxp_1064_json.h"
#include "iar_stm32f469i_metal_json.h"
#include "mcuhelpers.h"
#include "mcukitmanager.h"
#include "mculegacyconstants.h"
#include "mcusupportconstants.h"
#include "mcusupportsdk.h"
#include "mcusupportoptions.h"
#include "mcutargetdescription.h"
#include "mcutargetfactory.h"
#include "mcutargetfactorylegacy.h"
#include <baremetal/baremetalconstants.h>
@@ -45,6 +49,8 @@
#include <gmock/gmock-actions.h>
#include <gmock/gmock.h>
#include <projectexplorer/customtoolchain.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/toolchain.h>
#include <projectexplorer/toolchainmanager.h>
#include <utils/algorithm.h>
@@ -59,30 +65,50 @@
namespace McuSupport::Internal::Test {
namespace {
const char id[]{"target_id"};
const char name[]{"target_name"};
const char vendor[]{"target_vendor"};
const char armgcc[]{"armgcc"};
const char cmakeExtension[]{".cmake"};
const char defaultfreeRtosPath[]{"/opt/freertos/default"};
const char empty[]{""};
const char armGccDir[]{"/opt/armgcc"};
const char armGccDirectorySetting[]{"GNUArmEmbeddedToolchain"};
const char armGccEnvVar[]{"ARMGCC_DIR"};
const char armGccLabel[]{"GNU Arm Embedded Toolchain"};
const char armGccToolchainFilePath[]{"/opt/qtformcu/2.2/lib/cmake/Qul/toolchain/armgcc.cmake"};
const char armGcc[]{"armgcc"};
const char cmakeToolchainLabel[]{"CMake Toolchain File"};
const char freeRtosCMakeVar[]{"FREERTOS_DIR"};
const char freeRtosDescription[]{"Freertos directory"};
const char freeRtosEnvVar[]{"EVK_MIMXRT1170_FREERTOS_PATH"};
const char gcc[]{"armgcc"};
const char freeRtosLabel[]{"FreeRTOS directory"};
const char freeRtosPath[]{"/opt/freertos/default"};
const char freeRtosSetting[]{"Freertos"};
const char greenhillToolchainFilePath[]{"/opt/qtformcu/2.2/lib/cmake/Qul/toolchain/ghs.cmake"};
const char greenhillCompilerDir[]{"/abs/ghs"};
const char greenhillSetting[]{"GHSToolchain"};
const char iarDir[]{"/opt/iar/compiler"};
const char iarEnvVar[]{"IAR_ARM_COMPILER_DIR"};
const char iarLabel[]{"IAR ARM Compiler"};
const char iarSetting[]{"IARToolchain"};
const char iarToolchainFilePath[]{"/opt/qtformcu/2.2/lib/cmake/Qul/toolchain/iar.cmake"};
const char iar[]{"iar"};
const char id[]{"target_id"};
const char name[]{"target_name"};
const char nxp1050FreeRtosEnvVar[]{"IMXRT1050_FREERTOS_DIR"};
const char nxp1050[]{"IMXRT1050"};
const char nxp1064FreeRtosEnvVar[]{"IMXRT1064_FREERTOS_DIR"};
const char nxp1064[]{"IMXRT1064"};
const char nxp1170FreeRtosEnvVar[]{"EVK_MIMXRT1170_FREERTOS_PATH"};
const char nxp1170[]{"EVK_MIMXRT1170"};
const char qtForMcuSdkPath[]{"/opt/qtformcu/2.2"};
const char qulCmakeVar[]{"Qul_ROOT"};
const char qulEnvVar[]{"Qul_DIR"};
const char stm32f7FreeRtosEnvVar[]{"STM32F7_FREERTOS_DIR"};
const char stm32f7[]{"STM32F7"};
const char unsupported[]{"unsupported"};
const char cmakeToolchainLabel[]{"CMake Toolchain File"};
const char vendor[]{"target_vendor"};
const QString settingsPrefix = QLatin1String(Constants::SETTINGS_GROUP) + '/'
+ QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX);
const char qmlToCppSuffixPath[]{"bin/qmltocpp"};
const QString unsupportedToolchainFilePath = QString{qtForMcuSdkPath}
+ "/lib/cmake/Qul/toolchain/unsupported.cmake";
const QStringList jsonFiles{QString::fromUtf8(armgcc_nxp_1050_json),
QString::fromUtf8(iar_nxp_1064_json)};
@@ -90,14 +116,13 @@ const QStringList jsonFiles{QString::fromUtf8(armgcc_nxp_1050_json),
const bool runLegacy{true};
const int colorDepth{32};
const Sdk::McuTargetDescription::Platform platform{id,
"",
"",
{colorDepth},
Sdk::McuTargetDescription::TargetType::MCU};
const Sdk::McuTargetDescription::Platform
platformDescription{id, "", "", {colorDepth}, Sdk::McuTargetDescription::TargetType::MCU};
const Utils::Id cxxLanguageId{ProjectExplorer::Constants::CXX_LANGUAGE_ID};
} // namespace
using namespace Utils;
using CMakeProjectManager::CMakeConfigItem;
using CMakeProjectManager::CMakeConfigurationKitAspect;
using ProjectExplorer::EnvironmentKitAspect;
@@ -106,13 +131,18 @@ using ProjectExplorer::KitManager;
using ProjectExplorer::ToolChain;
using ProjectExplorer::ToolChainManager;
using testing::_;
using testing::Return;
using Utils::FilePath;
void verifyIarToolchain(const McuToolChainPackage *iarToolchainPackage)
void verifyIarToolchain(const McuToolChainPackagePtr &iarToolchainPackage)
{
ProjectExplorer::ToolChainFactory toolchainFactory;
Id iarId{BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID};
ToolChain *iarToolchain{toolchainFactory.createToolChain(iarId)};
iarToolchain->setLanguage(cxxLanguageId);
ToolChainManager::instance()->registerToolChain(iarToolchain);
QVERIFY(iarToolchainPackage != nullptr);
QCOMPARE(iarToolchainPackage->cmakeToolChainFileName(), QString{iar}.append(cmakeExtension));
QCOMPARE(iarToolchainPackage->cmakeVariableName(), Constants::TOOLCHAIN_DIR_CMAKE_VARIABLE);
QCOMPARE(iarToolchainPackage->environmentVariableName(), iarEnvVar);
QCOMPARE(iarToolchainPackage->isDesktopToolchain(), false);
@@ -120,22 +150,38 @@ void verifyIarToolchain(const McuToolChainPackage *iarToolchainPackage)
QCOMPARE(iarToolchainPackage->toolchainType(), McuToolChainPackage::ToolChainType::IAR);
QCOMPARE(iarToolchainPackage->label(), iarLabel);
ProjectExplorer::ToolChainFactory toolchainFactory;
Utils::Id iarId{BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID};
ToolChain *iar{toolchainFactory.createToolChain(iarId)};
iar->setLanguage(cxxLanguageId);
ToolChainManager::instance()->registerToolChain(iar);
ToolChain *iarToolchain{iarToolchainPackage->toolChain(cxxLanguageId)};
iarToolchain = iarToolchainPackage->toolChain(cxxLanguageId);
QVERIFY(iarToolchain != nullptr);
QCOMPARE(iarToolchain->displayName(), "IAREW");
QCOMPARE(iarToolchain->detection(), ToolChain::UninitializedDetection);
}
void verifyGccToolchain(const McuToolChainPackage *gccPackage)
void verifyArmGccToolchain(const McuToolChainPackagePtr &armGccPackage)
{
//Fake register and fake detect compiler.
ProjectExplorer::ToolChainFactory toolchainFactory;
Id armGccId{ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID};
ToolChain *armToolchain{toolchainFactory.createToolChain(armGccId)};
armToolchain->setLanguage(cxxLanguageId);
ToolChainManager::instance()->registerToolChain(armToolchain);
QVERIFY(armGccPackage != nullptr);
QCOMPARE(armGccPackage->cmakeVariableName(), Constants::TOOLCHAIN_DIR_CMAKE_VARIABLE);
QCOMPARE(armGccPackage->environmentVariableName(), armGccEnvVar);
QCOMPARE(armGccPackage->isDesktopToolchain(), false);
QCOMPARE(armGccPackage->toolChainName(), armGcc);
QCOMPARE(armGccPackage->toolchainType(), McuToolChainPackage::ToolChainType::ArmGcc);
QCOMPARE(armGccPackage->settingsKey(), armGccDirectorySetting);
// FIXME(piotr.mucko): Re-enable when toolchains retrieval from McuToolChainPackage is unified for arm and iar.
// armToolchain = armGccPackage->toolChain(cxxLanguageId);
// QVERIFY(armToolchain != nullptr);
}
void verifyGccToolchain(const McuToolChainPackagePtr &gccPackage)
{
QVERIFY(gccPackage != nullptr);
QCOMPARE(gccPackage->cmakeToolChainFileName(), QString{unsupported}.append(cmakeExtension));
QCOMPARE(gccPackage->cmakeVariableName(), "");
QCOMPARE(gccPackage->environmentVariableName(), "");
QCOMPARE(gccPackage->isDesktopToolchain(), true);
@@ -143,25 +189,71 @@ void verifyGccToolchain(const McuToolChainPackage *gccPackage)
QCOMPARE(gccPackage->toolchainType(), McuToolChainPackage::ToolChainType::GCC);
}
void verifyTargetToolchains(const Targets &targets,
const QString &toolchainFilePath,
const QString &compilerPath,
const QString &compilerSetting)
{
QCOMPARE(targets.size(), 1);
const auto &target{targets.first()};
const auto toolchainFile{target->toolChainFilePackage()};
QVERIFY(toolchainFile);
QCOMPARE(toolchainFile->cmakeVariableName(), Constants::TOOLCHAIN_FILE_CMAKE_VARIABLE);
QCOMPARE(toolchainFile->settingsKey(), empty);
QCOMPARE(toolchainFile->path().toString(), toolchainFilePath);
const auto toolchainCompiler{target->toolChainPackage()};
QVERIFY(toolchainCompiler);
QCOMPARE(toolchainCompiler->cmakeVariableName(), Constants::TOOLCHAIN_DIR_CMAKE_VARIABLE);
QCOMPARE(toolchainCompiler->path().toUserOutput(), compilerPath);
QCOMPARE(toolchainCompiler->settingsKey(), compilerSetting);
}
McuSupportTest::McuSupportTest()
: targetFactory{settingsMockPtr}
, toolchainPackagePtr{
new McuToolChainPackage{settingsMockPtr,
{}, // label
{}, // defaultPath
{}, // detectionPath
{}, // settingsKey
McuToolChainPackage::ToolChainType::Unsupported, // toolchain type
{}, // cmake var name
{}}} // env var name
{}
, toolchainPackagePtr{new McuToolChainPackage{
settingsMockPtr,
{}, // label
{}, // defaultPath
{}, // detectionPath
{}, // settingsKey
McuToolChainPackage::ToolChainType::Unsupported, // toolchain type
{}, // cmake var name
{}}} // env var name
, armGccToolchainPackagePtr{new McuToolChainPackage{settingsMockPtr,
armGccLabel,
armGccDir,
{}, // validation path
armGccDirectorySetting,
McuToolChainPackage::ToolChainType::ArmGcc,
Constants::TOOLCHAIN_DIR_CMAKE_VARIABLE,
armGccEnvVar}}
, iarToolchainPackagePtr{new McuToolChainPackage{settingsMockPtr,
iarLabel,
iarDir,
{}, // validation path
iarSetting,
McuToolChainPackage::ToolChainType::IAR,
Constants::TOOLCHAIN_DIR_CMAKE_VARIABLE,
iarEnvVar}}
, platform{id, name, vendor}
, mcuTarget{currentQulVersion,
platform,
McuTarget::OS::FreeRTOS,
{sdkPackagePtr, freeRtosPackagePtr},
armGccToolchainPackagePtr,
armGccToolchainFilePackagePtr}
{
testing::Mock::AllowLeak(settingsMockPtr.get());
}
void McuSupportTest::initTestCase()
{
targetDescription = Sdk::McuTargetDescription{
"2.0.1",
"2",
platform,
platformDescription,
Sdk::McuTargetDescription::Toolchain{},
Sdk::McuTargetDescription::BoardSdk{},
Sdk::McuTargetDescription::FreeRTOS{},
@@ -172,19 +264,31 @@ void McuSupportTest::initTestCase()
EXPECT_CALL(*freeRtosPackage, cmakeVariableName())
.WillRepeatedly(Return(QString{freeRtosCMakeVar}));
EXPECT_CALL(*freeRtosPackage, isValidStatus()).WillRepeatedly(Return(true));
EXPECT_CALL(*freeRtosPackage, path())
.WillRepeatedly(Return(FilePath::fromString(defaultfreeRtosPath)));
EXPECT_CALL(*freeRtosPackage, path()).WillRepeatedly(Return(FilePath::fromString(freeRtosPath)));
EXPECT_CALL(*freeRtosPackage, isAddToSystemPath()).WillRepeatedly(Return(true));
EXPECT_CALL(*freeRtosPackage, detectionPath()).WillRepeatedly(Return(Utils::FilePath{}));
EXPECT_CALL(*freeRtosPackage, detectionPath()).WillRepeatedly(Return(FilePath{}));
EXPECT_CALL(*sdkPackage, environmentVariableName())
.WillRepeatedly(Return(QString{freeRtosEnvVar}));
EXPECT_CALL(*sdkPackage, cmakeVariableName()).WillRepeatedly(Return(QString{freeRtosCMakeVar}));
EXPECT_CALL(*sdkPackage, environmentVariableName()).WillRepeatedly(Return(QString{qulEnvVar}));
EXPECT_CALL(*sdkPackage, cmakeVariableName()).WillRepeatedly(Return(QString{qulCmakeVar}));
EXPECT_CALL(*sdkPackage, isValidStatus()).WillRepeatedly(Return(true));
EXPECT_CALL(*sdkPackage, path())
.WillRepeatedly(Return(FilePath::fromString(defaultfreeRtosPath)));
EXPECT_CALL(*sdkPackage, path()).WillRepeatedly(Return(FilePath::fromString(qtForMcuSdkPath)));
EXPECT_CALL(*sdkPackage, isAddToSystemPath()).WillRepeatedly(Return(true));
EXPECT_CALL(*sdkPackage, detectionPath()).WillRepeatedly(Return(Utils::FilePath{}));
EXPECT_CALL(*sdkPackage, detectionPath()).WillRepeatedly(Return(FilePath{}));
EXPECT_CALL(*armGccToolchainFilePackage, environmentVariableName())
.WillRepeatedly(Return(QString{QString{}}));
EXPECT_CALL(*armGccToolchainFilePackage, cmakeVariableName())
.WillRepeatedly(Return(QString{Constants::TOOLCHAIN_FILE_CMAKE_VARIABLE}));
EXPECT_CALL(*armGccToolchainFilePackage, isValidStatus()).WillRepeatedly(Return(true));
EXPECT_CALL(*armGccToolchainFilePackage, path())
.WillRepeatedly(Return(FilePath::fromString(armGccToolchainFilePath)));
EXPECT_CALL(*armGccToolchainFilePackage, isAddToSystemPath()).WillRepeatedly(Return(false));
EXPECT_CALL(*armGccToolchainFilePackage, detectionPath()).WillRepeatedly(Return(FilePath{}));
ON_CALL(*settingsMockPtr, getPath)
.WillByDefault([](const QString &, QSettings::Scope, const FilePath &m_defaultPath) {
return m_defaultPath;
});
}
void McuSupportTest::test_parseBasicInfoFromJson()
@@ -204,67 +308,56 @@ void McuSupportTest::test_parseCmakeEntries()
QCOMPARE(freeRtosPackage.envVar, nxp1064FreeRtosEnvVar);
}
void McuSupportTest::test_parseToolchainFromJSON_data()
{
QTest::addColumn<QString>("json");
QTest::addColumn<QString>("environmentVariable");
QTest::addColumn<QString>("label");
QTest::addColumn<QString>("toolchainFile");
QTest::addColumn<QString>("id");
//TODO(me): Add ghs nxp 1064 nxp 1070.
QTest::newRow("armgcc_nxp_1050_json")
<< armgcc_nxp_1050_json << armGccEnvVar << armGccLabel << armGccToolchainFilePath << armGcc;
QTest::newRow("armgcc_stm32f769i_freertos_json")
<< armgcc_stm32f769i_freertos_json << armGccEnvVar << armGccLabel << armGccToolchainFilePath
<< armGcc;
QTest::newRow("armgcc_stm32h750b_metal_json")
<< armgcc_stm32h750b_metal_json << armGccEnvVar << armGccLabel << armGccToolchainFilePath
<< armGcc;
QTest::newRow("armgcc_nxp_mimxrt1170_evk_freertos_json")
<< armgcc_nxp_mimxrt1170_evk_freertos_json << armGccEnvVar << armGccLabel
<< armGccToolchainFilePath << armGcc;
QTest::newRow("iar_stm32f469i_metal_json")
<< iar_stm32f469i_metal_json << iarEnvVar << iarLabel << iarToolchainFilePath << iar;
}
void McuSupportTest::test_parseToolchainFromJSON()
{
Sdk::McuTargetDescription description{Sdk::parseDescriptionJson(iar_stm32f469i_metal_json)};
QCOMPARE(description.toolchain.id, iar);
QCOMPARE(description.toolchain.packages.size(), 2);
QFETCH(QString, json);
QFETCH(QString, environmentVariable);
QFETCH(QString, label);
QFETCH(QString, toolchainFile);
QFETCH(QString, id);
Sdk::McuTargetDescription description{Sdk::parseDescriptionJson(json.toLocal8Bit())};
QCOMPARE(description.toolchain.id, id);
const Sdk::PackageDescription &compilerPackage{description.toolchain.packages.at(0)};
const Sdk::PackageDescription &compilerPackage{description.toolchain.compiler};
QCOMPARE(compilerPackage.cmakeVar, Constants::TOOLCHAIN_DIR_CMAKE_VARIABLE);
QCOMPARE(compilerPackage.envVar, iarEnvVar);
QCOMPARE(compilerPackage.envVar, environmentVariable);
const Sdk::PackageDescription &toolchainFilePackage{description.toolchain.packages.at(1)};
const Sdk::PackageDescription &toolchainFilePackage{description.toolchain.file};
QCOMPARE(toolchainFilePackage.label, cmakeToolchainLabel);
QCOMPARE(toolchainFilePackage.envVar, QString{});
QCOMPARE(toolchainFilePackage.cmakeVar, Constants::TOOLCHAIN_FILE_CMAKE_VARIABLE);
QCOMPARE(toolchainFilePackage.defaultPath, "$Qul_ROOT/lib/cmake/Qul/toolchain/iar.cmake");
}
void McuSupportTest::test_addNewKit()
{
const QString cmakeVar = "CMAKE_SDK";
EXPECT_CALL(*sdkPackage, cmakeVariableName()).WillRepeatedly(Return(cmakeVar));
Kit kit;
const McuTarget::Platform platform{id, name, vendor};
McuTarget mcuTarget{currentQulVersion, // version
platform, // platform
McuTarget::OS::FreeRTOS, // os
{sdkPackagePtr, freeRtosPackagePtr}, // packages
toolchainPackagePtr}; // toolchain packages
auto &kitManager{*KitManager::instance()};
QSignalSpy kitAddedSpy(&kitManager, &KitManager::kitAdded);
auto *newKit{McuKitManager::newKit(&mcuTarget, sdkPackagePtr)};
QVERIFY(newKit != nullptr);
QCOMPARE(kitAddedSpy.count(), 1);
QList<QVariant> arguments = kitAddedSpy.takeFirst();
auto *createdKit = qvariant_cast<Kit *>(arguments.at(0));
QVERIFY(createdKit != nullptr);
QCOMPARE(createdKit, newKit);
const auto config = CMakeConfigurationKitAspect::configuration(newKit);
QVERIFY(config.size() > 0);
QVERIFY(Utils::indexOf(config.toVector(),
[&cmakeVar](const CMakeConfigItem &item) {
return item.key == cmakeVar.toUtf8();
})
!= -1);
QCOMPARE(toolchainFilePackage.defaultPath.cleanPath().toUserOutput(), toolchainFile);
}
void McuSupportTest::test_addFreeRtosCmakeVarToKit()
{
Kit kit;
const McuTarget::Platform platform{id, name, vendor};
McuTarget mcuTarget{currentQulVersion,
platform,
McuTarget::OS::FreeRTOS,
{sdkPackagePtr, freeRtosPackagePtr},
toolchainPackagePtr};
McuKitManager::upgradeKitInPlace(&kit, &mcuTarget, sdkPackagePtr);
QVERIFY(kit.hasValue(EnvironmentKitAspect::id()));
@@ -273,65 +366,65 @@ void McuSupportTest::test_addFreeRtosCmakeVarToKit()
const auto &cmakeConfig{CMakeConfigurationKitAspect::configuration(&kit)};
QVERIFY(cmakeConfig.size() > 0);
CMakeConfigItem
expectedCmakeVar{freeRtosCMakeVar,
FilePath::fromString(defaultfreeRtosPath).toUserOutput().toLocal8Bit()};
QVERIFY(cmakeConfig.contains(expectedCmakeVar));
QCOMPARE(cmakeConfig.valueOf(freeRtosCMakeVar),
FilePath::fromString(freeRtosPath).toString().toLocal8Bit());
}
void McuSupportTest::test_legacy_createIarToolchain()
{
McuToolChainPackagePtr iarToolchainPackage = Sdk::createIarToolChainPackage(settingsMockPtr);
verifyIarToolchain(iarToolchainPackage.get());
verifyIarToolchain(iarToolchainPackage);
}
void McuSupportTest::test_createIarToolchain()
{
const auto description = Sdk::parseDescriptionJson(iar_stm32f469i_metal_json);
McuToolChainPackage *iarToolchainPackage{targetFactory.createToolchain(description.toolchain)};
McuToolChainPackagePtr iarToolchainPackage{targetFactory.createToolchain(description.toolchain)};
verifyIarToolchain(iarToolchainPackage);
}
void McuSupportTest::test_legacy_createDesktopGccToolchain()
{
McuToolChainPackagePtr gccPackage = Sdk::createGccToolChainPackage(settingsMockPtr);
verifyGccToolchain(gccPackage.get());
verifyGccToolchain(gccPackage);
}
void McuSupportTest::test_createDesktopGccToolchain()
{
const auto description = Sdk::parseDescriptionJson(gcc_desktop_json);
McuToolChainPackage *gccPackage{targetFactory.createToolchain(description.toolchain)};
McuToolChainPackagePtr gccPackage{targetFactory.createToolchain(description.toolchain)};
verifyGccToolchain(gccPackage);
}
void McuSupportTest::test_skipTargetCreationWhenToolchainInfoIsMissing()
void McuSupportTest::test_verifyManuallyCreatedArmGccToolchain()
{
const auto [targets, packages]{targetFactory.createTargets(targetDescription)};
QVERIFY(targets.isEmpty());
verifyArmGccToolchain(armGccToolchainPackagePtr);
}
void McuSupportTest::test_returnNullWhenCreatingToolchainIfInfoIsMissing()
void McuSupportTest::test_legacy_createArmGccToolchain()
{
Sdk::McuTargetDescription::Toolchain toolchainDescription{};
toolchainDescription.id = iar;
McuToolChainPackage *toolchain{targetFactory.createToolchain(toolchainDescription)};
QCOMPARE(toolchain, nullptr);
McuToolChainPackagePtr armGccPackage = Sdk::createArmGccToolchainPackage(settingsMockPtr);
verifyArmGccToolchain(armGccPackage);
}
void McuSupportTest::test_returnNullWhenCreatingToolchainIfIdIsEmpty()
void McuSupportTest::test_createArmGccToolchain_data()
{
McuToolChainPackage *toolchain{targetFactory.createToolchain({})};
QCOMPARE(toolchain, nullptr);
QTest::addColumn<QString>("json");
QTest::newRow("armgcc_nxp_1050_json") << armgcc_nxp_1050_json;
QTest::newRow("armgcc_stm32f769i_freertos_json") << armgcc_stm32f769i_freertos_json;
QTest::newRow("armgcc_stm32h750b_metal_json") << armgcc_stm32h750b_metal_json;
QTest::newRow("armgcc_nxp_mimxrt1170_evk_freertos_json")
<< armgcc_nxp_mimxrt1170_evk_freertos_json;
}
void McuSupportTest::test_defaultToolchainPackageCtorShouldReturnDefaultToolchainFileName()
void McuSupportTest::test_createArmGccToolchain()
{
QVERIFY(!toolchainPackagePtr->cmakeToolChainFileName().isEmpty());
QCOMPARE(toolchainPackagePtr->cmakeToolChainFileName(),
QString{unsupported}.append(cmakeExtension));
QFETCH(QString, json);
const auto description = Sdk::parseDescriptionJson(json.toLocal8Bit());
McuToolChainPackagePtr armGccPackage{targetFactory.createToolchain(description.toolchain)};
verifyArmGccToolchain(armGccPackage);
}
void McuSupportTest::test_mapParsedToolchainIdToCorrespondingType_data()
@@ -358,16 +451,12 @@ void McuSupportTest::test_mapParsedToolchainIdToCorrespondingType()
QCOMPARE(toolchain->toolchainType(), toolchainType);
}
void McuSupportTest::test_createPackagesWithCorrespondingSettings_data()
void McuSupportTest::test_legacy_createPackagesWithCorrespondingSettings_data()
{
QTest::addColumn<QString>("json");
QTest::addColumn<QSet<QString>>("expectedSettings");
QSet<QString> commonSettings{{"CypressAutoFlashUtil"},
{"GHSArmToolchain"},
{"GHSToolchain"},
{"GNUArmEmbeddedToolchain"},
{"IARToolchain"},
{"MCUXpressoIDE"},
{"RenesasFlashProgrammer"},
{"Stm32CubeProgrammer"}};
@@ -375,33 +464,40 @@ void McuSupportTest::test_createPackagesWithCorrespondingSettings_data()
QTest::newRow("nxp1064") << iar_nxp_1064_json
<< QSet<QString>{{"EVK_MIMXRT1064_SDK_PATH"},
{QString{Constants::SETTINGS_KEY_FREERTOS_PREFIX}
.append("IMXRT1064")}}
.append("IMXRT1064")},
"IARToolchain"}
.unite(commonSettings);
QTest::newRow("stm32f469i") << iar_stm32f469i_metal_json
<< QSet<QString>{{"STM32Cube_FW_F4_SDK_PATH"}, "IARToolchain"}.unite(
commonSettings);
QTest::newRow("nxp1050") << armgcc_nxp_1050_json
<< QSet<QString>{{"EVKB_IMXRT1050_SDK_PATH"},
{QString{Constants::SETTINGS_KEY_FREERTOS_PREFIX}
.append("IMXRT1050")}}
.append("IMXRT1050")},
"GNUArmEmbeddedToolchain"}
.unite(commonSettings);
QTest::newRow("stm32h750b") << armgcc_stm32h750b_metal_json
<< QSet<QString>{{"STM32Cube_FW_H7_SDK_PATH"}}.unite(commonSettings);
<< QSet<QString>{{"STM32Cube_FW_H7_SDK_PATH"},
"GNUArmEmbeddedToolchain"}
.unite(commonSettings);
QTest::newRow("stm32f769i") << armgcc_stm32f769i_freertos_json
<< QSet<QString>{{"STM32Cube_FW_F7_SDK_PATH"}}.unite(commonSettings);
<< QSet<QString>{{"STM32Cube_FW_F7_SDK_PATH"},
"GNUArmEmbeddedToolchain"}
.unite(commonSettings);
QTest::newRow("stm32f469i") << iar_stm32f469i_metal_json
<< QSet<QString>{{"STM32Cube_FW_F4_SDK_PATH"}}.unite(commonSettings);
QTest::newRow("ghs_rh850_d1m1a_baremetal_json")
<< ghs_rh850_d1m1a_baremetal_json << QSet<QString>{"GHSToolchain"}.unite(commonSettings);
}
void McuSupportTest::test_createPackagesWithCorrespondingSettings()
void McuSupportTest::test_legacy_createPackagesWithCorrespondingSettings()
{
QFETCH(QString, json);
const Sdk::McuTargetDescription description = Sdk::parseDescriptionJson(json.toLocal8Bit());
const auto [targets,
packages]{Sdk::targetsFromDescriptions({description}, settingsMockPtr, runLegacy)};
const auto [targets, packages]{
Sdk::targetsFromDescriptions({description}, settingsMockPtr, qtForMcuSdkPath, runLegacy)};
Q_UNUSED(targets);
QSet<QString> settings = Utils::transform<QSet<QString>>(packages, [](const auto &package) {
QSet<QString> settings = transform<QSet<QString>>(packages, [](const auto &package) {
return package->settingsKey();
});
QFETCH(QSet<QString>, expectedSettings);
@@ -440,30 +536,26 @@ void McuSupportTest::test_createTargets()
Sdk::PackageDescription packageDescription{id,
nxp1064FreeRtosEnvVar,
freeRtosCMakeVar,
"setting",
"Freertos directory",
"/opt/freertos/1064",
freeRtosSetting,
freeRtosDescription,
freeRtosPath,
"",
{},
true};
targetDescription.freeRTOS.packages.append(packageDescription);
targetDescription.toolchain.id = armgcc;
targetDescription.toolchain.packages.append(Sdk::PackageDescription{});
targetDescription.toolchain.id = armGcc;
const auto [targets, packages]{targetFactory.createTargets(targetDescription)};
const auto [targets, packages]{targetFactory.createTargets(targetDescription, qtForMcuSdkPath)};
QVERIFY(!targets.empty());
const McuTargetPtr target{*targets.constBegin()};
const McuTargetPtr target{targets.at(0)};
QCOMPARE(target->colorDepth(), colorDepth);
const auto &tgtPackages{target->packages()};
QVERIFY(!tgtPackages.empty());
// for whatever reasons there are more than a single package, get the right one to check
const auto rtosPackage
= Utils::findOrDefault(tgtPackages,
[id = QString::fromLatin1(id)](McuPackagePtr pkg) {
return pkg->label() == id;
});
QVERIFY(rtosPackage);
QCOMPARE(rtosPackage->environmentVariableName(), nxp1064FreeRtosEnvVar);
QVERIFY(anyOf(tgtPackages, [](const McuPackagePtr &pkg) {
return (pkg->environmentVariableName() == nxp1064FreeRtosEnvVar
&& pkg->cmakeVariableName() == freeRtosCMakeVar && pkg->label() == id);
}));
}
void McuSupportTest::test_createPackages()
@@ -471,9 +563,9 @@ void McuSupportTest::test_createPackages()
Sdk::PackageDescription packageDescription{id,
nxp1064FreeRtosEnvVar,
freeRtosCMakeVar,
"Freertos directory",
"setting",
"/opt/freertos/1064",
freeRtosLabel,
freeRtosSetting,
freeRtosPath,
"",
{},
true};
@@ -483,7 +575,7 @@ void McuSupportTest::test_createPackages()
QVERIFY(!packages.empty());
}
void McuSupportTest::test_removeRtosSuffix_data()
void McuSupportTest::test_removeRtosSuffixFromEnvironmentVariable_data()
{
QTest::addColumn<QString>("freeRtosEnvVar");
QTest::addColumn<QString>("expectedEnvVarWithoutSuffix");
@@ -494,14 +586,14 @@ void McuSupportTest::test_removeRtosSuffix_data()
QTest::newRow("stm32f7") << stm32f7FreeRtosEnvVar << stm32f7;
}
void McuSupportTest::test_removeRtosSuffix()
void McuSupportTest::test_removeRtosSuffixFromEnvironmentVariable()
{
QFETCH(QString, freeRtosEnvVar);
QFETCH(QString, expectedEnvVarWithoutSuffix);
QCOMPARE(removeRtosSuffix(freeRtosEnvVar), expectedEnvVarWithoutSuffix);
}
void McuSupportTest::test_2dot1UsesLegacyImplementation()
void McuSupportTest::test_twoDotOneUsesLegacyImplementation()
{
QCOMPARE(McuSupportOptions::isLegacyVersion({2, 1}), true);
QCOMPARE(McuSupportOptions::isLegacyVersion({2, 0}), true);
@@ -511,4 +603,144 @@ void McuSupportTest::test_2dot1UsesLegacyImplementation()
QCOMPARE(McuSupportOptions::isLegacyVersion({2, 2, 1}), false);
}
void McuSupportTest::test_addNewKit()
{
const QString cmakeVar = "CMAKE_SDK";
EXPECT_CALL(*sdkPackage, cmakeVariableName()).WillRepeatedly(Return(cmakeVar));
auto &kitManager{*KitManager::instance()};
QSignalSpy kitAddedSpy(&kitManager, &KitManager::kitAdded);
auto *newKit{McuKitManager::newKit(&mcuTarget, sdkPackagePtr)};
QVERIFY(newKit != nullptr);
QCOMPARE(kitAddedSpy.count(), 1);
QList<QVariant> arguments = kitAddedSpy.takeFirst();
auto *createdKit = qvariant_cast<Kit *>(arguments.at(0));
QVERIFY(createdKit != nullptr);
QCOMPARE(createdKit, newKit);
const auto config = CMakeConfigurationKitAspect::configuration(newKit);
QVERIFY(config.size() > 0);
QVERIFY(
indexOf(config.toVector(),
[&cmakeVar](const CMakeConfigItem &item) { return item.key == cmakeVar.toUtf8(); })
!= -1);
}
void McuSupportTest::test_getFullToolchainFilePathFromTarget()
{
QCOMPARE(mcuTarget.toolChainFilePackage()->path().toUserOutput(),
armGccToolchainFilePackagePtr->path().toUserOutput());
}
void McuSupportTest::test_legacy_getPredefinedToolchainFilePackage()
{
QHash<QString, ToolchainCompilerCreator> toolchainCreators{
{armGcc, [this] { return armGccToolchainPackagePtr; }}};
McuTargetFactoryLegacy legacyTargetFactory{toolchainCreators,
{{armGcc, armGccToolchainFilePackagePtr}},
{},
settingsMockPtr};
auto armToolchainFile = legacyTargetFactory.getToolchainFile(qtForMcuSdkPath, armGcc);
QVERIFY(armToolchainFile);
QCOMPARE(armToolchainFile, armGccToolchainFilePackagePtr);
}
void McuSupportTest::test_legacy_createUnsupportedToolchainFilePackage()
{
QHash<QString, ToolchainCompilerCreator> toolchainCreators{
{armGcc, [this] { return armGccToolchainPackagePtr; }}};
McuTargetFactoryLegacy legacyTargetFactory{toolchainCreators,
{{armGcc, armGccToolchainFilePackagePtr}},
{},
settingsMockPtr};
auto unsupportedToolchainFile = legacyTargetFactory.getToolchainFile(qtForMcuSdkPath, iar);
QVERIFY(unsupportedToolchainFile);
QCOMPARE(unsupportedToolchainFile->path().toUserOutput(), unsupportedToolchainFilePath);
QCOMPARE(unsupportedToolchainFile->cmakeVariableName(),
Constants::TOOLCHAIN_FILE_CMAKE_VARIABLE);
}
void McuSupportTest::test_legacy_createTargetWithToolchainPackages_data()
{
QTest::addColumn<QString>("json");
QTest::addColumn<QString>("toolchainFilePath");
QTest::addColumn<QString>("compilerPath");
QTest::addColumn<QString>("compilerSetting");
QTest::newRow("nxp1050") << armgcc_nxp_1050_json << armGccToolchainFilePath << armGccDir
<< armGccDirectorySetting;
QTest::newRow("stm32h750b") << armgcc_stm32h750b_metal_json << armGccToolchainFilePath
<< armGccDir << armGccDirectorySetting;
QTest::newRow("stm32f769i") << armgcc_stm32f769i_freertos_json << armGccToolchainFilePath
<< armGccDir << armGccDirectorySetting;
QTest::newRow("stm32f469i") << iar_stm32f469i_metal_json << iarToolchainFilePath << iarDir
<< iarSetting;
QTest::newRow("nxp1064") << iar_nxp_1064_json << iarToolchainFilePath << iarDir << iarSetting;
QTest::newRow("nxp1064") << iar_nxp_1064_json << iarToolchainFilePath << iarDir << iarSetting;
QTest::newRow("ghs_rh850_d1m1a_baremetal_json")
<< ghs_rh850_d1m1a_baremetal_json << greenhillToolchainFilePath << greenhillCompilerDir
<< greenhillSetting;
}
void McuSupportTest::test_legacy_createTargetWithToolchainPackages()
{
QFETCH(QString, json);
QFETCH(QString, toolchainFilePath);
QFETCH(QString, compilerPath);
QFETCH(QString, compilerSetting);
const Sdk::McuTargetDescription description = Sdk::parseDescriptionJson(json.toLocal8Bit());
EXPECT_CALL(*settingsMockPtr,
getPath(QString{Constants::SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK}, _, _))
.WillRepeatedly(Return(FilePath::fromString(qtForMcuSdkPath)));
EXPECT_CALL(*settingsMockPtr, getPath(compilerSetting, _, _))
.WillRepeatedly(Return(FilePath::fromString(compilerPath)));
const auto [targets, packages]{
Sdk::targetsFromDescriptions({description}, settingsMockPtr, qtForMcuSdkPath, runLegacy)};
Q_UNUSED(packages);
verifyTargetToolchains(targets, toolchainFilePath, compilerPath, compilerSetting);
}
void McuSupportTest::test_createTargetWithToolchainPackages_data()
{
test_legacy_createTargetWithToolchainPackages_data();
}
void McuSupportTest::test_createTargetWithToolchainPackages()
{
QFETCH(QString, json);
QFETCH(QString, toolchainFilePath);
QFETCH(QString, compilerPath);
QFETCH(QString, compilerSetting);
EXPECT_CALL(*settingsMockPtr, getPath(compilerSetting, _, _))
.WillRepeatedly(Return(FilePath::fromString(compilerPath)));
const Sdk::McuTargetDescription description = Sdk::parseDescriptionJson(json.toLocal8Bit());
const auto [targets, packages]{
Sdk::targetsFromDescriptions({description}, settingsMockPtr, qtForMcuSdkPath, !runLegacy)};
Q_UNUSED(packages);
verifyTargetToolchains(targets, toolchainFilePath, compilerPath, compilerSetting);
}
void McuSupportTest::test_addToolchainFileInfoToKit()
{
McuKitManager::upgradeKitInPlace(&kit, &mcuTarget, sdkPackagePtr);
QVERIFY(kit.isValid());
QCOMPARE(kit.value(Constants::KIT_MCUTARGET_TOOLCHAIN_KEY).toString(), armGcc);
const auto &cmakeConfig{CMakeConfigurationKitAspect::configuration(&kit)};
QVERIFY(!cmakeConfig.empty());
QCOMPARE(cmakeConfig.valueOf(Constants::TOOLCHAIN_FILE_CMAKE_VARIABLE), armGccToolchainFilePath);
}
} // namespace McuSupport::Internal::Test