McuSupport: Prepare support for more toolchains than GNU Arm Embedded

Move all hardcoded arm-specific strings and code into the new
McuToolChainPackage class (which will later support IAR and KEIL).

In the same change: Adjust paths in CMake options to latest Qul path
changes in the master branch.

Change-Id: Iefa205729588a3efa783eb9eaaa339ed9f8e2813
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
Alessandro Portale
2020-02-26 16:41:52 +01:00
parent 42b595d865
commit daa9804699
3 changed files with 154 additions and 101 deletions

View File

@@ -195,12 +195,101 @@ void McuPackage::updateStatus()
m_infoLabel->setText(statusText); m_infoLabel->setText(statusText);
} }
McuToolChainPackage::McuToolChainPackage(const QString &label, const QString &defaultPath,
const QString &detectionPath, const QString &settingsKey,
McuToolChainPackage::Type type)
: McuPackage(label, defaultPath, detectionPath, settingsKey)
, m_type(type)
{
}
McuToolChainPackage::Type McuToolChainPackage::type() const
{
return m_type;
}
static ProjectExplorer::ToolChain* armGccToolChain(const Utils::FilePath &path, Core::Id language)
{
using namespace ProjectExplorer;
ToolChain *toolChain = ToolChainManager::toolChain([&path, language](const ToolChain *t){
return t->compilerCommand() == path && t->language() == language;
});
if (!toolChain) {
ToolChainFactory *gccFactory =
Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), [](ToolChainFactory *f){
return f->supportedToolChainType() == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID;
});
if (gccFactory) {
const QList<ToolChain*> detected = gccFactory->detectForImport({path, language});
if (!detected.isEmpty()) {
toolChain = detected.first();
toolChain->setDetection(ToolChain::ManualDetection);
toolChain->setDisplayName("Arm GCC");
ToolChainManager::registerToolChain(toolChain);
}
}
}
return toolChain;
}
ProjectExplorer::ToolChain *McuToolChainPackage::toolChain(Core::Id language) const
{
const QLatin1String compilerName(
language == ProjectExplorer::Constants::C_LANGUAGE_ID ? "gcc" : "g++");
const Utils::FilePath compiler = Utils::FilePath::fromUserInput(
Utils::HostOsInfo::withExecutableSuffix(
path() + (
m_type == TypeArmGcc
? "/bin/arm-none-eabi-%1" : m_type == TypeIAR
? "/foo/bar-iar-%1" : "/bar/foo-keil-%1")).arg(compilerName));
ProjectExplorer::ToolChain *tc = armGccToolChain(compiler, language);
return tc;
}
QString McuToolChainPackage::cmakeToolChainFileName() const
{
return QLatin1String(m_type == TypeArmGcc
? "armgcc.cmake" : m_type == McuToolChainPackage::TypeIAR
? "iar.cmake" : "keil.cmake");
}
QVariant McuToolChainPackage::debuggerId() const
{
using namespace Debugger;
const Utils::FilePath command = Utils::FilePath::fromUserInput(
Utils::HostOsInfo::withExecutableSuffix(path() + (
m_type == TypeArmGcc
? "/bin/arm-none-eabi-gdb-py" : m_type == TypeIAR
? "/foo/bar-iar-gdb" : "/bar/foo-keil-gdb")));
const DebuggerItem *debugger = DebuggerItemManager::findByCommand(command);
QVariant debuggerId;
if (!debugger) {
DebuggerItem newDebugger;
newDebugger.setCommand(command);
const QString displayName =
m_type == TypeArmGcc
? tr("Arm GDB at %1") : m_type == TypeIAR
? QLatin1String("/foo/bar-iar-gdb") : QLatin1String("/bar/foo-keil-gdb");
newDebugger.setUnexpandedDisplayName(displayName.arg(command.toUserOutput()));
debuggerId = DebuggerItemManager::registerDebugger(newDebugger);
} else {
debuggerId = debugger->id();
}
return debuggerId;
}
McuTarget::McuTarget(const QString &vendor, const QString &platform, McuTarget::McuTarget(const QString &vendor, const QString &platform,
const QVector<McuPackage*> &packages) const QVector<McuPackage *> &packages, McuToolChainPackage *toolChainPackage)
: m_vendor(vendor) : m_vendor(vendor)
, m_qulPlatform(platform) , m_qulPlatform(platform)
, m_packages(packages) , m_packages(packages)
, m_toolChainPackage(toolChainPackage)
{ {
QTC_CHECK(m_toolChainPackage == nullptr || m_packages.contains(m_toolChainPackage));
} }
QString McuTarget::vendor() const QString McuTarget::vendor() const
@@ -213,14 +302,9 @@ QVector<McuPackage *> McuTarget::packages() const
return m_packages; return m_packages;
} }
void McuTarget::setToolChainFile(const QString &toolChainFile) McuToolChainPackage *McuTarget::toolChainPackage() const
{ {
m_toolChainFile = toolChainFile; return m_toolChainPackage;
}
QString McuTarget::toolChainFile() const
{
return m_toolChainFile;
} }
QString McuTarget::qulPlatform() const QString McuTarget::qulPlatform() const
@@ -269,7 +353,7 @@ static McuPackage *createQtForMCUsPackage()
return result; return result;
} }
static McuPackage *createArmGccPackage() static McuToolChainPackage *createArmGccPackage()
{ {
const char envVar[] = "ARMGCC_DIR"; const char envVar[] = "ARMGCC_DIR";
@@ -290,11 +374,12 @@ static McuPackage *createArmGccPackage()
if (defaultPath.isEmpty()) if (defaultPath.isEmpty())
defaultPath = QDir::homePath(); defaultPath = QDir::homePath();
auto result = new McuPackage( auto result = new McuToolChainPackage(
McuPackage::tr("GNU Arm Embedded Toolchain"), McuPackage::tr("GNU Arm Embedded Toolchain"),
defaultPath, defaultPath,
Utils::HostOsInfo::withExecutableSuffix("bin/arm-none-eabi-g++"), Utils::HostOsInfo::withExecutableSuffix("bin/arm-none-eabi-g++"),
"GNUArmEmbeddedToolchain"); "GNUArmEmbeddedToolchain",
McuToolChainPackage::TypeArmGcc);
result->setDownloadUrl( result->setDownloadUrl(
"https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads"); "https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads");
result->setEnvironmentVariableName(envVar); result->setEnvironmentVariableName(envVar);
@@ -368,19 +453,19 @@ static McuPackage *createSeggerJLinkPackage()
McuSupportOptions::McuSupportOptions(QObject *parent) McuSupportOptions::McuSupportOptions(QObject *parent)
: QObject(parent) : QObject(parent)
, qtForMCUsSdkPackage(createQtForMCUsPackage())
{ {
qtForMCUsSdkPackage = createQtForMCUsPackage(); McuToolChainPackage* armGccPackage = createArmGccPackage();
armGccPackage = createArmGccPackage();
McuPackage* stm32CubeFwF7SdkPackage = createStm32CubeFwF7SdkPackage(); McuPackage* stm32CubeFwF7SdkPackage = createStm32CubeFwF7SdkPackage();
McuPackage* stm32CubeProgrammerPackage = createStm32CubeProgrammerPackage(); McuPackage* stm32CubeProgrammerPackage = createStm32CubeProgrammerPackage();
McuPackage* evkbImxrt1050SdkPackage = createEvkbImxrt1050SdkPackage(); McuPackage* evkbImxrt1050SdkPackage = createEvkbImxrt1050SdkPackage();
McuPackage* seggerJLinkPackage = createSeggerJLinkPackage(); McuPackage* seggerJLinkPackage = createSeggerJLinkPackage();
auto stmEvalPackages = { QVector<McuPackage*> stmEvalPackages = {
armGccPackage, stm32CubeProgrammerPackage, qtForMCUsSdkPackage}; armGccPackage, stm32CubeProgrammerPackage, qtForMCUsSdkPackage};
auto nxpEvalPackages = { QVector<McuPackage*> nxpEvalPackages = {
armGccPackage, seggerJLinkPackage, qtForMCUsSdkPackage}; armGccPackage, seggerJLinkPackage, qtForMCUsSdkPackage};
auto desktopPackages = { QVector<McuPackage*> desktopPackages = {
qtForMCUsSdkPackage}; qtForMCUsSdkPackage};
packages = { packages = {
armGccPackage, stm32CubeFwF7SdkPackage, stm32CubeProgrammerPackage, evkbImxrt1050SdkPackage, armGccPackage, stm32CubeFwF7SdkPackage, stm32CubeProgrammerPackage, evkbImxrt1050SdkPackage,
@@ -390,30 +475,25 @@ McuSupportOptions::McuSupportOptions(QObject *parent)
const QString vendorNxp = "NXP"; const QString vendorNxp = "NXP";
const QString vendorQt = "Qt"; const QString vendorQt = "Qt";
const QString armGccToochainFile = "CMake/toolchain/armgcc.cmake";
// STM // STM
auto mcuTarget = new McuTarget(vendorStm, "STM32F7508-DISCOVERY", stmEvalPackages); auto mcuTarget = new McuTarget(vendorStm, "STM32F7508-DISCOVERY", stmEvalPackages,
mcuTarget->setToolChainFile(armGccToochainFile); armGccPackage);
mcuTarget->setColorDepth(32); mcuTarget->setColorDepth(32);
mcuTargets.append(mcuTarget); mcuTargets.append(mcuTarget);
mcuTarget = new McuTarget(vendorStm, "STM32F7508-DISCOVERY", stmEvalPackages); mcuTarget = new McuTarget(vendorStm, "STM32F7508-DISCOVERY", stmEvalPackages, armGccPackage);
mcuTarget->setToolChainFile(armGccToochainFile);
mcuTarget->setColorDepth(16); mcuTarget->setColorDepth(16);
mcuTargets.append(mcuTarget); mcuTargets.append(mcuTarget);
mcuTarget = new McuTarget(vendorStm, "STM32F769I-DISCOVERY", stmEvalPackages); mcuTarget = new McuTarget(vendorStm, "STM32F769I-DISCOVERY", stmEvalPackages, armGccPackage);
mcuTarget->setToolChainFile(armGccToochainFile);
mcuTargets.append(mcuTarget); mcuTargets.append(mcuTarget);
// NXP // NXP
mcuTarget = new McuTarget(vendorNxp, "MIMXRT1050-EVK", nxpEvalPackages); mcuTarget = new McuTarget(vendorNxp, "MIMXRT1050-EVK", nxpEvalPackages, armGccPackage);
mcuTarget->setToolChainFile(armGccToochainFile);
mcuTargets.append(mcuTarget); mcuTargets.append(mcuTarget);
// Desktop (Qt) // Desktop (Qt)
mcuTarget = new McuTarget(vendorQt, "Qt", desktopPackages); mcuTarget = new McuTarget(vendorQt, "Qt", desktopPackages, nullptr);
mcuTarget->setColorDepth(32); mcuTarget->setColorDepth(32);
mcuTargets.append(mcuTarget); mcuTargets.append(mcuTarget);
@@ -431,32 +511,6 @@ McuSupportOptions::~McuSupportOptions()
mcuTargets.clear(); mcuTargets.clear();
} }
static ProjectExplorer::ToolChain* armGccToolchain(const Utils::FilePath &path, Core::Id language)
{
using namespace ProjectExplorer;
ToolChain *toolChain = ToolChainManager::toolChain([&path, language](const ToolChain *t){
return t->compilerCommand() == path && t->language() == language;
});
if (!toolChain) {
ToolChainFactory *gccFactory =
Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), [](ToolChainFactory *f){
return f->supportedToolChainType() == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID;
});
if (gccFactory) {
const QList<ToolChain*> detected = gccFactory->detectForImport({path, language});
if (!detected.isEmpty()) {
toolChain = detected.first();
toolChain->setDetection(ToolChain::ManualDetection);
toolChain->setDisplayName("Arm GCC");
ToolChainManager::registerToolChain(toolChain);
}
}
}
return toolChain;
}
static bool mcuTargetIsDesktop(const McuTarget* mcuTarget) static bool mcuTargetIsDesktop(const McuTarget* mcuTarget)
{ {
return mcuTarget->qulPlatform() == "Qt"; return mcuTarget->qulPlatform() == "Qt";
@@ -492,48 +546,22 @@ static void setKitProperties(const QString &kitName, ProjectExplorer::Kit *k,
} }
} }
static void setKitToolchains(ProjectExplorer::Kit *k, const QString &armGccPath) static void setKitToolchains(ProjectExplorer::Kit *k, const McuToolChainPackage *tcPackage)
{ {
using namespace ProjectExplorer; ProjectExplorer::ToolChainKitAspect::setToolChain(k, tcPackage->toolChain(
ProjectExplorer::Constants::C_LANGUAGE_ID));
const QString compileNameScheme = Utils::HostOsInfo::withExecutableSuffix( ProjectExplorer::ToolChainKitAspect::setToolChain(k, tcPackage->toolChain(
armGccPath + "/bin/arm-none-eabi-%1"); ProjectExplorer::Constants::CXX_LANGUAGE_ID));
ToolChain *cTc = armGccToolchain(
Utils::FilePath::fromUserInput(compileNameScheme.arg("gcc")),
ProjectExplorer::Constants::C_LANGUAGE_ID);
ToolChain *cxxTc = armGccToolchain(
Utils::FilePath::fromUserInput(compileNameScheme.arg("g++")),
ProjectExplorer::Constants::CXX_LANGUAGE_ID);
ToolChainKitAspect::setToolChain(k, cTc);
ToolChainKitAspect::setToolChain(k, cxxTc);
} }
static void setKitDebugger(ProjectExplorer::Kit *k, const QString &armGccPath) static void setKitDebugger(ProjectExplorer::Kit *k, const McuToolChainPackage *tcPackage)
{ {
using namespace Debugger; Debugger::DebuggerKitAspect::setDebugger(k, tcPackage->debuggerId());
const Utils::FilePath command = Utils::FilePath::fromUserInput(
Utils::HostOsInfo::withExecutableSuffix(armGccPath + "/bin/arm-none-eabi-gdb-py"));
const DebuggerItem *debugger = DebuggerItemManager::findByCommand(command);
QVariant debuggerId;
if (!debugger) {
DebuggerItem newDebugger;
newDebugger.setCommand(command);
newDebugger.setUnexpandedDisplayName(
McuPackage::tr("Arm GDB at %1").arg(command.toUserOutput()));
debuggerId = DebuggerItemManager::registerDebugger(newDebugger);
} else {
debuggerId = debugger->id();
}
DebuggerKitAspect::setDebugger(k, debuggerId);
} }
static void setKitDevice(ProjectExplorer::Kit *k) static void setKitDevice(ProjectExplorer::Kit *k)
{ {
using namespace ProjectExplorer; ProjectExplorer::DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DEVICE_TYPE);
DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DEVICE_TYPE);
} }
static void setKitEnvironment(ProjectExplorer::Kit *k, const McuTarget* mcuTarget) static void setKitEnvironment(ProjectExplorer::Kit *k, const McuTarget* mcuTarget)
@@ -564,11 +592,13 @@ static void setKitCMakeOptions(ProjectExplorer::Kit *k, const McuTarget* mcuTarg
CMakeConfig config = CMakeConfigurationKitAspect::configuration(k); CMakeConfig config = CMakeConfigurationKitAspect::configuration(k);
config.append(CMakeConfigItem("CMAKE_CXX_COMPILER", "%{Compiler:Executable:Cxx}")); config.append(CMakeConfigItem("CMAKE_CXX_COMPILER", "%{Compiler:Executable:Cxx}"));
config.append(CMakeConfigItem("CMAKE_C_COMPILER", "%{Compiler:Executable:C}")); config.append(CMakeConfigItem("CMAKE_C_COMPILER", "%{Compiler:Executable:C}"));
if (!mcuTarget->toolChainFile().isEmpty()) if (mcuTarget->toolChainPackage())
config.append(CMakeConfigItem("CMAKE_TOOLCHAIN_FILE", config.append(CMakeConfigItem(
(qulDir + "/" + mcuTarget->toolChainFile()).toUtf8())); "CMAKE_TOOLCHAIN_FILE",
(qulDir + "/lib/cmake/Qul/toolchain/"
+ mcuTarget->toolChainPackage()->cmakeToolChainFileName()).toUtf8()));
config.append(CMakeConfigItem("QUL_GENERATORS", config.append(CMakeConfigItem("QUL_GENERATORS",
(qulDir + "/CMake/QulGenerators.cmake").toUtf8())); (qulDir + "/lib/cmake/Qul/QulGenerators.cmake").toUtf8()));
config.append(CMakeConfigItem("QUL_PLATFORM", config.append(CMakeConfigItem("QUL_PLATFORM",
mcuTarget->qulPlatform().toUtf8())); mcuTarget->qulPlatform().toUtf8()));
if (mcuTargetIsDesktop(mcuTarget)) if (mcuTargetIsDesktop(mcuTarget))
@@ -607,15 +637,13 @@ ProjectExplorer::Kit *McuSupportOptions::newKit(const McuTarget *mcuTarget)
{ {
using namespace ProjectExplorer; using namespace ProjectExplorer;
const QString armGccPath = armGccPackage->path();
const QString qulDir = qtForMCUsSdkPackage->path();
const auto init = [this, mcuTarget](Kit *k) { const auto init = [this, mcuTarget](Kit *k) {
KitGuard kitGuard(k); KitGuard kitGuard(k);
setKitProperties(kitName(mcuTarget), k, mcuTarget); setKitProperties(kitName(mcuTarget), k, mcuTarget);
if (!mcuTargetIsDesktop(mcuTarget)) { if (!mcuTargetIsDesktop(mcuTarget)) {
setKitToolchains(k, armGccPackage->path()); setKitToolchains(k, mcuTarget->toolChainPackage());
setKitDebugger(k, armGccPackage->path()); setKitDebugger(k, mcuTarget->toolChainPackage());
setKitDevice(k); setKitDevice(k);
} }
setKitEnvironment(k, mcuTarget); setKitEnvironment(k, mcuTarget);

View File

@@ -30,6 +30,10 @@
QT_FORWARD_DECLARE_CLASS(QWidget) QT_FORWARD_DECLARE_CLASS(QWidget)
namespace Core {
class Id;
}
namespace Utils { namespace Utils {
class PathChooser; class PathChooser;
class InfoLabel; class InfoLabel;
@@ -37,6 +41,7 @@ class InfoLabel;
namespace ProjectExplorer { namespace ProjectExplorer {
class Kit; class Kit;
class ToolChain;
} }
namespace McuSupport { namespace McuSupport {
@@ -55,6 +60,7 @@ public:
McuPackage(const QString &label, const QString &defaultPath, const QString &detectionPath, McuPackage(const QString &label, const QString &defaultPath, const QString &detectionPath,
const QString &settingsKey); const QString &settingsKey);
virtual ~McuPackage() = default;
QString path() const; QString path() const;
QString label() const; QString label() const;
@@ -95,17 +101,38 @@ private:
Status m_status = InvalidPath; Status m_status = InvalidPath;
}; };
class McuToolChainPackage : public McuPackage
{
public:
enum Type {
TypeArmGcc,
TypeIAR,
TypeKEIL
};
McuToolChainPackage(const QString &label, const QString &defaultPath,
const QString &detectionPath, const QString &settingsKey, Type type);
Type type() const;
ProjectExplorer::ToolChain *toolChain(Core::Id language) const;
QString cmakeToolChainFileName() const;
QVariant debuggerId() const;
private:
const Type m_type;
};
class McuTarget : public QObject class McuTarget : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
McuTarget(const QString &vendor, const QString &platform, const QVector<McuPackage *> &packages); McuTarget(const QString &vendor, const QString &platform, const QVector<McuPackage *> &packages,
McuToolChainPackage *toolChainPackage);
QString vendor() const; QString vendor() const;
QVector<McuPackage *> packages() const; QVector<McuPackage *> packages() const;
void setToolChainFile(const QString &toolChainFile); McuToolChainPackage *toolChainPackage() const;
QString toolChainFile() const;
QString qulPlatform() const; QString qulPlatform() const;
void setColorDepth(int colorDepth); void setColorDepth(int colorDepth);
int colorDepth() const; int colorDepth() const;
@@ -115,7 +142,7 @@ private:
const QString m_vendor; const QString m_vendor;
const QString m_qulPlatform; const QString m_qulPlatform;
const QVector<McuPackage*> m_packages; const QVector<McuPackage*> m_packages;
QString m_toolChainFile; McuToolChainPackage *m_toolChainPackage;
int m_colorDepth = -1; int m_colorDepth = -1;
}; };
@@ -129,7 +156,6 @@ public:
QVector<McuPackage*> packages; QVector<McuPackage*> packages;
QVector<McuTarget*> mcuTargets; QVector<McuTarget*> mcuTargets;
McuPackage *armGccPackage = nullptr;
McuPackage *qtForMCUsSdkPackage = nullptr; McuPackage *qtForMCUsSdkPackage = nullptr;
QString kitName(const McuTarget* mcuTarget) const; QString kitName(const McuTarget* mcuTarget) const;

View File

@@ -183,7 +183,6 @@ void McuSupportOptionsWidget::apply()
for (auto package : m_options.packages) for (auto package : m_options.packages)
package->writeToSettings(); package->writeToSettings();
QTC_ASSERT(m_options.armGccPackage, return);
QTC_ASSERT(m_options.qtForMCUsSdkPackage, return); QTC_ASSERT(m_options.qtForMCUsSdkPackage, return);
if (!isVisible() || !cMakeAvailable()) if (!isVisible() || !cMakeAvailable())