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
settingshandler.cpp settingshandler.h
mcuqmlprojectnode.cpp mcuqmlprojectnode.h
mcubuildstep.cpp mcubuildstep.h
)
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
#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/buildsteplist.h>
@@ -14,10 +18,8 @@
#include <projectexplorer/task.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 <utils/aspects.h>
@@ -25,7 +27,7 @@
#include <QVersionNumber>
namespace QmlProjectManager {
namespace McuSupport::Internal {
const Utils::Id DeployMcuProcessStep::id = "QmlProject.Mcu.DeployStep";
@@ -35,26 +37,17 @@ void DeployMcuProcessStep::showError(const QString &text)
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)
: AbstractProcessStep(bc, id)
, m_tmpDir()
{
if (!buildSystem()) {
showError(Tr::tr("Failed to find valid build system"));
showError(QmlProjectManager::Tr::tr("Failed to find valid build system"));
return;
}
if (!m_tmpDir.isValid()) {
showError(Tr::tr("Failed to create valid build directory"));
showError(QmlProjectManager::Tr::tr("Failed to create valid build directory"));
return;
}
@@ -62,14 +55,14 @@ DeployMcuProcessStep::DeployMcuProcessStep(ProjectExplorer::BuildStepList *bc, U
if (!kit)
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 cmd = addAspect<Utils::StringAspect>();
cmd->setSettingsKey("QmlProject.Mcu.ProcessStep.Command");
cmd->setDisplayStyle(Utils::StringAspect::PathChooserDisplay);
cmd->setExpectedKind(Utils::PathChooser::Command);
cmd->setLabelText(Tr::tr("Command:"));
cmd->setLabelText(QmlProjectManager::Tr::tr("Command:"));
cmd->setFilePath(rootPath.pathAppended("/bin/qmlprojectexporter"));
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())
};
const char *toolChainConstant = McuSupport::Internal::Constants::KIT_MCUTARGET_TOOLCHAIN_KEY;
const char *toolChainConstant = Internal::Constants::KIT_MCUTARGET_TOOLCHAIN_KEY;
QStringList arguments = {
Utils::ProcessArgs::quoteArg(buildSystem()->projectFilePath().toString()),
"--platform", findKitInformation(kit, "QUL_PLATFORM"),
@@ -91,14 +84,14 @@ DeployMcuProcessStep::DeployMcuProcessStep(ProjectExplorer::BuildStepList *bc, U
auto args = addAspect<Utils::StringAspect>();
args->setSettingsKey("QmlProject.Mcu.ProcessStep.Arguments");
args->setDisplayStyle(Utils::StringAspect::LineEditDisplay);
args->setLabelText(Tr::tr("Arguments:"));
args->setLabelText(QmlProjectManager::Tr::tr("Arguments:"));
args->setValue(Utils::ProcessArgs::joinArgs(arguments));
auto outDir = addAspect<Utils::StringAspect>();
outDir->setSettingsKey("QmlProject.Mcu.ProcessStep.BuildDirectory");
outDir->setDisplayStyle(Utils::StringAspect::PathChooserDisplay);
outDir->setExpectedKind(Utils::PathChooser::Directory);
outDir->setLabelText(Tr::tr("Build directory:"));
outDir->setLabelText(QmlProjectManager::Tr::tr("Build directory:"));
outDir->setPlaceHolderText(m_tmpDir.path());
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)
{
// This is (kind of) stolen from mcukitmanager.cpp. Might make sense to unify.
using namespace CMakeProjectManager;
const auto config = CMakeConfigurationKitAspect::configuration(kit).toList();
const auto keyName = key.toUtf8();
@@ -130,57 +122,50 @@ QString DeployMcuProcessStep::findKitInformation(ProjectExplorer::Kit *kit, cons
MCUBuildStepFactory::MCUBuildStepFactory()
: BuildStepFactory()
{
setDisplayName(Tr::tr("Qt4MCU Deploy Step"));
setDisplayName(QmlProjectManager::Tr::tr("Qt for MCUs Deploy Step"));
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()
{
// 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;
for (auto availableKit : ProjectExplorer::KitManager::kits()) {
if (!availableKit)
continue;
auto qulVersion = kitQulVersion(availableKit);
auto qulVersion = McuKitManager::kitQulVersion(availableKit);
if (qulVersion.isNull())
continue;
if (!mcuKit)
mcuKit = availableKit;
if (qulVersion > kitQulVersion(mcuKit))
if (qulVersion > McuKitManager::kitQulVersion(mcuKit))
mcuKit = availableKit;
}
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>
namespace QmlProjectManager {
namespace McuSupport::Internal {
class DeployMcuProcessStep : public ProjectExplorer::AbstractProcessStep
{
@@ -30,8 +30,8 @@ class MCUBuildStepFactory : public ProjectExplorer::BuildStepFactory
{
public:
MCUBuildStepFactory();
static void attachToTarget(ProjectExplorer::Target *target);
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 "mcubuildstep.h"
#include "mcukitinformation.h"
#include "mcukitmanager.h"
#include "mcuqmlprojectnode.h"
@@ -98,6 +99,7 @@ public:
McuSupportOptions m_options{m_settingsHandler};
McuSupportOptionsPage optionsPage{m_options, m_settingsHandler};
McuDependenciesKitAspect environmentPathsKitAspect;
MCUBuildStepFactory mcuBuildStepFactory;
}; // class McuSupportPluginPrivate
static McuSupportPluginPrivate *dd{nullptr};
@@ -219,4 +221,9 @@ void McuSupportPlugin::askUserAboutRemovingUninstalledTargetsKits()
ICore::infoBar()->addInfo(info);
}
void McuSupportPlugin::updateDeployStep(ProjectExplorer::Target *target, bool enabled)
{
MCUBuildStepFactory::updateDeployStep(target, enabled);
}
} // namespace McuSupport::Internal

View File

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

View File

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

View File

@@ -3,7 +3,6 @@
#include "qmlbuildsystem.h"
#include "qmlprojectconstants.h"
#include "mcubuildstep.h"
#include <QtCore5Compat/qtextcodec.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
@@ -18,6 +17,10 @@
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
#include <extensionsystem/iplugin.h>
#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
#include <projectexplorer/deploymentdata.h>
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/kitinformation.h>
@@ -41,6 +44,31 @@ namespace {
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)
: BuildSystem(target)
{
@@ -52,11 +80,11 @@ QmlBuildSystem::QmlBuildSystem(Target *target)
connect(target->project(), &Project::activeTargetChanged, [this](Target *target) {
refresh(RefreshOptions::NoFileRefresh);
if (qtForMCUs())
MCUBuildStepFactory::attachToTarget(target);
updateMcuBuildStep(target, qtForMCUs());
});
connect(target->project(), &Project::projectFileIsDirty, [this]() {
refresh(RefreshOptions::Project);
updateMcuBuildStep(project()->activeTarget(), qtForMCUs());
});
// FIXME: Check. Probably bogus after the BuildSystem move.

View File

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