forked from qt-creator/qt-creator
Add MCU build step to the QmlBuildSystem
If a qml project is marked as qtForMCU the buildstep will run the qmlprojectexporter on the currently active qmlproject when pressing the "Run" button. The output messages of the tool will then show up in the "Compile Output" panel. The build step itself can be seen when switching to "Projects" mode under "Deployment". Change-Id: I5ac31d5655e3b4b6137aaf541839776f144a09c4 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io> Reviewed-by: Burak Hancerli <burak.hancerli@qt.io>
This commit is contained in:
committed by
Thomas Hartmann
parent
43bf597611
commit
3387c68ff2
@@ -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
|
DEPENDS QmlJS Qt5::QuickWidgets Utils McuSupport CMakeProjectManager
|
||||||
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,6 +21,7 @@ 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"
|
||||||
)
|
)
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#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>
|
||||||
@@ -49,7 +50,11 @@ QmlBuildSystem::QmlBuildSystem(Target *target)
|
|||||||
updateDeploymentData();
|
updateDeploymentData();
|
||||||
registerMenuButtons();
|
registerMenuButtons();
|
||||||
|
|
||||||
connect(target->project(), &Project::activeTargetChanged, [this]() { refresh(RefreshOptions::NoFileRefresh); });
|
connect(target->project(), &Project::activeTargetChanged, [this](Target *target) {
|
||||||
|
refresh(RefreshOptions::NoFileRefresh);
|
||||||
|
if (qtForMCUs())
|
||||||
|
MCUBuildStepFactory::attachToTarget(target);
|
||||||
|
});
|
||||||
connect(target->project(), &Project::projectFileIsDirty, [this]() {
|
connect(target->project(), &Project::projectFileIsDirty, [this]() {
|
||||||
refresh(RefreshOptions::Project);
|
refresh(RefreshOptions::Project);
|
||||||
});
|
});
|
||||||
|
197
src/plugins/qmlprojectmanager/mcubuildstep.cpp
Normal file
197
src/plugins/qmlprojectmanager/mcubuildstep.cpp
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#include "mcubuildstep.h"
|
||||||
|
|
||||||
|
#include "projectexplorer/buildstep.h"
|
||||||
|
#include "projectexplorer/buildsystem.h"
|
||||||
|
#include "projectexplorer/buildsteplist.h"
|
||||||
|
#include "projectexplorer/deployconfiguration.h"
|
||||||
|
#include "projectexplorer/kit.h"
|
||||||
|
#include "projectexplorer/target.h"
|
||||||
|
#include "projectexplorer/kitmanager.h"
|
||||||
|
|
||||||
|
#include <coreplugin/messagebox.h>
|
||||||
|
#include <cmakeprojectmanager/cmakekitinformation.h>
|
||||||
|
|
||||||
|
#include "qtsupport/qtsupportconstants.h"
|
||||||
|
#include "mcusupport/mcusupportconstants.h"
|
||||||
|
#include "mcusupport/mculegacyconstants.h"
|
||||||
|
|
||||||
|
#include "utils/aspects.h"
|
||||||
|
#include "utils/filepath.h"
|
||||||
|
|
||||||
|
#include <QVersionNumber>
|
||||||
|
|
||||||
|
namespace QmlProjectManager {
|
||||||
|
|
||||||
|
const Utils::Id DeployMcuProcessStep::id = "QmlProject.Mcu.DeployStep";
|
||||||
|
const QString DeployMcuProcessStep::processCommandKey = "QmlProject.Mcu.ProcessStep.Command";
|
||||||
|
const QString DeployMcuProcessStep::processArgumentsKey = "QmlProject.Mcu.ProcessStep.Arguments";
|
||||||
|
const QString DeployMcuProcessStep::processWorkingDirectoryKey = "QmlProject.Mcu.ProcessStep.BuildDirectory";
|
||||||
|
|
||||||
|
void DeployMcuProcessStep::showError(const QString& text) {
|
||||||
|
Core::AsynchronousMessageBox::critical(tr("Qt4MCU Deploy Step"), text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 (not buildSystem()) {
|
||||||
|
showError(QObject::tr("Failed to find valid build system"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not m_tmpDir.isValid()) {
|
||||||
|
showError(QObject::tr("Failed to create valid build directory"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto fixPath = [](const QString& path) -> QString {
|
||||||
|
return "\"" + QDir::toNativeSeparators(path) + "\"";
|
||||||
|
};
|
||||||
|
|
||||||
|
ProjectExplorer::Kit* kit = MCUBuildStepFactory::findMostRecentQulKit();
|
||||||
|
if (not kit)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString root = findKitInformation(kit, McuSupport::Internal::Legacy::Constants::QUL_CMAKE_VAR);
|
||||||
|
|
||||||
|
auto* cmd = addAspect<Utils::StringAspect>();
|
||||||
|
cmd->setSettingsKey(processCommandKey);
|
||||||
|
cmd->setDisplayStyle(Utils::StringAspect::PathChooserDisplay);
|
||||||
|
cmd->setExpectedKind(Utils::PathChooser::Command);
|
||||||
|
cmd->setLabelText(tr("Command:"));
|
||||||
|
cmd->setValue(QDir::toNativeSeparators(root + "/bin/qmlprojectexporter"));
|
||||||
|
|
||||||
|
const char* importPathConstant = QtSupport::Constants::KIT_QML_IMPORT_PATH;
|
||||||
|
QString projectDir = buildSystem()->projectDirectory().toString();
|
||||||
|
QString qulIncludeDir = kit->value(importPathConstant).toString( );
|
||||||
|
QStringList includeDirs {
|
||||||
|
fixPath(qulIncludeDir),
|
||||||
|
fixPath(qulIncludeDir + "/Timeline"),
|
||||||
|
fixPath(projectDir + "/imports")
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* toolChainConstant = McuSupport::Internal::Constants::KIT_MCUTARGET_TOOLCHAIN_KEY;
|
||||||
|
QStringList arguments = {
|
||||||
|
fixPath(buildSystem()->projectFilePath().toString()),
|
||||||
|
"--platform", findKitInformation(kit, "QUL_PLATFORM"),
|
||||||
|
"--toolchain", kit->value(toolChainConstant).toString( ),
|
||||||
|
"--include-dirs", includeDirs.join(","),
|
||||||
|
};
|
||||||
|
|
||||||
|
auto* args = addAspect<Utils::StringAspect>();
|
||||||
|
args->setSettingsKey(processArgumentsKey);
|
||||||
|
args->setDisplayStyle(Utils::StringAspect::LineEditDisplay);
|
||||||
|
args->setLabelText(tr("Arguments:"));
|
||||||
|
args->setValue(arguments.join(" "));
|
||||||
|
|
||||||
|
auto* outDir = addAspect<Utils::StringAspect>();
|
||||||
|
outDir->setSettingsKey(processWorkingDirectoryKey);
|
||||||
|
outDir->setDisplayStyle(Utils::StringAspect::PathChooserDisplay);
|
||||||
|
outDir->setExpectedKind(Utils::PathChooser::Directory);
|
||||||
|
outDir->setLabelText(tr("Build directory:"));
|
||||||
|
outDir->setPlaceHolderText(fixPath(m_tmpDir.path()));
|
||||||
|
|
||||||
|
setCommandLineProvider([this, cmd, args, outDir, fixPath]() -> Utils::CommandLine {
|
||||||
|
auto directory = outDir->value();
|
||||||
|
if (directory.isEmpty())
|
||||||
|
directory = fixPath(m_tmpDir.path());
|
||||||
|
|
||||||
|
QString outArg = " --outdir " + directory;
|
||||||
|
return {cmd->filePath(), args->value() + outArg, Utils::CommandLine::Raw};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DeployMcuProcessStep::init()
|
||||||
|
{
|
||||||
|
if (!AbstractProcessStep::init())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeployMcuProcessStep::doRun()
|
||||||
|
{
|
||||||
|
AbstractProcessStep::doRun();
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
for (const CMakeProjectManager::CMakeConfigItem &configItem : config) {
|
||||||
|
if (configItem.key == keyName)
|
||||||
|
return QString::fromUtf8(configItem.value);
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MCUBuildStepFactory::MCUBuildStepFactory()
|
||||||
|
: BuildStepFactory()
|
||||||
|
{
|
||||||
|
setDisplayName("Qt4MCU Deploy Step");
|
||||||
|
registerStep< DeployMcuProcessStep >(DeployMcuProcessStep::id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MCUBuildStepFactory::attachToTarget(ProjectExplorer::Target *target)
|
||||||
|
{
|
||||||
|
if (not target)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ProjectExplorer::DeployConfiguration* deployConfiguration = target->activeDeployConfiguration();
|
||||||
|
ProjectExplorer::BuildStepList* stepList = deployConfiguration->stepList();
|
||||||
|
if (stepList->contains(DeployMcuProcessStep::id))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (not findMostRecentQulKit()) {
|
||||||
|
DeployMcuProcessStep::showError(QObject::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* kit = nullptr;
|
||||||
|
for (auto k : ProjectExplorer::KitManager::kits())
|
||||||
|
{
|
||||||
|
auto qulVersion = kitQulVersion(k);
|
||||||
|
if (qulVersion.isNull( ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (not kit)
|
||||||
|
kit = k;
|
||||||
|
|
||||||
|
if (qulVersion > kitQulVersion(kit))
|
||||||
|
kit = k;
|
||||||
|
}
|
||||||
|
return kit;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlProjectManager
|
42
src/plugins/qmlprojectmanager/mcubuildstep.h
Normal file
42
src/plugins/qmlprojectmanager/mcubuildstep.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "projectexplorer/kit.h"
|
||||||
|
#include "projectexplorer/project.h"
|
||||||
|
#include <projectexplorer/abstractprocessstep.h>
|
||||||
|
#include <projectexplorer/buildstep.h>
|
||||||
|
#include <utils/id.h>
|
||||||
|
|
||||||
|
#include <QTemporaryDir>
|
||||||
|
|
||||||
|
namespace QmlProjectManager {
|
||||||
|
|
||||||
|
class DeployMcuProcessStep : public ProjectExplorer::AbstractProcessStep
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const Utils::Id id;
|
||||||
|
static void showError(const QString& text);
|
||||||
|
|
||||||
|
DeployMcuProcessStep(ProjectExplorer::BuildStepList *bc, Utils::Id id);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool init() override;
|
||||||
|
void doRun() override;
|
||||||
|
QString findKitInformation(ProjectExplorer::Kit* kit, const QString& key);
|
||||||
|
|
||||||
|
static const QString processCommandKey;
|
||||||
|
static const QString processArgumentsKey;
|
||||||
|
static const QString processWorkingDirectoryKey;
|
||||||
|
QTemporaryDir m_tmpDir;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MCUBuildStepFactory : public ProjectExplorer::BuildStepFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MCUBuildStepFactory();
|
||||||
|
static void attachToTarget(ProjectExplorer::Target *target);
|
||||||
|
static ProjectExplorer::Kit* findMostRecentQulKit( );
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlProjectManager
|
@@ -1,6 +1,7 @@
|
|||||||
// 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"
|
||||||
@@ -93,6 +94,7 @@ 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()
|
||||||
|
Reference in New Issue
Block a user