Move mcu deploy step into the mcusupport plugin

This deploy step will run the qmlprojectexporter commandline tool
on the currently active qmlproject if qtForMCUs is set to true.
The output of the tool is shown in the "Compile Output" panel.
Possible configuration issues are shown in the "Issues" panel.
Note that the step is not removed from the list but disabled when
setting qtForMCUs to false in order to retain possible changes made
by the user.

Change-Id: I03b0d6fbe420b49400d48e7365d4395491b9aa2d
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Knud Dollereder
2023-05-03 12:17:28 +02:00
committed by Tim Jenssen
parent 36936196bf
commit 5bf1b598c1
8 changed files with 87 additions and 65 deletions

View File

@@ -23,6 +23,7 @@ add_qtc_plugin(McuSupport
mcuhelpers.cpp mcuhelpers.h mcuhelpers.cpp mcuhelpers.h
settingshandler.cpp settingshandler.h settingshandler.cpp settingshandler.h
mcuqmlprojectnode.cpp mcuqmlprojectnode.h mcuqmlprojectnode.cpp mcuqmlprojectnode.h
mcubuildstep.cpp mcubuildstep.h
) )
add_subdirectory(test) add_subdirectory(test)

View File

@@ -2,7 +2,11 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "mcubuildstep.h" #include "mcubuildstep.h"
#include "qmlprojectmanagertr.h" #include "mcukitmanager.h"
#include "mculegacyconstants.h"
#include "mcusupportconstants.h"
#include <cmakeprojectmanager/cmakekitinformation.h>
#include <projectexplorer/buildstep.h> #include <projectexplorer/buildstep.h>
#include <projectexplorer/buildsteplist.h> #include <projectexplorer/buildsteplist.h>
@@ -14,10 +18,8 @@
#include <projectexplorer/task.h> #include <projectexplorer/task.h>
#include <projectexplorer/taskhub.h> #include <projectexplorer/taskhub.h>
#include <cmakeprojectmanager/cmakekitinformation.h> #include <qmlprojectmanager/qmlprojectmanagertr.h>
#include <mcusupport/mculegacyconstants.h>
#include <mcusupport/mcusupportconstants.h>
#include <qtsupport/qtsupportconstants.h> #include <qtsupport/qtsupportconstants.h>
#include <utils/aspects.h> #include <utils/aspects.h>
@@ -25,7 +27,7 @@
#include <QVersionNumber> #include <QVersionNumber>
namespace QmlProjectManager { namespace McuSupport::Internal {
const Utils::Id DeployMcuProcessStep::id = "QmlProject.Mcu.DeployStep"; const Utils::Id DeployMcuProcessStep::id = "QmlProject.Mcu.DeployStep";
@@ -35,26 +37,17 @@ void DeployMcuProcessStep::showError(const QString &text)
ProjectExplorer::TaskHub::addTask(task); ProjectExplorer::TaskHub::addTask(task);
} }
// TODO:
// - Grabbing *a* kit might not be the best todo.
// Would be better to specify a specific version of Qt4MCU in the qmlproject file.
// Currently we use the kit with the greatest version number.
//
// - Do not compare to *legacy* constants.
// Sounds like they will stop existing at some point.
// Also: Find Constant for QUL_PLATFORM
DeployMcuProcessStep::DeployMcuProcessStep(ProjectExplorer::BuildStepList *bc, Utils::Id id) DeployMcuProcessStep::DeployMcuProcessStep(ProjectExplorer::BuildStepList *bc, Utils::Id id)
: AbstractProcessStep(bc, id) : AbstractProcessStep(bc, id)
, m_tmpDir() , m_tmpDir()
{ {
if (!buildSystem()) { if (!buildSystem()) {
showError(Tr::tr("Failed to find valid build system")); showError(QmlProjectManager::Tr::tr("Failed to find valid build system"));
return; return;
} }
if (!m_tmpDir.isValid()) { if (!m_tmpDir.isValid()) {
showError(Tr::tr("Failed to create valid build directory")); showError(QmlProjectManager::Tr::tr("Failed to create valid build directory"));
return; return;
} }
@@ -62,14 +55,14 @@ DeployMcuProcessStep::DeployMcuProcessStep(ProjectExplorer::BuildStepList *bc, U
if (!kit) if (!kit)
return; return;
QString root = findKitInformation(kit, McuSupport::Internal::Legacy::Constants::QUL_CMAKE_VAR); QString root = findKitInformation(kit, Internal::Legacy::Constants::QUL_CMAKE_VAR);
auto rootPath = Utils::FilePath::fromString(root); auto rootPath = Utils::FilePath::fromString(root);
auto cmd = addAspect<Utils::StringAspect>(); auto cmd = addAspect<Utils::StringAspect>();
cmd->setSettingsKey("QmlProject.Mcu.ProcessStep.Command"); cmd->setSettingsKey("QmlProject.Mcu.ProcessStep.Command");
cmd->setDisplayStyle(Utils::StringAspect::PathChooserDisplay); cmd->setDisplayStyle(Utils::StringAspect::PathChooserDisplay);
cmd->setExpectedKind(Utils::PathChooser::Command); cmd->setExpectedKind(Utils::PathChooser::Command);
cmd->setLabelText(Tr::tr("Command:")); cmd->setLabelText(QmlProjectManager::Tr::tr("Command:"));
cmd->setFilePath(rootPath.pathAppended("/bin/qmlprojectexporter")); cmd->setFilePath(rootPath.pathAppended("/bin/qmlprojectexporter"));
const char *importPathConstant = QtSupport::Constants::KIT_QML_IMPORT_PATH; const char *importPathConstant = QtSupport::Constants::KIT_QML_IMPORT_PATH;
@@ -80,7 +73,7 @@ DeployMcuProcessStep::DeployMcuProcessStep(ProjectExplorer::BuildStepList *bc, U
Utils::ProcessArgs::quoteArg(qulIncludeDir.pathAppended("Timeline").toString()) Utils::ProcessArgs::quoteArg(qulIncludeDir.pathAppended("Timeline").toString())
}; };
const char *toolChainConstant = McuSupport::Internal::Constants::KIT_MCUTARGET_TOOLCHAIN_KEY; const char *toolChainConstant = Internal::Constants::KIT_MCUTARGET_TOOLCHAIN_KEY;
QStringList arguments = { QStringList arguments = {
Utils::ProcessArgs::quoteArg(buildSystem()->projectFilePath().toString()), Utils::ProcessArgs::quoteArg(buildSystem()->projectFilePath().toString()),
"--platform", findKitInformation(kit, "QUL_PLATFORM"), "--platform", findKitInformation(kit, "QUL_PLATFORM"),
@@ -91,14 +84,14 @@ DeployMcuProcessStep::DeployMcuProcessStep(ProjectExplorer::BuildStepList *bc, U
auto args = addAspect<Utils::StringAspect>(); auto args = addAspect<Utils::StringAspect>();
args->setSettingsKey("QmlProject.Mcu.ProcessStep.Arguments"); args->setSettingsKey("QmlProject.Mcu.ProcessStep.Arguments");
args->setDisplayStyle(Utils::StringAspect::LineEditDisplay); args->setDisplayStyle(Utils::StringAspect::LineEditDisplay);
args->setLabelText(Tr::tr("Arguments:")); args->setLabelText(QmlProjectManager::Tr::tr("Arguments:"));
args->setValue(Utils::ProcessArgs::joinArgs(arguments)); args->setValue(Utils::ProcessArgs::joinArgs(arguments));
auto outDir = addAspect<Utils::StringAspect>(); auto outDir = addAspect<Utils::StringAspect>();
outDir->setSettingsKey("QmlProject.Mcu.ProcessStep.BuildDirectory"); outDir->setSettingsKey("QmlProject.Mcu.ProcessStep.BuildDirectory");
outDir->setDisplayStyle(Utils::StringAspect::PathChooserDisplay); outDir->setDisplayStyle(Utils::StringAspect::PathChooserDisplay);
outDir->setExpectedKind(Utils::PathChooser::Directory); outDir->setExpectedKind(Utils::PathChooser::Directory);
outDir->setLabelText(Tr::tr("Build directory:")); outDir->setLabelText(QmlProjectManager::Tr::tr("Build directory:"));
outDir->setPlaceHolderText(m_tmpDir.path()); outDir->setPlaceHolderText(m_tmpDir.path());
setCommandLineProvider([this, cmd, args, outDir]() -> Utils::CommandLine { setCommandLineProvider([this, cmd, args, outDir]() -> Utils::CommandLine {
@@ -116,7 +109,6 @@ DeployMcuProcessStep::DeployMcuProcessStep(ProjectExplorer::BuildStepList *bc, U
QString DeployMcuProcessStep::findKitInformation(ProjectExplorer::Kit *kit, const QString &key) QString DeployMcuProcessStep::findKitInformation(ProjectExplorer::Kit *kit, const QString &key)
{ {
// This is (kind of) stolen from mcukitmanager.cpp. Might make sense to unify.
using namespace CMakeProjectManager; using namespace CMakeProjectManager;
const auto config = CMakeConfigurationKitAspect::configuration(kit).toList(); const auto config = CMakeConfigurationKitAspect::configuration(kit).toList();
const auto keyName = key.toUtf8(); const auto keyName = key.toUtf8();
@@ -130,57 +122,50 @@ QString DeployMcuProcessStep::findKitInformation(ProjectExplorer::Kit *kit, cons
MCUBuildStepFactory::MCUBuildStepFactory() MCUBuildStepFactory::MCUBuildStepFactory()
: BuildStepFactory() : BuildStepFactory()
{ {
setDisplayName(Tr::tr("Qt4MCU Deploy Step")); setDisplayName(QmlProjectManager::Tr::tr("Qt for MCUs Deploy Step"));
registerStep<DeployMcuProcessStep>(DeployMcuProcessStep::id); registerStep<DeployMcuProcessStep>(DeployMcuProcessStep::id);
} }
void MCUBuildStepFactory::attachToTarget(ProjectExplorer::Target *target)
{
if (!target)
return;
ProjectExplorer::DeployConfiguration *deployConfiguration = target->activeDeployConfiguration();
ProjectExplorer::BuildStepList *stepList = deployConfiguration->stepList();
if (stepList->contains(DeployMcuProcessStep::id))
return;
if (!findMostRecentQulKit()) {
DeployMcuProcessStep::showError(Tr::tr("Failed to find valid Qt4MCU kit"));
return;
}
for (BuildStepFactory *factory : BuildStepFactory::allBuildStepFactories()) {
if (factory->stepId() == DeployMcuProcessStep::id) {
ProjectExplorer::BuildStep *deployConfig = factory->create(stepList);
stepList->appendStep(deployConfig);
}
}
}
ProjectExplorer::Kit *MCUBuildStepFactory::findMostRecentQulKit() ProjectExplorer::Kit *MCUBuildStepFactory::findMostRecentQulKit()
{ {
// Stolen from mcukitmanager.cpp
auto kitQulVersion = [](const ProjectExplorer::Kit *kit) -> QVersionNumber {
const char *sdkVersion = McuSupport::Internal::Constants::KIT_MCUTARGET_SDKVERSION_KEY;
return QVersionNumber::fromString(kit->value(sdkVersion).toString());
};
ProjectExplorer::Kit *mcuKit = nullptr; ProjectExplorer::Kit *mcuKit = nullptr;
for (auto availableKit : ProjectExplorer::KitManager::kits()) { for (auto availableKit : ProjectExplorer::KitManager::kits()) {
if (!availableKit) if (!availableKit)
continue; continue;
auto qulVersion = kitQulVersion(availableKit); auto qulVersion = McuKitManager::kitQulVersion(availableKit);
if (qulVersion.isNull()) if (qulVersion.isNull())
continue; continue;
if (!mcuKit) if (!mcuKit)
mcuKit = availableKit; mcuKit = availableKit;
if (qulVersion > kitQulVersion(mcuKit)) if (qulVersion > McuKitManager::kitQulVersion(mcuKit))
mcuKit = availableKit; mcuKit = availableKit;
} }
return mcuKit; return mcuKit;
} }
} // namespace QmlProjectManager void MCUBuildStepFactory::updateDeployStep(ProjectExplorer::Target *target, bool enabled)
{
if (!target)
return;
ProjectExplorer::DeployConfiguration *deployConfiguration = target->activeDeployConfiguration();
ProjectExplorer::BuildStepList *stepList = deployConfiguration->stepList();
ProjectExplorer::BuildStep *step = stepList->firstStepWithId(DeployMcuProcessStep::id);
if (!step && enabled) {
if (findMostRecentQulKit()) {
stepList->appendStep(DeployMcuProcessStep::id);
} else {
DeployMcuProcessStep::showError(
QmlProjectManager::Tr::tr("Failed to find valid Qt for MCUs kit"));
}
} else {
if (!step)
return;
step->setEnabled(enabled);
}
}
} // namespace McuSupport::Internal

View File

@@ -11,7 +11,7 @@
#include <QTemporaryDir> #include <QTemporaryDir>
namespace QmlProjectManager { namespace McuSupport::Internal {
class DeployMcuProcessStep : public ProjectExplorer::AbstractProcessStep class DeployMcuProcessStep : public ProjectExplorer::AbstractProcessStep
{ {
@@ -30,8 +30,8 @@ class MCUBuildStepFactory : public ProjectExplorer::BuildStepFactory
{ {
public: public:
MCUBuildStepFactory(); MCUBuildStepFactory();
static void attachToTarget(ProjectExplorer::Target *target);
static ProjectExplorer::Kit *findMostRecentQulKit(); static ProjectExplorer::Kit *findMostRecentQulKit();
static void updateDeployStep(ProjectExplorer::Target *target, bool enabled);
}; };
} // namespace QmlProjectManager } // namespace McuSupport::Internal

View File

@@ -3,6 +3,7 @@
#include "mcusupportplugin.h" #include "mcusupportplugin.h"
#include "mcubuildstep.h"
#include "mcukitinformation.h" #include "mcukitinformation.h"
#include "mcukitmanager.h" #include "mcukitmanager.h"
#include "mcuqmlprojectnode.h" #include "mcuqmlprojectnode.h"
@@ -98,6 +99,7 @@ public:
McuSupportOptions m_options{m_settingsHandler}; McuSupportOptions m_options{m_settingsHandler};
McuSupportOptionsPage optionsPage{m_options, m_settingsHandler}; McuSupportOptionsPage optionsPage{m_options, m_settingsHandler};
McuDependenciesKitAspect environmentPathsKitAspect; McuDependenciesKitAspect environmentPathsKitAspect;
MCUBuildStepFactory mcuBuildStepFactory;
}; // class McuSupportPluginPrivate }; // class McuSupportPluginPrivate
static McuSupportPluginPrivate *dd{nullptr}; static McuSupportPluginPrivate *dd{nullptr};
@@ -219,4 +221,9 @@ void McuSupportPlugin::askUserAboutRemovingUninstalledTargetsKits()
ICore::infoBar()->addInfo(info); ICore::infoBar()->addInfo(info);
} }
void McuSupportPlugin::updateDeployStep(ProjectExplorer::Target *target, bool enabled)
{
MCUBuildStepFactory::updateDeployStep(target, enabled);
}
} // namespace McuSupport::Internal } // namespace McuSupport::Internal

View File

@@ -7,6 +7,8 @@
#include <extensionsystem/iplugin.h> #include <extensionsystem/iplugin.h>
#include <projectexplorer/target.h>
namespace McuSupport::Internal { namespace McuSupport::Internal {
void printMessage(const QString &message, bool important); void printMessage(const QString &message, bool important);
@@ -25,6 +27,8 @@ public:
void askUserAboutMcuSupportKitsSetup(); void askUserAboutMcuSupportKitsSetup();
static void askUserAboutMcuSupportKitsUpgrade(const SettingsHandler::Ptr &settingsHandler); static void askUserAboutMcuSupportKitsUpgrade(const SettingsHandler::Ptr &settingsHandler);
static void askUserAboutRemovingUninstalledTargetsKits(); static void askUserAboutRemovingUninstalledTargetsKits();
Q_INVOKABLE static void updateDeployStep(ProjectExplorer::Target *target, bool enabled);
}; };
} // McuSupport::Internal } // McuSupport::Internal

View File

@@ -1,7 +1,7 @@
add_qtc_plugin(QmlProjectManager add_qtc_plugin(QmlProjectManager
CONDITION TARGET Qt5::QuickWidgets CONDITION TARGET Qt5::QuickWidgets
PLUGIN_CLASS QmlProjectPlugin PLUGIN_CLASS QmlProjectPlugin
DEPENDS QmlJS Qt5::QuickWidgets Utils McuSupport CMakeProjectManager DEPENDS QmlJS Qt5::QuickWidgets Utils
PLUGIN_DEPENDS Core ProjectExplorer QtSupport QmlDesignerBase PLUGIN_DEPENDS Core ProjectExplorer QtSupport QmlDesignerBase
SOURCES SOURCES
qmlprojectgen/qmlprojectgenerator.cpp qmlprojectgen/qmlprojectgenerator.h qmlprojectgen/qmlprojectgenerator.cpp qmlprojectgen/qmlprojectgenerator.h
@@ -21,7 +21,6 @@ add_qtc_plugin(QmlProjectManager
qmlprojectplugin.cpp qmlprojectplugin.h qmlprojectplugin.cpp qmlprojectplugin.h
qmlprojectrunconfiguration.cpp qmlprojectrunconfiguration.h qmlprojectrunconfiguration.cpp qmlprojectrunconfiguration.h
buildsystem/qmlbuildsystem.cpp buildsystem/qmlbuildsystem.h buildsystem/qmlbuildsystem.cpp buildsystem/qmlbuildsystem.h
mcubuildstep.cpp mcubuildstep.h
"${PROJECT_SOURCE_DIR}/src/share/3rdparty/studiofonts/studiofonts.qrc" "${PROJECT_SOURCE_DIR}/src/share/3rdparty/studiofonts/studiofonts.qrc"
) )

View File

@@ -3,7 +3,6 @@
#include "qmlbuildsystem.h" #include "qmlbuildsystem.h"
#include "qmlprojectconstants.h" #include "qmlprojectconstants.h"
#include "mcubuildstep.h"
#include <QtCore5Compat/qtextcodec.h> #include <QtCore5Compat/qtextcodec.h>
#include <qmljs/qmljsmodelmanagerinterface.h> #include <qmljs/qmljsmodelmanagerinterface.h>
@@ -18,6 +17,10 @@
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h> #include <coreplugin/messagemanager.h>
#include <extensionsystem/iplugin.h>
#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
#include <projectexplorer/deploymentdata.h> #include <projectexplorer/deploymentdata.h>
#include <projectexplorer/devicesupport/idevice.h> #include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/kitinformation.h> #include <projectexplorer/kitinformation.h>
@@ -41,6 +44,31 @@ namespace {
Q_LOGGING_CATEGORY(infoLogger, "QmlProjectManager.QmlBuildSystem", QtInfoMsg) Q_LOGGING_CATEGORY(infoLogger, "QmlProjectManager.QmlBuildSystem", QtInfoMsg)
} }
ExtensionSystem::IPlugin *findMcuSupportPlugin()
{
const ExtensionSystem::PluginSpec *pluginSpec = Utils::findOrDefault(
ExtensionSystem::PluginManager::plugins(),
Utils::equal(&ExtensionSystem::PluginSpec::name, QString("McuSupport")));
if (pluginSpec)
return pluginSpec->plugin();
return nullptr;
}
void updateMcuBuildStep(Target *target, bool mcuEnabled)
{
if (auto plugin = findMcuSupportPlugin()) {
QMetaObject::invokeMethod(
plugin,
"updateDeployStep",
Qt::DirectConnection,
Q_ARG(ProjectExplorer::Target*, target),
Q_ARG(bool, mcuEnabled));
} else if (mcuEnabled) {
qWarning() << "Failed to find McuSupport plugin but qtForMCUs is enabled in the project";
}
}
QmlBuildSystem::QmlBuildSystem(Target *target) QmlBuildSystem::QmlBuildSystem(Target *target)
: BuildSystem(target) : BuildSystem(target)
{ {
@@ -52,11 +80,11 @@ QmlBuildSystem::QmlBuildSystem(Target *target)
connect(target->project(), &Project::activeTargetChanged, [this](Target *target) { connect(target->project(), &Project::activeTargetChanged, [this](Target *target) {
refresh(RefreshOptions::NoFileRefresh); refresh(RefreshOptions::NoFileRefresh);
if (qtForMCUs()) updateMcuBuildStep(target, qtForMCUs());
MCUBuildStepFactory::attachToTarget(target);
}); });
connect(target->project(), &Project::projectFileIsDirty, [this]() { connect(target->project(), &Project::projectFileIsDirty, [this]() {
refresh(RefreshOptions::Project); refresh(RefreshOptions::Project);
updateMcuBuildStep(project()->activeTarget(), qtForMCUs());
}); });
// FIXME: Check. Probably bogus after the BuildSystem move. // FIXME: Check. Probably bogus after the BuildSystem move.

View File

@@ -1,7 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd. // Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "mcubuildstep.h"
#include "qdslandingpage.h" #include "qdslandingpage.h"
#include "qmlprojectplugin.h" #include "qmlprojectplugin.h"
#include "qmlproject.h" #include "qmlproject.h"
@@ -94,7 +93,6 @@ public:
QPointer<QMessageBox> lastMessageBox; QPointer<QMessageBox> lastMessageBox;
QdsLandingPage *landingPage = nullptr; QdsLandingPage *landingPage = nullptr;
QdsLandingPageWidget *landingPageWidget = nullptr; QdsLandingPageWidget *landingPageWidget = nullptr;
MCUBuildStepFactory mcuBuildStepFactory;
}; };
QmlProjectPlugin::~QmlProjectPlugin() QmlProjectPlugin::~QmlProjectPlugin()