aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/nim
diff options
context:
space:
mode:
authorChristian Kandeler <[email protected]>2025-01-24 14:48:59 +0100
committerChristian Kandeler <[email protected]>2025-01-24 16:07:48 +0000
commit6c56d0deb92225636fa4a34352bf771577dfc536 (patch)
tree229cf56ac410402d6279fff5c0afed08a193320e /src/plugins/nim
parent72acdb5a98a8f04d032e128955702a7663b4fa50 (diff)
Nim: Merge Project/BuildSystem/BuildConfiguration classes into one TU
Diffstat (limited to 'src/plugins/nim')
-rw-r--r--src/plugins/nim/CMakeLists.txt4
-rw-r--r--src/plugins/nim/nim.qbs4
-rw-r--r--src/plugins/nim/nimplugin.cpp4
-rw-r--r--src/plugins/nim/project/nimblebuildconfiguration.cpp84
-rw-r--r--src/plugins/nim/project/nimblebuildconfiguration.h36
-rw-r--r--src/plugins/nim/project/nimblebuildstep.cpp3
-rw-r--r--src/plugins/nim/project/nimblebuildsystem.cpp250
-rw-r--r--src/plugins/nim/project/nimblebuildsystem.h74
-rw-r--r--src/plugins/nim/project/nimbleproject.cpp329
-rw-r--r--src/plugins/nim/project/nimbleproject.h53
-rw-r--r--src/plugins/nim/project/nimblerunconfiguration.cpp3
-rw-r--r--src/plugins/nim/project/nimbletaskstep.cpp2
-rw-r--r--src/plugins/nim/project/nimbuildconfiguration.cpp101
-rw-r--r--src/plugins/nim/project/nimbuildconfiguration.h30
-rw-r--r--src/plugins/nim/project/nimbuildsystem.cpp261
-rw-r--r--src/plugins/nim/project/nimbuildsystem.h52
-rw-r--r--src/plugins/nim/project/nimcompilerbuildstep.cpp2
-rw-r--r--src/plugins/nim/project/nimcompilercleanstep.cpp2
-rw-r--r--src/plugins/nim/project/nimproject.cpp319
-rw-r--r--src/plugins/nim/project/nimproject.h53
-rw-r--r--src/plugins/nim/project/nimrunconfiguration.cpp3
21 files changed, 760 insertions, 909 deletions
diff --git a/src/plugins/nim/CMakeLists.txt b/src/plugins/nim/CMakeLists.txt
index 4bb9fa28bb2..d1a4cff1591 100644
--- a/src/plugins/nim/CMakeLists.txt
+++ b/src/plugins/nim/CMakeLists.txt
@@ -14,10 +14,6 @@ add_qtc_plugin(Nim
project/nimbleproject.h project/nimbleproject.cpp
project/nimblerunconfiguration.h project/nimblerunconfiguration.cpp
project/nimbletaskstep.h project/nimbletaskstep.cpp
- project/nimblebuildsystem.h project/nimblebuildsystem.cpp
- project/nimblebuildconfiguration.h project/nimblebuildconfiguration.cpp
- project/nimbuildsystem.cpp project/nimbuildsystem.h
- project/nimbuildconfiguration.cpp project/nimbuildconfiguration.h
project/nimcompilerbuildstep.cpp project/nimcompilerbuildstep.h
project/nimcompilercleanstep.cpp project/nimcompilercleanstep.h
project/nimoutputtaskparser.cpp project/nimoutputtaskparser.h
diff --git a/src/plugins/nim/nim.qbs b/src/plugins/nim/nim.qbs
index 2b8fbcecff5..8639b3be725 100644
--- a/src/plugins/nim/nim.qbs
+++ b/src/plugins/nim/nim.qbs
@@ -38,8 +38,6 @@ QtcPlugin {
name: "Project"
prefix: "project/"
files: [
- "nimbuildsystem.cpp", "nimbuildsystem.h",
- "nimbuildconfiguration.h", "nimbuildconfiguration.cpp",
"nimcompilerbuildstep.h", "nimcompilerbuildstep.cpp",
"nimcompilercleanstep.h", "nimcompilercleanstep.cpp",
"nimoutputtaskparser.h", "nimoutputtaskparser.cpp",
@@ -50,8 +48,6 @@ QtcPlugin {
"nimbleproject.h", "nimbleproject.cpp",
"nimblerunconfiguration.h", "nimblerunconfiguration.cpp",
"nimbletaskstep.h", "nimbletaskstep.cpp",
- "nimblebuildsystem.h", "nimblebuildsystem.cpp",
- "nimblebuildconfiguration.h", "nimblebuildconfiguration.cpp",
]
}
diff --git a/src/plugins/nim/nimplugin.cpp b/src/plugins/nim/nimplugin.cpp
index 6315b5e92cc..ccf78860bf3 100644
--- a/src/plugins/nim/nimplugin.cpp
+++ b/src/plugins/nim/nimplugin.cpp
@@ -4,12 +4,10 @@
#include "nimconstants.h"
#include "nimtr.h"
#include "editor/nimeditorfactory.h"
-#include "project/nimblebuildconfiguration.h"
#include "project/nimblebuildstep.h"
#include "project/nimbleproject.h"
#include "project/nimblerunconfiguration.h"
#include "project/nimbletaskstep.h"
-#include "project/nimbuildconfiguration.h"
#include "project/nimcompilerbuildstep.h"
#include "project/nimcompilercleanstep.h"
#include "project/nimoutputtaskparser.h"
@@ -44,8 +42,6 @@ class NimPluginPrivate
{
public:
NimEditorFactory editorFactory;
- NimBuildConfigurationFactory buildConfigFactory;
- NimbleBuildConfigurationFactory nimbleBuildConfigFactory;
NimRunConfigurationFactory nimRunConfigFactory;
NimbleRunConfigurationFactory nimbleRunConfigFactory;
NimbleTestConfigurationFactory nimbleTestConfigFactory;
diff --git a/src/plugins/nim/project/nimblebuildconfiguration.cpp b/src/plugins/nim/project/nimblebuildconfiguration.cpp
deleted file mode 100644
index a0efe78fa7b..00000000000
--- a/src/plugins/nim/project/nimblebuildconfiguration.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (C) Filippo Cucchetto <[email protected]>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "nimblebuildconfiguration.h"
-
-#include "nimconstants.h"
-#include "nimtr.h"
-
-#include <projectexplorer/buildinfo.h>
-#include <projectexplorer/buildstep.h>
-#include <projectexplorer/buildsteplist.h>
-#include <projectexplorer/kit.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/projectexplorer.h>
-
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace Nim {
-
-NimbleBuildConfiguration::NimbleBuildConfiguration(Target *target, Id id)
- : BuildConfiguration(target, id)
-{
- setConfigWidgetDisplayName(Tr::tr("General"));
- setConfigWidgetHasFrame(true);
- setBuildDirectorySettingsKey("Nim.NimbleBuildConfiguration.BuildDirectory");
- appendInitialBuildStep(Constants::C_NIMBLEBUILDSTEP_ID);
-
- setInitializer([this](const BuildInfo &info) {
- setBuildType(info.buildType);
- setBuildDirectory(project()->projectDirectory());
- });
-}
-
-BuildConfiguration::BuildType NimbleBuildConfiguration::buildType() const
-{
- return m_buildType;
-}
-
-void NimbleBuildConfiguration::fromMap(const Store &map)
-{
- m_buildType = static_cast<BuildType>(map[Constants::C_NIMBLEBUILDCONFIGURATION_BUILDTYPE].toInt());
- BuildConfiguration::fromMap(map);
-}
-
-void NimbleBuildConfiguration::toMap(Store &map) const
-{
- BuildConfiguration::toMap(map);
- map[Constants::C_NIMBLEBUILDCONFIGURATION_BUILDTYPE] = buildType();
-}
-
-void NimbleBuildConfiguration::setBuildType(BuildConfiguration::BuildType buildType)
-{
- if (buildType == m_buildType)
- return;
- m_buildType = buildType;
- emit buildTypeChanged();
-}
-
-NimbleBuildConfigurationFactory::NimbleBuildConfigurationFactory()
-{
- registerBuildConfiguration<NimbleBuildConfiguration>(Constants::C_NIMBLEBUILDCONFIGURATION_ID);
- setSupportedProjectType(Constants::C_NIMBLEPROJECT_ID);
- setSupportedProjectMimeTypeName(Constants::C_NIMBLE_MIMETYPE);
-
- setBuildGenerator([](const Kit *, const FilePath &projectPath, bool forSetup) {
- const auto oneBuild = [&](BuildConfiguration::BuildType buildType, const QString &typeName) {
- BuildInfo info;
- info.buildType = buildType;
- info.typeName = typeName;
- if (forSetup) {
- info.displayName = info.typeName;
- info.buildDirectory = projectPath.parentDir();
- }
- return info;
- };
- return QList<BuildInfo>{
- oneBuild(BuildConfiguration::Debug, Tr::tr("Debug")),
- oneBuild(BuildConfiguration::Release, Tr::tr("Release"))
- };
- });
-}
-
-} // Nim
diff --git a/src/plugins/nim/project/nimblebuildconfiguration.h b/src/plugins/nim/project/nimblebuildconfiguration.h
deleted file mode 100644
index 4b1e9593097..00000000000
--- a/src/plugins/nim/project/nimblebuildconfiguration.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) Filippo Cucchetto <[email protected]>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/target.h>
-
-namespace Nim {
-
-class NimbleBuildConfiguration : public ProjectExplorer::BuildConfiguration
-{
- Q_OBJECT
-
- friend class ProjectExplorer::BuildConfigurationFactory;
-
- NimbleBuildConfiguration(ProjectExplorer::Target *target, Utils::Id id);
-
- BuildType buildType() const override;
-
- void fromMap(const Utils::Store &map) override;
- void toMap(Utils::Store &map) const override;
-
-private:
- void setBuildType(BuildType buildType);
-
- BuildType m_buildType = ProjectExplorer::BuildConfiguration::Unknown;
-};
-
-class NimbleBuildConfigurationFactory final : public ProjectExplorer::BuildConfigurationFactory
-{
-public:
- NimbleBuildConfigurationFactory();
-};
-
-} // Nim
diff --git a/src/plugins/nim/project/nimblebuildstep.cpp b/src/plugins/nim/project/nimblebuildstep.cpp
index efda9aa5baf..f867a337985 100644
--- a/src/plugins/nim/project/nimblebuildstep.cpp
+++ b/src/plugins/nim/project/nimblebuildstep.cpp
@@ -4,12 +4,13 @@
#include "nimblebuildstep.h"
#include "nimconstants.h"
-#include "nimbuildsystem.h"
#include "nimoutputtaskparser.h"
+#include "nimproject.h"
#include "nimtr.h"
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/processparameters.h>
+#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runconfigurationaspects.h>
diff --git a/src/plugins/nim/project/nimblebuildsystem.cpp b/src/plugins/nim/project/nimblebuildsystem.cpp
deleted file mode 100644
index f7b6fb4a7d0..00000000000
--- a/src/plugins/nim/project/nimblebuildsystem.cpp
+++ /dev/null
@@ -1,250 +0,0 @@
-// Copyright (C) Filippo Cucchetto <[email protected]>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "nimblebuildsystem.h"
-
-#include "nimbuildsystem.h"
-#include "../nimconstants.h"
-
-#include <projectexplorer/target.h>
-#include <projectexplorer/taskhub.h>
-
-#include <utils/algorithm.h>
-#include <utils/qtcprocess.h>
-#include <utils/qtcassert.h>
-
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace Nim {
-
-const char C_NIMBLEPROJECT_TASKS[] = "Nim.NimbleProject.Tasks";
-
-static QList<QByteArray> linesFromProcessOutput(Process *process)
-{
- QList<QByteArray> lines = process->readAllRawStandardOutput().split('\n');
- lines = Utils::transform(lines, [](const QByteArray &line){ return line.trimmed(); });
- Utils::erase(lines, [](const QByteArray &line) { return line.isEmpty(); });
- return lines;
-}
-
-static std::vector<NimbleTask> parseTasks(const FilePath &nimblePath, const FilePath &workingDirectory)
-{
- Process process;
- process.setCommand({nimblePath, {"tasks"}});
- process.setWorkingDirectory(workingDirectory);
- process.start();
- process.waitForFinished();
-
- std::vector<NimbleTask> result;
-
- if (process.exitCode() != 0) {
- TaskHub::addTask(ProjectExplorer::BuildSystemTask(Task::Error, process.cleanedStdOut()));
- return result;
- }
-
- const QList<QByteArray> &lines = linesFromProcessOutput(&process);
-
- for (const QByteArray &line : lines) {
- QList<QByteArray> tokens = line.trimmed().split(' ');
- QTC_ASSERT(!tokens.empty(), continue);
- QString taskName = QString::fromUtf8(tokens.takeFirst());
- QString taskDesc = QString::fromUtf8(tokens.join(' '));
- result.push_back({std::move(taskName), std::move(taskDesc)});
- }
-
- return result;
-}
-
-static NimbleMetadata parseMetadata(const FilePath &nimblePath, const FilePath &workingDirectory)
-{
- Process process;
- process.setCommand({nimblePath, {"dump"}});
- process.setWorkingDirectory(workingDirectory);
- process.start();
- process.waitForFinished();
-
- NimbleMetadata result = {};
-
- if (process.exitCode() != 0) {
- TaskHub::addTask(ProjectExplorer::BuildSystemTask(Task::Error, process.cleanedStdOut()));
- return result;
- }
- const QList<QByteArray> &lines = linesFromProcessOutput(&process);
-
- for (const QByteArray &line : lines) {
- QList<QByteArray> tokens = line.trimmed().split(':');
- QTC_ASSERT(tokens.size() == 2, continue);
- QString name = QString::fromUtf8(tokens.takeFirst()).trimmed();
- QString value = QString::fromUtf8(tokens.takeFirst()).trimmed();
- QTC_ASSERT(value.size() >= 2, continue);
- QTC_ASSERT(value.front() == QChar('"'), continue);
- QTC_ASSERT(value.back() == QChar('"'), continue);
- value.remove(0, 1);
- value.remove(value.size() - 1, 1);
-
- if (name == "binDir")
- result.binDir = value;
- else if (name == "srcDir")
- result.srcDir = value;
- else if (name == "bin") {
- QStringList bin = value.split(',');
- bin = Utils::transform(bin, [](const QString &x){ return x.trimmed(); });
- Utils::erase(bin, [](const QString &x) { return x.isEmpty(); });
- result.bin = std::move(bin);
- }
- }
-
- return result;
-}
-
-NimbleBuildSystem::NimbleBuildSystem(Target *target)
- : BuildSystem(target), m_projectScanner(target->project())
-{
- m_projectScanner.watchProjectFilePath();
-
- connect(&m_projectScanner, &NimProjectScanner::fileChanged, this, [this](const QString &path) {
- if (path == projectFilePath().toUrlishString())
- requestDelayedParse();
- });
-
- connect(&m_projectScanner, &NimProjectScanner::requestReparse,
- this, &NimbleBuildSystem::requestDelayedParse);
-
- connect(&m_projectScanner, &NimProjectScanner::finished, this, &NimbleBuildSystem::updateProject);
-
- connect(&m_projectScanner, &NimProjectScanner::directoryChanged, this, [this] (const QString &directory){
- // Workaround for nimble creating temporary files in project root directory
- // when querying the list of tasks.
- // See https://github.com/nim-lang/nimble/issues/720
- if (directory != projectDirectory().toUrlishString())
- requestDelayedParse();
- });
-
- connect(target->project(), &ProjectExplorer::Project::settingsLoaded,
- this, &NimbleBuildSystem::loadSettings);
- connect(target->project(), &ProjectExplorer::Project::aboutToSaveSettings,
- this, &NimbleBuildSystem::saveSettings);
- requestDelayedParse();
-}
-
-void NimbleBuildSystem::triggerParsing()
-{
- // Only allow one parsing run at the same time:
- auto guard = guardParsingRun();
- if (!guard.guardsProject())
- return;
- m_guard = std::move(guard);
-
- m_projectScanner.startScan();
-}
-
-void NimbleBuildSystem::updateProject()
-{
- const FilePath projectDir = projectDirectory();
- const FilePath nimble = Nim::nimblePathFromKit(kit());
-
- const NimbleMetadata metadata = parseMetadata(nimble, projectDir);
- const FilePath binDir = projectDir.pathAppended(metadata.binDir);
- const FilePath srcDir = projectDir.pathAppended("src");
-
- QList<BuildTargetInfo> targets = Utils::transform(metadata.bin, [&](const QString &bin){
- BuildTargetInfo info = {};
- info.displayName = bin;
- info.targetFilePath = binDir.pathAppended(bin);
- info.projectFilePath = projectFilePath();
- info.workingDirectory = binDir;
- info.buildKey = bin;
- return info;
- });
-
- setApplicationTargets(std::move(targets));
-
- std::vector<NimbleTask> tasks = parseTasks(nimble, projectDir);
- if (tasks != m_tasks) {
- m_tasks = std::move(tasks);
- emit tasksChanged();
- }
-
- // Complete scan
- m_guard.markAsSuccess();
- m_guard = {};
-
- emitBuildSystemUpdated();
-}
-
-std::vector<NimbleTask> NimbleBuildSystem::tasks() const
-{
- return m_tasks;
-}
-
-void NimbleBuildSystem::saveSettings()
-{
- // only handles nimble specific settings - NimProjectScanner handles general settings
- QStringList result;
- for (const NimbleTask &task : m_tasks) {
- result.push_back(task.name);
- result.push_back(task.description);
- }
-
- project()->setNamedSettings(C_NIMBLEPROJECT_TASKS, result);
-}
-
-void NimbleBuildSystem::loadSettings()
-{
- // only handles nimble specific settings - NimProjectScanner handles general settings
- QStringList list = project()->namedSettings(C_NIMBLEPROJECT_TASKS).toStringList();
-
- m_tasks.clear();
- if (list.size() % 2 != 0)
- return;
-
- for (int i = 0; i < list.size(); i += 2)
- m_tasks.push_back({list[i], list[i + 1]});
-}
-
-bool NimbleBuildSystem::supportsAction(Node *context, ProjectAction action, const Node *node) const
-{
- if (node->asFileNode()) {
- return action == ProjectAction::Rename
- || action == ProjectAction::RemoveFile;
- }
- if (node->isFolderNodeType() || node->isProjectNodeType()) {
- return action == ProjectAction::AddNewFile
- || action == ProjectAction::RemoveFile
- || action == ProjectAction::AddExistingFile;
- }
- return BuildSystem::supportsAction(context, action, node);
-}
-
-bool NimbleBuildSystem::addFiles(Node *, const FilePaths &filePaths, FilePaths *)
-{
- return m_projectScanner.addFiles(Utils::transform(filePaths, &FilePath::toUrlishString));
-}
-
-RemovedFilesFromProject NimbleBuildSystem::removeFiles(Node *,
- const FilePaths &filePaths,
- FilePaths *)
-{
- return m_projectScanner.removeFiles(Utils::transform(filePaths, &FilePath::toUrlishString));
-}
-
-bool NimbleBuildSystem::deleteFiles(Node *, const FilePaths &)
-{
- return true;
-}
-
-bool NimbleBuildSystem::renameFiles(Node *, const FilePairs &filesToRename, FilePaths *notRenamed)
-{
- bool success = true;
- for (const auto &[oldFilePath, newFilePath] : filesToRename) {
- if (!m_projectScanner.renameFile(oldFilePath.toUrlishString(), newFilePath.toUrlishString())) {
- success = false;
- if (notRenamed)
- *notRenamed << oldFilePath;
- }
- }
- return success;
-}
-
-} // Nim
diff --git a/src/plugins/nim/project/nimblebuildsystem.h b/src/plugins/nim/project/nimblebuildsystem.h
deleted file mode 100644
index 78e130ea746..00000000000
--- a/src/plugins/nim/project/nimblebuildsystem.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (C) Filippo Cucchetto <[email protected]>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include "nimbuildsystem.h"
-
-namespace Nim {
-
-struct NimbleTask
-{
- QString name;
- QString description;
-
- bool operator==(const NimbleTask &o) const {
- return name == o.name && description == o.description;
- }
-};
-
-struct NimbleMetadata
-{
- QStringList bin;
- QString binDir;
- QString srcDir;
-
- bool operator==(const NimbleMetadata &o) const {
- return bin == o.bin && binDir == o.binDir && srcDir == o.srcDir;
- }
- bool operator!=(const NimbleMetadata &o) const {
- return !operator==(o);
- }
-};
-
-class NimbleBuildSystem final : public ProjectExplorer::BuildSystem
-{
- Q_OBJECT
-
-public:
- NimbleBuildSystem(ProjectExplorer::Target *target);
-
- std::vector<NimbleTask> tasks() const;
-
-signals:
- void tasksChanged();
-
-private:
- void loadSettings();
- void saveSettings();
-
- void updateProject();
-
- bool supportsAction(ProjectExplorer::Node *,
- ProjectExplorer::ProjectAction action,
- const ProjectExplorer::Node *node) const override;
- bool addFiles(ProjectExplorer::Node *node,
- const Utils::FilePaths &filePaths, Utils::FilePaths *) override;
- ProjectExplorer::RemovedFilesFromProject removeFiles(ProjectExplorer::Node *node,
- const Utils::FilePaths &filePaths,
- Utils::FilePaths *) override;
- bool deleteFiles(ProjectExplorer::Node *, const Utils::FilePaths &) override;
- bool renameFiles(
- ProjectExplorer::Node *,
- const Utils::FilePairs &filesToRename,
- Utils::FilePaths *notRenamed) override;
- QString name() const final { return QLatin1String("mimble"); }
- void triggerParsing() final;
-
- std::vector<NimbleTask> m_tasks;
-
- NimProjectScanner m_projectScanner;
- ParseGuard m_guard;
-};
-
-} // Nim
diff --git a/src/plugins/nim/project/nimbleproject.cpp b/src/plugins/nim/project/nimbleproject.cpp
index 982ca06514f..70bde36c72c 100644
--- a/src/plugins/nim/project/nimbleproject.cpp
+++ b/src/plugins/nim/project/nimbleproject.cpp
@@ -3,13 +3,19 @@
#include "nimbleproject.h"
#include "nimconstants.h"
-#include "nimblebuildsystem.h"
+#include "../nimtr.h"
#include <coreplugin/icontext.h>
+#include <projectexplorer/buildconfiguration.h>
+#include <projectexplorer/buildinfo.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
+#include <projectexplorer/target.h>
+#include <projectexplorer/taskhub.h>
+#include <utils/algorithm.h>
+#include <utils/qtcprocess.h>
#include <utils/qtcassert.h>
using namespace ProjectExplorer;
@@ -17,6 +23,324 @@ using namespace Utils;
namespace Nim {
+struct NimbleMetadata
+{
+ QStringList bin;
+ QString binDir;
+ QString srcDir;
+
+ bool operator==(const NimbleMetadata &o) const {
+ return bin == o.bin && binDir == o.binDir && srcDir == o.srcDir;
+ }
+ bool operator!=(const NimbleMetadata &o) const {
+ return !operator==(o);
+ }
+};
+
+const char C_NIMBLEPROJECT_TASKS[] = "Nim.NimbleProject.Tasks";
+
+static QList<QByteArray> linesFromProcessOutput(Process *process)
+{
+ QList<QByteArray> lines = process->readAllRawStandardOutput().split('\n');
+ lines = Utils::transform(lines, [](const QByteArray &line){ return line.trimmed(); });
+ Utils::erase(lines, [](const QByteArray &line) { return line.isEmpty(); });
+ return lines;
+}
+
+static std::vector<NimbleTask> parseTasks(const FilePath &nimblePath, const FilePath &workingDirectory)
+{
+ Process process;
+ process.setCommand({nimblePath, {"tasks"}});
+ process.setWorkingDirectory(workingDirectory);
+ process.start();
+ process.waitForFinished();
+
+ std::vector<NimbleTask> result;
+
+ if (process.exitCode() != 0) {
+ TaskHub::addTask(ProjectExplorer::BuildSystemTask(Task::Error, process.cleanedStdOut()));
+ return result;
+ }
+
+ const QList<QByteArray> &lines = linesFromProcessOutput(&process);
+
+ for (const QByteArray &line : lines) {
+ QList<QByteArray> tokens = line.trimmed().split(' ');
+ QTC_ASSERT(!tokens.empty(), continue);
+ QString taskName = QString::fromUtf8(tokens.takeFirst());
+ QString taskDesc = QString::fromUtf8(tokens.join(' '));
+ result.push_back({std::move(taskName), std::move(taskDesc)});
+ }
+
+ return result;
+}
+
+static NimbleMetadata parseMetadata(const FilePath &nimblePath, const FilePath &workingDirectory)
+{
+ Process process;
+ process.setCommand({nimblePath, {"dump"}});
+ process.setWorkingDirectory(workingDirectory);
+ process.start();
+ process.waitForFinished();
+
+ NimbleMetadata result = {};
+
+ if (process.exitCode() != 0) {
+ TaskHub::addTask(ProjectExplorer::BuildSystemTask(Task::Error, process.cleanedStdOut()));
+ return result;
+ }
+ const QList<QByteArray> &lines = linesFromProcessOutput(&process);
+
+ for (const QByteArray &line : lines) {
+ QList<QByteArray> tokens = line.trimmed().split(':');
+ QTC_ASSERT(tokens.size() == 2, continue);
+ QString name = QString::fromUtf8(tokens.takeFirst()).trimmed();
+ QString value = QString::fromUtf8(tokens.takeFirst()).trimmed();
+ QTC_ASSERT(value.size() >= 2, continue);
+ QTC_ASSERT(value.front() == QChar('"'), continue);
+ QTC_ASSERT(value.back() == QChar('"'), continue);
+ value.remove(0, 1);
+ value.remove(value.size() - 1, 1);
+
+ if (name == "binDir")
+ result.binDir = value;
+ else if (name == "srcDir")
+ result.srcDir = value;
+ else if (name == "bin") {
+ QStringList bin = value.split(',');
+ bin = Utils::transform(bin, [](const QString &x){ return x.trimmed(); });
+ Utils::erase(bin, [](const QString &x) { return x.isEmpty(); });
+ result.bin = std::move(bin);
+ }
+ }
+
+ return result;
+}
+
+NimbleBuildSystem::NimbleBuildSystem(Target *target)
+ : BuildSystem(target), m_projectScanner(target->project())
+{
+ m_projectScanner.watchProjectFilePath();
+
+ connect(&m_projectScanner, &NimProjectScanner::fileChanged, this, [this](const QString &path) {
+ if (path == projectFilePath().toUrlishString())
+ requestDelayedParse();
+ });
+
+ connect(&m_projectScanner, &NimProjectScanner::requestReparse,
+ this, &NimbleBuildSystem::requestDelayedParse);
+
+ connect(&m_projectScanner, &NimProjectScanner::finished, this, &NimbleBuildSystem::updateProject);
+
+ connect(&m_projectScanner, &NimProjectScanner::directoryChanged, this, [this] (const QString &directory){
+ // Workaround for nimble creating temporary files in project root directory
+ // when querying the list of tasks.
+ // See https://github.com/nim-lang/nimble/issues/720
+ if (directory != projectDirectory().toUrlishString())
+ requestDelayedParse();
+ });
+
+ connect(target->project(), &ProjectExplorer::Project::settingsLoaded,
+ this, &NimbleBuildSystem::loadSettings);
+ connect(target->project(), &ProjectExplorer::Project::aboutToSaveSettings,
+ this, &NimbleBuildSystem::saveSettings);
+ requestDelayedParse();
+}
+
+void NimbleBuildSystem::triggerParsing()
+{
+ // Only allow one parsing run at the same time:
+ auto guard = guardParsingRun();
+ if (!guard.guardsProject())
+ return;
+ m_guard = std::move(guard);
+
+ m_projectScanner.startScan();
+}
+
+void NimbleBuildSystem::updateProject()
+{
+ const FilePath projectDir = projectDirectory();
+ const FilePath nimble = Nim::nimblePathFromKit(kit());
+
+ const NimbleMetadata metadata = parseMetadata(nimble, projectDir);
+ const FilePath binDir = projectDir.pathAppended(metadata.binDir);
+ const FilePath srcDir = projectDir.pathAppended("src");
+
+ QList<BuildTargetInfo> targets = Utils::transform(metadata.bin, [&](const QString &bin){
+ BuildTargetInfo info = {};
+ info.displayName = bin;
+ info.targetFilePath = binDir.pathAppended(bin);
+ info.projectFilePath = projectFilePath();
+ info.workingDirectory = binDir;
+ info.buildKey = bin;
+ return info;
+ });
+
+ setApplicationTargets(std::move(targets));
+
+ std::vector<NimbleTask> tasks = parseTasks(nimble, projectDir);
+ if (tasks != m_tasks) {
+ m_tasks = std::move(tasks);
+ emit tasksChanged();
+ }
+
+ // Complete scan
+ m_guard.markAsSuccess();
+ m_guard = {};
+
+ emitBuildSystemUpdated();
+}
+
+std::vector<NimbleTask> NimbleBuildSystem::tasks() const
+{
+ return m_tasks;
+}
+
+void NimbleBuildSystem::saveSettings()
+{
+ // only handles nimble specific settings - NimProjectScanner handles general settings
+ QStringList result;
+ for (const NimbleTask &task : m_tasks) {
+ result.push_back(task.name);
+ result.push_back(task.description);
+ }
+
+ project()->setNamedSettings(C_NIMBLEPROJECT_TASKS, result);
+}
+
+void NimbleBuildSystem::loadSettings()
+{
+ // only handles nimble specific settings - NimProjectScanner handles general settings
+ QStringList list = project()->namedSettings(C_NIMBLEPROJECT_TASKS).toStringList();
+
+ m_tasks.clear();
+ if (list.size() % 2 != 0)
+ return;
+
+ for (int i = 0; i < list.size(); i += 2)
+ m_tasks.push_back({list[i], list[i + 1]});
+}
+
+bool NimbleBuildSystem::supportsAction(Node *context, ProjectAction action, const Node *node) const
+{
+ if (node->asFileNode()) {
+ return action == ProjectAction::Rename
+ || action == ProjectAction::RemoveFile;
+ }
+ if (node->isFolderNodeType() || node->isProjectNodeType()) {
+ return action == ProjectAction::AddNewFile
+ || action == ProjectAction::RemoveFile
+ || action == ProjectAction::AddExistingFile;
+ }
+ return BuildSystem::supportsAction(context, action, node);
+}
+
+bool NimbleBuildSystem::addFiles(Node *, const FilePaths &filePaths, FilePaths *)
+{
+ return m_projectScanner.addFiles(Utils::transform(filePaths, &FilePath::toUrlishString));
+}
+
+RemovedFilesFromProject NimbleBuildSystem::removeFiles(Node *,
+ const FilePaths &filePaths,
+ FilePaths *)
+{
+ return m_projectScanner.removeFiles(Utils::transform(filePaths, &FilePath::toUrlishString));
+}
+
+bool NimbleBuildSystem::deleteFiles(Node *, const FilePaths &)
+{
+ return true;
+}
+
+bool NimbleBuildSystem::renameFiles(Node *, const FilePairs &filesToRename, FilePaths *notRenamed)
+{
+ bool success = true;
+ for (const auto &[oldFilePath, newFilePath] : filesToRename) {
+ if (!m_projectScanner.renameFile(oldFilePath.toUrlishString(), newFilePath.toUrlishString())) {
+ success = false;
+ if (notRenamed)
+ *notRenamed << oldFilePath;
+ }
+ }
+ return success;
+}
+
+class NimbleBuildConfiguration : public ProjectExplorer::BuildConfiguration
+{
+ Q_OBJECT
+
+ friend class ProjectExplorer::BuildConfigurationFactory;
+
+ NimbleBuildConfiguration(ProjectExplorer::Target *target, Utils::Id id)
+ : BuildConfiguration(target, id)
+ {
+ setConfigWidgetDisplayName(Tr::tr("General"));
+ setConfigWidgetHasFrame(true);
+ setBuildDirectorySettingsKey("Nim.NimbleBuildConfiguration.BuildDirectory");
+ appendInitialBuildStep(Constants::C_NIMBLEBUILDSTEP_ID);
+
+ setInitializer([this](const BuildInfo &info) {
+ setBuildType(info.buildType);
+ setBuildDirectory(project()->projectDirectory());
+ });
+ }
+
+ BuildType buildType() const override { return m_buildType; }
+
+ void fromMap(const Utils::Store &map) override
+ {
+ m_buildType = static_cast<BuildType>(
+ map[Constants::C_NIMBLEBUILDCONFIGURATION_BUILDTYPE].toInt());
+ BuildConfiguration::fromMap(map);
+ }
+
+ void toMap(Utils::Store &map) const override
+ {
+ BuildConfiguration::toMap(map);
+ map[Constants::C_NIMBLEBUILDCONFIGURATION_BUILDTYPE] = buildType();
+ }
+
+private:
+ void setBuildType(BuildType buildType)
+ {
+ if (buildType == m_buildType)
+ return;
+ m_buildType = buildType;
+ emit buildTypeChanged();
+ }
+
+ BuildType m_buildType = ProjectExplorer::BuildConfiguration::Unknown;
+};
+
+class NimbleBuildConfigurationFactory final : public ProjectExplorer::BuildConfigurationFactory
+{
+public:
+ NimbleBuildConfigurationFactory()
+ {
+ registerBuildConfiguration<NimbleBuildConfiguration>(Constants::C_NIMBLEBUILDCONFIGURATION_ID);
+ setSupportedProjectType(Constants::C_NIMBLEPROJECT_ID);
+ setSupportedProjectMimeTypeName(Constants::C_NIMBLE_MIMETYPE);
+
+ setBuildGenerator([](const Kit *, const FilePath &projectPath, bool forSetup) {
+ const auto oneBuild = [&](BuildConfiguration::BuildType buildType, const QString &typeName) {
+ BuildInfo info;
+ info.buildType = buildType;
+ info.typeName = typeName;
+ if (forSetup) {
+ info.displayName = info.typeName;
+ info.buildDirectory = projectPath.parentDir();
+ }
+ return info;
+ };
+ return QList<BuildInfo>{
+ oneBuild(BuildConfiguration::Debug, Tr::tr("Debug")),
+ oneBuild(BuildConfiguration::Release, Tr::tr("Release"))
+ };
+ });
+ }
+};
+
NimbleProject::NimbleProject(const FilePath &fileName)
: Project(Constants::C_NIMBLE_MIMETYPE, fileName)
{
@@ -54,7 +378,10 @@ void NimbleProject::setExcludedFiles(const QStringList &excludedFiles)
void setupNimbleProject()
{
+ static const NimbleBuildConfigurationFactory nimbleBuildConfigFactory;
ProjectManager::registerProjectType<NimbleProject>(Constants::C_NIMBLE_MIMETYPE);
}
} // Nim
+
+#include <nimbleproject.moc>
diff --git a/src/plugins/nim/project/nimbleproject.h b/src/plugins/nim/project/nimbleproject.h
index 03d7fb3299a..beb9d82c654 100644
--- a/src/plugins/nim/project/nimbleproject.h
+++ b/src/plugins/nim/project/nimbleproject.h
@@ -3,10 +3,63 @@
#pragma once
+#include "nimproject.h"
+
+#include <projectexplorer/buildsystem.h>
#include <projectexplorer/project.h>
namespace Nim {
+struct NimbleTask
+{
+ QString name;
+ QString description;
+
+ bool operator==(const NimbleTask &o) const {
+ return name == o.name && description == o.description;
+ }
+};
+
+class NimbleBuildSystem final : public ProjectExplorer::BuildSystem
+{
+ Q_OBJECT
+
+public:
+ NimbleBuildSystem(ProjectExplorer::Target *target);
+
+ std::vector<NimbleTask> tasks() const;
+
+signals:
+ void tasksChanged();
+
+private:
+ void loadSettings();
+ void saveSettings();
+
+ void updateProject();
+
+ bool supportsAction(ProjectExplorer::Node *,
+ ProjectExplorer::ProjectAction action,
+ const ProjectExplorer::Node *node) const override;
+ bool addFiles(ProjectExplorer::Node *node,
+ const Utils::FilePaths &filePaths, Utils::FilePaths *) override;
+ ProjectExplorer::RemovedFilesFromProject removeFiles(ProjectExplorer::Node *node,
+ const Utils::FilePaths &filePaths,
+ Utils::FilePaths *) override;
+ bool deleteFiles(ProjectExplorer::Node *, const Utils::FilePaths &) override;
+ bool renameFiles(
+ ProjectExplorer::Node *,
+ const Utils::FilePairs &filesToRename,
+ Utils::FilePaths *notRenamed) override;
+ QString name() const final { return QLatin1String("mimble"); }
+ void triggerParsing() final;
+
+ std::vector<NimbleTask> m_tasks;
+
+ NimProjectScanner m_projectScanner;
+ ParseGuard m_guard;
+};
+
class NimbleProject final : public ProjectExplorer::Project
{
public:
diff --git a/src/plugins/nim/project/nimblerunconfiguration.cpp b/src/plugins/nim/project/nimblerunconfiguration.cpp
index 4e6884e8a0a..adecb710e9c 100644
--- a/src/plugins/nim/project/nimblerunconfiguration.cpp
+++ b/src/plugins/nim/project/nimblerunconfiguration.cpp
@@ -3,10 +3,11 @@
#include "nimblerunconfiguration.h"
-#include "nimbuildsystem.h"
#include "nimconstants.h"
+#include "nimproject.h"
#include "nimtr.h"
+#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runconfigurationaspects.h>
#include <projectexplorer/target.h>
diff --git a/src/plugins/nim/project/nimbletaskstep.cpp b/src/plugins/nim/project/nimbletaskstep.cpp
index 1885a9daa15..e2a34018f8f 100644
--- a/src/plugins/nim/project/nimbletaskstep.cpp
+++ b/src/plugins/nim/project/nimbletaskstep.cpp
@@ -3,8 +3,8 @@
#include "nimbletaskstep.h"
+#include "nimbleproject.h"
#include "nimconstants.h"
-#include "nimblebuildsystem.h"
#include "nimtr.h"
#include <projectexplorer/abstractprocessstep.h>
diff --git a/src/plugins/nim/project/nimbuildconfiguration.cpp b/src/plugins/nim/project/nimbuildconfiguration.cpp
deleted file mode 100644
index 0db746ee7a9..00000000000
--- a/src/plugins/nim/project/nimbuildconfiguration.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (C) Filippo Cucchetto <[email protected]>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "nimbuildconfiguration.h"
-#include "nimcompilerbuildstep.h"
-
-#include "../nimtr.h"
-#include "../nimconstants.h"
-
-#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/buildinfo.h>
-#include <projectexplorer/buildsteplist.h>
-#include <projectexplorer/buildstep.h>
-#include <projectexplorer/kit.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/projectexplorer.h>
-#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/target.h>
-
-#include <utils/aspects.h>
-#include <utils/qtcassert.h>
-
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace Nim {
-
-static FilePath defaultBuildDirectory(const Kit *k,
- const FilePath &projectFilePath,
- const QString &bc,
- BuildConfiguration::BuildType buildType)
-{
- return BuildConfiguration::buildDirectoryFromTemplate(
- projectFilePath.parentDir(), projectFilePath, projectFilePath.baseName(),
- k, bc, buildType, "nim");
-}
-
-NimBuildConfiguration::NimBuildConfiguration(Target *target, Utils::Id id)
- : BuildConfiguration(target, id)
-{
- setConfigWidgetDisplayName(Tr::tr("General"));
- setConfigWidgetHasFrame(true);
- setBuildDirectorySettingsKey("Nim.NimBuildConfiguration.BuildDirectory");
-
- appendInitialBuildStep(Constants::C_NIMCOMPILERBUILDSTEP_ID);
- appendInitialCleanStep(Constants::C_NIMCOMPILERCLEANSTEP_ID);
-
- setInitializer([this, target](const BuildInfo &info) {
- // Create the build configuration and initialize it from build info
- setBuildDirectory(defaultBuildDirectory(target->kit(),
- project()->projectFilePath(),
- displayName(),
- buildType()));
-
- auto nimCompilerBuildStep = buildSteps()->firstOfType<NimCompilerBuildStep>();
- QTC_ASSERT(nimCompilerBuildStep, return);
- nimCompilerBuildStep->setBuildType(info.buildType);
- });
-}
-
-
-FilePath NimBuildConfiguration::cacheDirectory() const
-{
- return buildDirectory().pathAppended("nimcache");
-}
-
-FilePath NimBuildConfiguration::outFilePath() const
-{
- auto nimCompilerBuildStep = buildSteps()->firstOfType<NimCompilerBuildStep>();
- QTC_ASSERT(nimCompilerBuildStep, return {});
- return nimCompilerBuildStep->outFilePath();
-}
-
-// NimBuildConfigurationFactory
-
-NimBuildConfigurationFactory::NimBuildConfigurationFactory()
-{
- registerBuildConfiguration<NimBuildConfiguration>(Constants::C_NIMBUILDCONFIGURATION_ID);
- setSupportedProjectType(Constants::C_NIMPROJECT_ID);
- setSupportedProjectMimeTypeName(Constants::C_NIM_PROJECT_MIMETYPE);
-
- setBuildGenerator([](const Kit *k, const FilePath &projectPath, bool forSetup) {
- const auto oneBuild = [&](BuildConfiguration::BuildType buildType, const QString &typeName) {
- BuildInfo info;
- info.buildType = buildType;
- info.typeName = typeName;
- if (forSetup) {
- info.displayName = info.typeName;
- info.buildDirectory = defaultBuildDirectory(k, projectPath, info.typeName, buildType);
- }
- return info;
- };
- return QList<BuildInfo>{
- oneBuild(BuildConfiguration::Debug, Tr::tr("Debug")),
- oneBuild(BuildConfiguration::Release, Tr::tr("Release"))
- };
- });
-}
-
-} // namespace Nim
-
diff --git a/src/plugins/nim/project/nimbuildconfiguration.h b/src/plugins/nim/project/nimbuildconfiguration.h
deleted file mode 100644
index b4b3fb0f57c..00000000000
--- a/src/plugins/nim/project/nimbuildconfiguration.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) Filippo Cucchetto <[email protected]>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/target.h>
-
-namespace Nim {
-
-class NimBuildConfiguration : public ProjectExplorer::BuildConfiguration
-{
- Q_OBJECT
-
- friend class ProjectExplorer::BuildConfigurationFactory;
- NimBuildConfiguration(ProjectExplorer::Target *target, Utils::Id id);
-
-public:
- Utils::FilePath cacheDirectory() const;
- Utils::FilePath outFilePath() const;
-};
-
-
-class NimBuildConfigurationFactory final : public ProjectExplorer::BuildConfigurationFactory
-{
-public:
- NimBuildConfigurationFactory();
-};
-
-} // Nim
diff --git a/src/plugins/nim/project/nimbuildsystem.cpp b/src/plugins/nim/project/nimbuildsystem.cpp
deleted file mode 100644
index 91862171a2a..00000000000
--- a/src/plugins/nim/project/nimbuildsystem.cpp
+++ /dev/null
@@ -1,261 +0,0 @@
-// Copyright (C) Filippo Cucchetto <[email protected]>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "nimbuildsystem.h"
-
-#include "nimconstants.h"
-#include "nimbleproject.h"
-
-#include <projectexplorer/target.h>
-#include <projectexplorer/toolchain.h>
-#include <projectexplorer/toolchainkitaspect.h>
-
-#include <utils/algorithm.h>
-#include <utils/fileutils.h>
-#include <utils/qtcassert.h>
-
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace Nim {
-
-const char SETTINGS_KEY[] = "Nim.BuildSystem";
-const char EXCLUDED_FILES_KEY[] = "ExcludedFiles";
-
-NimProjectScanner::NimProjectScanner(Project *project)
- : m_project(project)
-{
- connect(&m_directoryWatcher, &FileSystemWatcher::directoryChanged,
- this, &NimProjectScanner::directoryChanged);
- connect(&m_directoryWatcher, &FileSystemWatcher::fileChanged,
- this, &NimProjectScanner::fileChanged);
-
- connect(m_project, &Project::settingsLoaded, this, &NimProjectScanner::loadSettings);
- connect(m_project, &Project::aboutToSaveSettings, this, &NimProjectScanner::saveSettings);
-
- connect(&m_scanner, &TreeScanner::finished, this, [this] {
- // Collect scanned nodes
- std::vector<std::unique_ptr<FileNode>> nodes;
- TreeScanner::Result scanResult = m_scanner.release();
- for (FileNode *node : scanResult.takeAllFiles()) {
- if (!node->path().endsWith(".nim") && !node->path().endsWith(".nimble"))
- node->setEnabled(false); // Disable files that do not end in .nim
- nodes.emplace_back(node);
- }
-
- // Sync watched dirs
- const QSet<FilePath> fsDirs = Utils::transform<QSet>(nodes,
- [](const std::unique_ptr<FileNode> &fn) { return fn->directory(); });
- const QSet<FilePath> projectDirs = Utils::toSet(m_directoryWatcher.directoryPaths());
- m_directoryWatcher.addDirectories(Utils::toList(fsDirs - projectDirs), FileSystemWatcher::WatchAllChanges);
- m_directoryWatcher.removeDirectories(Utils::toList(projectDirs - fsDirs));
-
- // Sync project files
- const QSet<FilePath> fsFiles = Utils::transform<QSet>(nodes, &FileNode::filePath);
- const QSet<FilePath> projectFiles = Utils::toSet(m_project->files([](const Node *n) { return Project::AllFiles(n); }));
-
- if (fsFiles != projectFiles) {
- auto projectNode = std::make_unique<ProjectNode>(m_project->projectDirectory());
- projectNode->setDisplayName(m_project->displayName());
- projectNode->addNestedNodes(std::move(nodes));
- m_project->setRootProjectNode(std::move(projectNode));
- }
-
- emit finished();
- });
-}
-
-void NimProjectScanner::loadSettings()
-{
- QVariantMap settings = m_project->namedSettings(SETTINGS_KEY).toMap();
- if (settings.contains(EXCLUDED_FILES_KEY))
- setExcludedFiles(settings.value(EXCLUDED_FILES_KEY, excludedFiles()).toStringList());
-
- emit requestReparse();
-}
-
-void NimProjectScanner::saveSettings()
-{
- QVariantMap settings;
- settings.insert(EXCLUDED_FILES_KEY, excludedFiles());
- m_project->setNamedSettings(SETTINGS_KEY, settings);
-}
-
-void NimProjectScanner::startScan()
-{
- m_scanner.setFilter(
- [excludedFiles = excludedFiles()](const Utils::MimeType &, const FilePath &fp) {
- const QString path = fp.toUrlishString();
- return excludedFiles.contains(path) || path.endsWith(".nimproject")
- || path.contains(".nimproject.user") || path.contains(".nimble.user");
- });
-
- m_scanner.asyncScanForFiles(m_project->projectDirectory());
-}
-
-void NimProjectScanner::watchProjectFilePath()
-{
- m_directoryWatcher.addFile(m_project->projectFilePath(), FileSystemWatcher::WatchModifiedDate);
-}
-
-void NimProjectScanner::setExcludedFiles(const QStringList &list)
-{
- static_cast<NimbleProject *>(m_project)->setExcludedFiles(list);
-}
-
-QStringList NimProjectScanner::excludedFiles() const
-{
- return static_cast<NimbleProject *>(m_project)->excludedFiles();
-}
-
-bool NimProjectScanner::addFiles(const QStringList &filePaths)
-{
- setExcludedFiles(Utils::filtered(excludedFiles(), [&](const QString & f) {
- return !filePaths.contains(f);
- }));
-
- emit requestReparse();
-
- return true;
-}
-
-RemovedFilesFromProject NimProjectScanner::removeFiles(const QStringList &filePaths)
-{
- setExcludedFiles(Utils::filteredUnique(excludedFiles() + filePaths));
-
- emit requestReparse();
-
- return RemovedFilesFromProject::Ok;
-}
-
-bool NimProjectScanner::renameFile(const QString &, const QString &to)
-{
- QStringList files = excludedFiles();
- files.removeOne(to);
- setExcludedFiles(files);
-
- emit requestReparse();
-
- return true;
-}
-
-// NimBuildSystem
-
-class NimBuildSystem final : public BuildSystem
-{
-public:
- explicit NimBuildSystem(Target *target);
-
- bool supportsAction(Node *, ProjectAction action, const Node *node) const final;
- bool addFiles(Node *node, const FilePaths &filePaths, FilePaths *) final;
- RemovedFilesFromProject removeFiles(Node *node,
- const FilePaths &filePaths,
- FilePaths *) final;
- bool deleteFiles(Node *, const FilePaths &) final;
- bool renameFiles(
- Node *,
- const Utils::FilePairs &filesToRename,
- Utils::FilePaths *notRenamed) final;
- QString name() const final { return QLatin1String("nim"); }
-
- void triggerParsing() final;
-
-protected:
- ParseGuard m_guard;
- NimProjectScanner m_projectScanner;
-};
-
-NimBuildSystem::NimBuildSystem(Target *target)
- : BuildSystem(target), m_projectScanner(target->project())
-{
- connect(&m_projectScanner, &NimProjectScanner::finished, this, [this] {
- m_guard.markAsSuccess();
- m_guard = {}; // Trigger destructor of previous object, emitting parsingFinished()
-
- emitBuildSystemUpdated();
- });
-
- connect(&m_projectScanner, &NimProjectScanner::requestReparse,
- this, &NimBuildSystem::requestDelayedParse);
-
- connect(&m_projectScanner, &NimProjectScanner::directoryChanged, this, [this] {
- if (!isWaitingForParse())
- requestDelayedParse();
- });
-
- requestDelayedParse();
-}
-
-void NimBuildSystem::triggerParsing()
-{
- m_guard = guardParsingRun();
- m_projectScanner.startScan();
-}
-
-FilePath nimPathFromKit(Kit *kit)
-{
- auto tc = ToolchainKitAspect::toolchain(kit, Constants::C_NIMLANGUAGE_ID);
- QTC_ASSERT(tc, return {});
- const FilePath command = tc->compilerCommand();
- return command.isEmpty() ? FilePath() : command.absolutePath();
-}
-
-FilePath nimblePathFromKit(Kit *kit)
-{
- // There's no extra setting for "nimble", derive it from the "nim" path.
- const FilePath nimbleFromPath = FilePath("nimble").searchInPath();
- const FilePath nimPath = nimPathFromKit(kit);
- const FilePath nimbleFromKit = nimPath.pathAppended("nimble").withExecutableSuffix();
- return nimbleFromKit.exists() ? nimbleFromKit.canonicalPath() : nimbleFromPath;
-}
-
-bool NimBuildSystem::supportsAction(Node *context, ProjectAction action, const Node *node) const
-{
- if (node->asFileNode()) {
- return action == ProjectAction::Rename
- || action == ProjectAction::RemoveFile;
- }
- if (node->isFolderNodeType() || node->isProjectNodeType()) {
- return action == ProjectAction::AddNewFile
- || action == ProjectAction::RemoveFile
- || action == ProjectAction::AddExistingFile;
- }
- return BuildSystem::supportsAction(context, action, node);
-}
-
-bool NimBuildSystem::addFiles(Node *, const FilePaths &filePaths, FilePaths *)
-{
- return m_projectScanner.addFiles(Utils::transform(filePaths, &FilePath::toUrlishString));
-}
-
-RemovedFilesFromProject NimBuildSystem::removeFiles(Node *,
- const FilePaths &filePaths,
- FilePaths *)
-{
- return m_projectScanner.removeFiles(Utils::transform(filePaths, &FilePath::toUrlishString));
-}
-
-bool NimBuildSystem::deleteFiles(Node *, const FilePaths &)
-{
- return true;
-}
-
-bool NimBuildSystem::renameFiles(Node *, const FilePairs &filesToRename, FilePaths *notRenamed)
-{
- bool success = true;
- for (const auto &[oldFilePath, newFilePath] : filesToRename) {
- if (!m_projectScanner.renameFile(oldFilePath.toUrlishString(), newFilePath.toUrlishString())) {
- success = false;
- if (notRenamed)
- *notRenamed << oldFilePath;
- }
- }
- return success;
-}
-
-BuildSystem *createNimBuildSystem(Target *target)
-{
- return new NimBuildSystem(target);
-}
-
-} // namespace Nim
diff --git a/src/plugins/nim/project/nimbuildsystem.h b/src/plugins/nim/project/nimbuildsystem.h
deleted file mode 100644
index 8eefbee50f2..00000000000
--- a/src/plugins/nim/project/nimbuildsystem.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (C) Filippo Cucchetto <[email protected]>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include <projectexplorer/buildsystem.h>
-#include <projectexplorer/treescanner.h>
-
-#include <utils/filesystemwatcher.h>
-
-namespace ProjectExplorer { class Kit; }
-
-namespace Nim {
-
-Utils::FilePath nimPathFromKit(ProjectExplorer::Kit *kit);
-Utils::FilePath nimblePathFromKit(ProjectExplorer::Kit *kit);
-
-class NimProjectScanner : public QObject
-{
- Q_OBJECT
-
-public:
- explicit NimProjectScanner(ProjectExplorer::Project *project);
-
- void startScan();
- void watchProjectFilePath();
-
- void setExcludedFiles(const QStringList &list);
- QStringList excludedFiles() const;
-
- bool addFiles(const QStringList &filePaths);
- ProjectExplorer::RemovedFilesFromProject removeFiles(const QStringList &filePaths);
- bool renameFile(const QString &from, const QString &to);
-
-signals:
- void finished();
- void requestReparse();
- void directoryChanged(const QString &path);
- void fileChanged(const QString &path);
-
-private:
- void loadSettings();
- void saveSettings();
-
- ProjectExplorer::Project *m_project = nullptr;
- ProjectExplorer::TreeScanner m_scanner;
- Utils::FileSystemWatcher m_directoryWatcher;
-};
-
-ProjectExplorer::BuildSystem *createNimBuildSystem(ProjectExplorer::Target *target);
-
-} // namespace Nim
diff --git a/src/plugins/nim/project/nimcompilerbuildstep.cpp b/src/plugins/nim/project/nimcompilerbuildstep.cpp
index 9b724ecf058..ea2fb12774b 100644
--- a/src/plugins/nim/project/nimcompilerbuildstep.cpp
+++ b/src/plugins/nim/project/nimcompilerbuildstep.cpp
@@ -3,10 +3,10 @@
#include "nimcompilerbuildstep.h"
-#include "nimbuildconfiguration.h"
#include "nimconstants.h"
#include "nimoutputtaskparser.h"
#include "nimtr.h"
+#include "project/nimproject.h"
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/ioutputparser.h>
diff --git a/src/plugins/nim/project/nimcompilercleanstep.cpp b/src/plugins/nim/project/nimcompilercleanstep.cpp
index 5de8a0b96de..4cde95e93b4 100644
--- a/src/plugins/nim/project/nimcompilercleanstep.cpp
+++ b/src/plugins/nim/project/nimcompilercleanstep.cpp
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "nimcompilercleanstep.h"
-#include "nimbuildconfiguration.h"
+#include "nimproject.h"
#include "../nimconstants.h"
#include "../nimtr.h"
diff --git a/src/plugins/nim/project/nimproject.cpp b/src/plugins/nim/project/nimproject.cpp
index 53e91b88a80..d3eb6b2a6a7 100644
--- a/src/plugins/nim/project/nimproject.cpp
+++ b/src/plugins/nim/project/nimproject.cpp
@@ -5,12 +5,15 @@
#include "../nimconstants.h"
#include "../nimtr.h"
-#include "nimbuildsystem.h"
+#include "nimbleproject.h"
+#include "nimcompilerbuildstep.h"
#include <coreplugin/icontext.h>
+#include <projectexplorer/buildinfo.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
+#include <projectexplorer/target.h>
#include <projectexplorer/toolchain.h>
#include <projectexplorer/toolchainkitaspect.h>
@@ -19,6 +22,317 @@ using namespace Utils;
namespace Nim {
+const char SETTINGS_KEY[] = "Nim.BuildSystem";
+const char EXCLUDED_FILES_KEY[] = "ExcludedFiles";
+
+NimProjectScanner::NimProjectScanner(Project *project)
+ : m_project(project)
+{
+ connect(&m_directoryWatcher, &FileSystemWatcher::directoryChanged,
+ this, &NimProjectScanner::directoryChanged);
+ connect(&m_directoryWatcher, &FileSystemWatcher::fileChanged,
+ this, &NimProjectScanner::fileChanged);
+
+ connect(m_project, &Project::settingsLoaded, this, &NimProjectScanner::loadSettings);
+ connect(m_project, &Project::aboutToSaveSettings, this, &NimProjectScanner::saveSettings);
+
+ connect(&m_scanner, &TreeScanner::finished, this, [this] {
+ // Collect scanned nodes
+ std::vector<std::unique_ptr<FileNode>> nodes;
+ TreeScanner::Result scanResult = m_scanner.release();
+ for (FileNode *node : scanResult.takeAllFiles()) {
+ if (!node->path().endsWith(".nim") && !node->path().endsWith(".nimble"))
+ node->setEnabled(false); // Disable files that do not end in .nim
+ nodes.emplace_back(node);
+ }
+
+ // Sync watched dirs
+ const QSet<FilePath> fsDirs = Utils::transform<QSet>(nodes,
+ [](const std::unique_ptr<FileNode> &fn) { return fn->directory(); });
+ const QSet<FilePath> projectDirs = Utils::toSet(m_directoryWatcher.directoryPaths());
+ m_directoryWatcher.addDirectories(Utils::toList(fsDirs - projectDirs), FileSystemWatcher::WatchAllChanges);
+ m_directoryWatcher.removeDirectories(Utils::toList(projectDirs - fsDirs));
+
+ // Sync project files
+ const QSet<FilePath> fsFiles = Utils::transform<QSet>(nodes, &FileNode::filePath);
+ const QSet<FilePath> projectFiles = Utils::toSet(m_project->files([](const Node *n) { return Project::AllFiles(n); }));
+
+ if (fsFiles != projectFiles) {
+ auto projectNode = std::make_unique<ProjectNode>(m_project->projectDirectory());
+ projectNode->setDisplayName(m_project->displayName());
+ projectNode->addNestedNodes(std::move(nodes));
+ m_project->setRootProjectNode(std::move(projectNode));
+ }
+
+ emit finished();
+ });
+}
+
+void NimProjectScanner::loadSettings()
+{
+ QVariantMap settings = m_project->namedSettings(SETTINGS_KEY).toMap();
+ if (settings.contains(EXCLUDED_FILES_KEY))
+ setExcludedFiles(settings.value(EXCLUDED_FILES_KEY, excludedFiles()).toStringList());
+
+ emit requestReparse();
+}
+
+void NimProjectScanner::saveSettings()
+{
+ QVariantMap settings;
+ settings.insert(EXCLUDED_FILES_KEY, excludedFiles());
+ m_project->setNamedSettings(SETTINGS_KEY, settings);
+}
+
+void NimProjectScanner::startScan()
+{
+ m_scanner.setFilter(
+ [excludedFiles = excludedFiles()](const Utils::MimeType &, const FilePath &fp) {
+ const QString path = fp.toUrlishString();
+ return excludedFiles.contains(path) || path.endsWith(".nimproject")
+ || path.contains(".nimproject.user") || path.contains(".nimble.user");
+ });
+
+ m_scanner.asyncScanForFiles(m_project->projectDirectory());
+}
+
+void NimProjectScanner::watchProjectFilePath()
+{
+ m_directoryWatcher.addFile(m_project->projectFilePath(), FileSystemWatcher::WatchModifiedDate);
+}
+
+void NimProjectScanner::setExcludedFiles(const QStringList &list)
+{
+ static_cast<NimbleProject *>(m_project)->setExcludedFiles(list);
+}
+
+QStringList NimProjectScanner::excludedFiles() const
+{
+ return static_cast<NimbleProject *>(m_project)->excludedFiles();
+}
+
+bool NimProjectScanner::addFiles(const QStringList &filePaths)
+{
+ setExcludedFiles(Utils::filtered(excludedFiles(), [&](const QString & f) {
+ return !filePaths.contains(f);
+ }));
+
+ emit requestReparse();
+
+ return true;
+}
+
+RemovedFilesFromProject NimProjectScanner::removeFiles(const QStringList &filePaths)
+{
+ setExcludedFiles(Utils::filteredUnique(excludedFiles() + filePaths));
+
+ emit requestReparse();
+
+ return RemovedFilesFromProject::Ok;
+}
+
+bool NimProjectScanner::renameFile(const QString &, const QString &to)
+{
+ QStringList files = excludedFiles();
+ files.removeOne(to);
+ setExcludedFiles(files);
+
+ emit requestReparse();
+
+ return true;
+}
+
+// NimBuildSystem
+
+class NimBuildSystem final : public BuildSystem
+{
+public:
+ explicit NimBuildSystem(Target *target);
+
+ bool supportsAction(Node *, ProjectAction action, const Node *node) const final;
+ bool addFiles(Node *node, const FilePaths &filePaths, FilePaths *) final;
+ RemovedFilesFromProject removeFiles(Node *node,
+ const FilePaths &filePaths,
+ FilePaths *) final;
+ bool deleteFiles(Node *, const FilePaths &) final;
+ bool renameFiles(
+ Node *,
+ const Utils::FilePairs &filesToRename,
+ Utils::FilePaths *notRenamed) final;
+ QString name() const final { return QLatin1String("nim"); }
+
+ void triggerParsing() final;
+
+protected:
+ ParseGuard m_guard;
+ NimProjectScanner m_projectScanner;
+};
+
+NimBuildSystem::NimBuildSystem(Target *target)
+ : BuildSystem(target), m_projectScanner(target->project())
+{
+ connect(&m_projectScanner, &NimProjectScanner::finished, this, [this] {
+ m_guard.markAsSuccess();
+ m_guard = {}; // Trigger destructor of previous object, emitting parsingFinished()
+
+ emitBuildSystemUpdated();
+ });
+
+ connect(&m_projectScanner, &NimProjectScanner::requestReparse,
+ this, &NimBuildSystem::requestDelayedParse);
+
+ connect(&m_projectScanner, &NimProjectScanner::directoryChanged, this, [this] {
+ if (!isWaitingForParse())
+ requestDelayedParse();
+ });
+
+ requestDelayedParse();
+}
+
+void NimBuildSystem::triggerParsing()
+{
+ m_guard = guardParsingRun();
+ m_projectScanner.startScan();
+}
+
+FilePath nimPathFromKit(Kit *kit)
+{
+ auto tc = ToolchainKitAspect::toolchain(kit, Constants::C_NIMLANGUAGE_ID);
+ QTC_ASSERT(tc, return {});
+ const FilePath command = tc->compilerCommand();
+ return command.isEmpty() ? FilePath() : command.absolutePath();
+}
+
+FilePath nimblePathFromKit(Kit *kit)
+{
+ // There's no extra setting for "nimble", derive it from the "nim" path.
+ const FilePath nimbleFromPath = FilePath("nimble").searchInPath();
+ const FilePath nimPath = nimPathFromKit(kit);
+ const FilePath nimbleFromKit = nimPath.pathAppended("nimble").withExecutableSuffix();
+ return nimbleFromKit.exists() ? nimbleFromKit.canonicalPath() : nimbleFromPath;
+}
+
+bool NimBuildSystem::supportsAction(Node *context, ProjectAction action, const Node *node) const
+{
+ if (node->asFileNode()) {
+ return action == ProjectAction::Rename
+ || action == ProjectAction::RemoveFile;
+ }
+ if (node->isFolderNodeType() || node->isProjectNodeType()) {
+ return action == ProjectAction::AddNewFile
+ || action == ProjectAction::RemoveFile
+ || action == ProjectAction::AddExistingFile;
+ }
+ return BuildSystem::supportsAction(context, action, node);
+}
+
+bool NimBuildSystem::addFiles(Node *, const FilePaths &filePaths, FilePaths *)
+{
+ return m_projectScanner.addFiles(Utils::transform(filePaths, &FilePath::toUrlishString));
+}
+
+RemovedFilesFromProject NimBuildSystem::removeFiles(Node *,
+ const FilePaths &filePaths,
+ FilePaths *)
+{
+ return m_projectScanner.removeFiles(Utils::transform(filePaths, &FilePath::toUrlishString));
+}
+
+bool NimBuildSystem::deleteFiles(Node *, const FilePaths &)
+{
+ return true;
+}
+
+bool NimBuildSystem::renameFiles(Node *, const FilePairs &filesToRename, FilePaths *notRenamed)
+{
+ bool success = true;
+ for (const auto &[oldFilePath, newFilePath] : filesToRename) {
+ if (!m_projectScanner.renameFile(oldFilePath.toUrlishString(), newFilePath.toUrlishString())) {
+ success = false;
+ if (notRenamed)
+ *notRenamed << oldFilePath;
+ }
+ }
+ return success;
+}
+
+static FilePath defaultBuildDirectory(const Kit *k,
+ const FilePath &projectFilePath,
+ const QString &bc,
+ BuildConfiguration::BuildType buildType)
+{
+ return BuildConfiguration::buildDirectoryFromTemplate(
+ projectFilePath.parentDir(), projectFilePath, projectFilePath.baseName(),
+ k, bc, buildType, "nim");
+}
+
+NimBuildConfiguration::NimBuildConfiguration(Target *target, Utils::Id id)
+ : BuildConfiguration(target, id)
+{
+ setConfigWidgetDisplayName(Tr::tr("General"));
+ setConfigWidgetHasFrame(true);
+ setBuildDirectorySettingsKey("Nim.NimBuildConfiguration.BuildDirectory");
+
+ appendInitialBuildStep(Constants::C_NIMCOMPILERBUILDSTEP_ID);
+ appendInitialCleanStep(Constants::C_NIMCOMPILERCLEANSTEP_ID);
+
+ setInitializer([this, target](const BuildInfo &info) {
+ // Create the build configuration and initialize it from build info
+ setBuildDirectory(defaultBuildDirectory(target->kit(),
+ project()->projectFilePath(),
+ displayName(),
+ buildType()));
+
+ auto nimCompilerBuildStep = buildSteps()->firstOfType<NimCompilerBuildStep>();
+ QTC_ASSERT(nimCompilerBuildStep, return);
+ nimCompilerBuildStep->setBuildType(info.buildType);
+ });
+}
+
+
+FilePath NimBuildConfiguration::cacheDirectory() const
+{
+ return buildDirectory().pathAppended("nimcache");
+}
+
+FilePath NimBuildConfiguration::outFilePath() const
+{
+ auto nimCompilerBuildStep = buildSteps()->firstOfType<NimCompilerBuildStep>();
+ QTC_ASSERT(nimCompilerBuildStep, return {});
+ return nimCompilerBuildStep->outFilePath();
+}
+
+// NimBuildConfigurationFactory
+
+class NimBuildConfigurationFactory final : public ProjectExplorer::BuildConfigurationFactory
+{
+public:
+ NimBuildConfigurationFactory()
+ {
+ registerBuildConfiguration<NimBuildConfiguration>(Constants::C_NIMBUILDCONFIGURATION_ID);
+ setSupportedProjectType(Constants::C_NIMPROJECT_ID);
+ setSupportedProjectMimeTypeName(Constants::C_NIM_PROJECT_MIMETYPE);
+
+ setBuildGenerator([](const Kit *k, const FilePath &projectPath, bool forSetup) {
+ const auto oneBuild = [&](BuildConfiguration::BuildType buildType, const QString &typeName) {
+ BuildInfo info;
+ info.buildType = buildType;
+ info.typeName = typeName;
+ if (forSetup) {
+ info.displayName = info.typeName;
+ info.buildDirectory = defaultBuildDirectory(k, projectPath, info.typeName, buildType);
+ }
+ return info;
+ };
+ return QList<BuildInfo>{
+ oneBuild(BuildConfiguration::Debug, Tr::tr("Debug")),
+ oneBuild(BuildConfiguration::Release, Tr::tr("Release"))
+ };
+ });
+ }
+};
+
+
class NimProject final : public Project
{
public:
@@ -46,7 +360,7 @@ NimProject::NimProject(const FilePath &filePath) : Project(Constants::C_NIM_MIME
// ensure debugging is enabled (Nim plugin translates nim code to C code)
setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
- setBuildSystemCreator(&createNimBuildSystem);
+ setBuildSystemCreator<NimBuildSystem>();
}
Tasks NimProject::projectIssues(const Kit *k) const
@@ -90,6 +404,7 @@ void NimProject::setExcludedFiles(const QStringList &excludedFiles)
void setupNimProject()
{
+ static const NimBuildConfigurationFactory buildConfigFactory;
ProjectManager::registerProjectType<NimProject>(Constants::C_NIM_PROJECT_MIMETYPE);
}
diff --git a/src/plugins/nim/project/nimproject.h b/src/plugins/nim/project/nimproject.h
index 48e104f7ba3..ae7c746edd9 100644
--- a/src/plugins/nim/project/nimproject.h
+++ b/src/plugins/nim/project/nimproject.h
@@ -3,8 +3,61 @@
#pragma once
+#include <projectexplorer/buildconfiguration.h>
+#include <projectexplorer/projectnodes.h>
+#include <projectexplorer/treescanner.h>
+
+#include <utils/filesystemwatcher.h>
+
namespace Nim {
+class NimBuildConfiguration : public ProjectExplorer::BuildConfiguration
+{
+ Q_OBJECT
+
+ friend class ProjectExplorer::BuildConfigurationFactory;
+ NimBuildConfiguration(ProjectExplorer::Target *target, Utils::Id id);
+
+public:
+ Utils::FilePath cacheDirectory() const;
+ Utils::FilePath outFilePath() const;
+};
+
+Utils::FilePath nimPathFromKit(ProjectExplorer::Kit *kit);
+Utils::FilePath nimblePathFromKit(ProjectExplorer::Kit *kit);
+
+class NimProjectScanner : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit NimProjectScanner(ProjectExplorer::Project *project);
+
+ void startScan();
+ void watchProjectFilePath();
+
+ void setExcludedFiles(const QStringList &list);
+ QStringList excludedFiles() const;
+
+ bool addFiles(const QStringList &filePaths);
+ ProjectExplorer::RemovedFilesFromProject removeFiles(const QStringList &filePaths);
+ bool renameFile(const QString &from, const QString &to);
+
+signals:
+ void finished();
+ void requestReparse();
+ void directoryChanged(const QString &path);
+ void fileChanged(const QString &path);
+
+private:
+ void loadSettings();
+ void saveSettings();
+
+ ProjectExplorer::Project *m_project = nullptr;
+ ProjectExplorer::TreeScanner m_scanner;
+ Utils::FileSystemWatcher m_directoryWatcher;
+};
+
void setupNimProject();
} // Nim
diff --git a/src/plugins/nim/project/nimrunconfiguration.cpp b/src/plugins/nim/project/nimrunconfiguration.cpp
index 30ed9c998df..c640234c7b4 100644
--- a/src/plugins/nim/project/nimrunconfiguration.cpp
+++ b/src/plugins/nim/project/nimrunconfiguration.cpp
@@ -1,14 +1,15 @@
// Copyright (C) Filippo Cucchetto <[email protected]>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+#include "nimproject.h"
#include "nimrunconfiguration.h"
-#include "nimbuildconfiguration.h"
#include "../nimconstants.h"
#include "../nimtr.h"
#include <projectexplorer/buildsystem.h>
#include <projectexplorer/runconfigurationaspects.h>
+#include <projectexplorer/target.h>
#include <utils/qtcassert.h>