From b7e4046a173a2c42ede92934cc05c0f76486db5e Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Fri, 9 Aug 2019 11:22:49 +0200 Subject: [PATCH] ProjectExplorer: Add BuildSystem class Add a class to abstract out the BuildSystem from the Project. Thie idea is to make a Project have-a BuildSystem, so that it can stop being one. The Projects in the different ProjectManagers will get much simpler that way (and many will only consist of a constructor with some setter calls) and handles all the interactions between the rest of Qt Creator and the project. The complex code to interact with the build systems is then separate from that. Change-Id: I3bbb000bb1aed91f0b547ac493f743ede8afb8cd Reviewed-by: Christian Kandeler --- .../cmakeprojectmanager/builddirmanager.cpp | 57 +++++++-- .../cmakeprojectmanager/builddirmanager.h | 43 ++++--- .../cmakebuildconfiguration.cpp | 13 +- .../cmakeprojectmanager/cmakebuildsystem.cpp | 114 +----------------- .../cmakeprojectmanager/cmakebuildsystem.h | 89 +------------- .../cmakeprojectmanager/cmakeproject.cpp | 4 +- .../cmakeprojectmanager/cmakeproject.h | 13 +- .../cmakeprojectmanager.cpp | 7 +- src/plugins/projectexplorer/CMakeLists.txt | 1 + src/plugins/projectexplorer/buildsystem.cpp | 102 ++++++++++++++++ src/plugins/projectexplorer/buildsystem.h | 111 +++++++++++++++++ src/plugins/projectexplorer/project.cpp | 13 ++ src/plugins/projectexplorer/project.h | 7 +- .../projectexplorer/projectexplorer.pro | 2 + .../projectexplorer/projectexplorer.qbs | 1 + 15 files changed, 324 insertions(+), 253 deletions(-) create mode 100644 src/plugins/projectexplorer/buildsystem.cpp create mode 100644 src/plugins/projectexplorer/buildsystem.h diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.cpp b/src/plugins/cmakeprojectmanager/builddirmanager.cpp index be570ad6812..4e3a67e3397 100644 --- a/src/plugins/cmakeprojectmanager/builddirmanager.cpp +++ b/src/plugins/cmakeprojectmanager/builddirmanager.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -95,6 +96,18 @@ Utils::FilePath BuildDirManager::workDirectory(const BuildDirParameters ¶met return Utils::FilePath::fromString(tmpDirIt->second->path()); } +void BuildDirManager::updateReparseParameters(const int parameters) +{ + m_reparseParameters |= parameters; +} + +int BuildDirManager::takeReparseParameters() +{ + int result = m_reparseParameters; + m_reparseParameters = REPARSE_DEFAULT; + return result; +} + void BuildDirManager::emitDataAvailable() { if (!isParsing()) @@ -108,6 +121,14 @@ void BuildDirManager::emitErrorOccured(const QString &message) const m_isHandlingError = false; } +void BuildDirManager::emitReparseRequest() const +{ + if (m_reparseParameters & REPARSE_URGENT) + emit requestReparse(); + else + emit requestDelayedReparse(); +} + void BuildDirManager::updateReaderType(const BuildDirParameters &p, std::function todo) { @@ -208,7 +229,7 @@ void BuildDirManager::stopParsingAndClearState() } void BuildDirManager::setParametersAndRequestParse(const BuildDirParameters ¶meters, - int reparseOptions) + const int reparseParameters) { if (!parameters.cmakeTool()) { TaskHub::addTask(Task::Error, @@ -222,9 +243,9 @@ void BuildDirManager::setParametersAndRequestParse(const BuildDirParameters &par m_parameters = parameters; m_parameters.workDirectory = workDirectory(parameters); + updateReparseParameters(reparseParameters); - updateReaderType(m_parameters, - [this, reparseOptions]() { emit requestReparse(reparseOptions); }); + updateReaderType(m_parameters, [this]() { emitReparseRequest(); }); } CMakeBuildConfiguration *BuildDirManager::buildConfiguration() const @@ -248,7 +269,8 @@ void BuildDirManager::becameDirty() if (!tool->isAutoRun()) return; - emit requestReparse(REPARSE_CHECK_CONFIGURATION | REPARSE_SCAN); + updateReparseParameters(REPARSE_CHECK_CONFIGURATION | REPARSE_SCAN); + emit requestReparse(); } void BuildDirManager::resetData() @@ -276,19 +298,30 @@ bool BuildDirManager::persistCMakeState() return true; } -void BuildDirManager::parse(int reparseParameters) +void BuildDirManager::requestFilesystemScan() { - qCDebug(cmakeBuildDirManagerLog) - << "Parse called with flags:" << flagsString(reparseParameters); + updateReparseParameters(REPARSE_SCAN); +} +bool BuildDirManager::isFilesystemScanRequested() const +{ + return m_reparseParameters & REPARSE_SCAN; +} + +void BuildDirManager::parse() +{ QTC_ASSERT(m_parameters.isValid(), return ); QTC_ASSERT(m_reader, return); - QTC_ASSERT((reparseParameters & REPARSE_IGNORE) == 0, return); m_reader->stop(); TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM); + int reparseParameters = takeReparseParameters(); + + qCDebug(cmakeBuildDirManagerLog) + << "Parse called with flags:" << flagsString(reparseParameters); + const QString cache = m_parameters.workDirectory.pathAppended("CMakeCache.txt").toString(); if (!QFileInfo::exists(cache)) { reparseParameters |= REPARSE_FORCE_CONFIGURATION | REPARSE_FORCE_CMAKE_RUN; @@ -323,8 +356,10 @@ QVector BuildDirManager::takeProjectFilesToWatch() if (!toWatch.isEmpty()) { connect(project(), &Project::projectFileIsDirty, this, [this]() { - if (m_parameters.cmakeTool() && m_parameters.cmakeTool()->isAutoRun()) - requestReparse(REPARSE_DEFAULT); + if (m_parameters.cmakeTool() && m_parameters.cmakeTool()->isAutoRun()) { + updateReparseParameters(REPARSE_DEFAULT); + emit requestReparse(); + } }); } else { disconnect(project(), nullptr, this, nullptr); @@ -452,8 +487,6 @@ QString BuildDirManager::flagsString(int reparseFlags) result += " CHECK_CONFIG"; if (reparseFlags & REPARSE_SCAN) result += " SCAN"; - if (reparseFlags & REPARSE_IGNORE) - result += " IGNORE"; } return result.trimmed(); } diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.h b/src/plugins/cmakeprojectmanager/builddirmanager.h index 99a1e7adb0b..136ebc1c686 100644 --- a/src/plugins/cmakeprojectmanager/builddirmanager.h +++ b/src/plugins/cmakeprojectmanager/builddirmanager.h @@ -60,6 +60,17 @@ class BuildDirManager : public QObject Q_OBJECT public: + enum ReparseParameters { + REPARSE_DEFAULT = 0, // Nothing special:-) + REPARSE_FORCE_CMAKE_RUN = (1 << 0), // Force cmake to run + REPARSE_FORCE_CONFIGURATION = (1 << 1), // Force configuration arguments to cmake + REPARSE_CHECK_CONFIGURATION = (1 << 2), // Check for on-disk config and QtC config diff + REPARSE_SCAN = (1 << 3), // Run filesystem scan + REPARSE_URGENT = (1 << 4), // Do not delay the parser run by 1s + }; + + static QString flagsString(int reparseFlags); + BuildDirManager(CMakeProject *project); ~BuildDirManager() final; @@ -67,7 +78,8 @@ public: void stopParsingAndClearState(); - void setParametersAndRequestParse(const BuildDirParameters ¶meters, int reparseOptions); + void setParametersAndRequestParse(const BuildDirParameters ¶meters, + const int reparseOptions); // nullptr if the BC is not active anymore! CMakeBuildConfiguration *buildConfiguration() const; CMakeProject *project() const {return m_project; } @@ -78,7 +90,9 @@ public: void resetData(); bool persistCMakeState(); - void parse(int reparseParameters); + void requestFilesystemScan(); + bool isFilesystemScanRequested() const; + void parse(); QVector takeProjectFilesToWatch(); std::unique_ptr generateProjectTree(const QList &allFiles, @@ -91,32 +105,20 @@ public: static CMakeConfig parseCMakeConfiguration(const Utils::FilePath &cacheFile, QString *errorMessage); - enum ReparseParameters { - REPARSE_DEFAULT = BuildSystem::PARAM_DEFAULT, // use defaults - REPARSE_URGENT = BuildSystem::PARAM_URGENT, // Do not wait for more requests, start ASAP - REPARSE_IGNORE = BuildSystem::PARAM_IGNORE, - - REPARSE_FORCE_CMAKE_RUN = (1 - << (BuildSystem::PARAM_CUSTOM_OFFSET + 0)), // Force cmake to run - REPARSE_FORCE_CONFIGURATION = (1 << (BuildSystem::PARAM_CUSTOM_OFFSET - + 1)), // Force configuration arguments to cmake - REPARSE_CHECK_CONFIGURATION - = (1 << (BuildSystem::PARAM_CUSTOM_OFFSET - + 2)), // Check and warn if on-disk config and QtC config differ - REPARSE_SCAN = (1 << (BuildSystem::PARAM_CUSTOM_OFFSET + 3)), // Run filesystem scan - }; - - static QString flagsString(int reparseFlags); - signals: - void requestReparse(int reparseParameters) const; + void requestReparse() const; + void requestDelayedReparse() const; void parsingStarted() const; void dataAvailable() const; void errorOccured(const QString &err) const; private: + void updateReparseParameters(const int parameters); + int takeReparseParameters(); + void emitDataAvailable(); void emitErrorOccured(const QString &message) const; + void emitReparseRequest() const; bool checkConfiguration(); Utils::FilePath workDirectory(const BuildDirParameters ¶meters) const; @@ -129,6 +131,7 @@ private: void becameDirty(); BuildDirParameters m_parameters; + int m_reparseParameters; CMakeProject *m_project = nullptr; mutable std::unordered_map> m_buildDirToTempDir; mutable std::unique_ptr m_reader; diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index 2a96c9b1f43..26c7327a0bc 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -93,12 +93,13 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *parent, Core::Id id) BuildSystem *bs = qobject_cast(project()->buildSystem()); // BuildDirManager: - connect(&m_buildDirManager, &BuildDirManager::requestReparse, this, [this, bs](int options) { - if (isActive()) { - qCDebug(cmakeBuildConfigurationLog) - << "Passing on reparse request with flags" << BuildDirManager::flagsString(options); - bs->requestParse(options); - } + connect(&m_buildDirManager, &BuildDirManager::requestReparse, this, [this, bs]() { + if (isActive()) + bs->requestParse(); + }); + connect(&m_buildDirManager, &BuildDirManager::requestDelayedReparse, this, [this, bs]() { + if (isActive()) + bs->requestDelayedParse(); }); connect(&m_buildDirManager, &BuildDirManager::dataAvailable, diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp index a0203742965..200f8018541 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp @@ -30,38 +30,6 @@ #include "cmakeprojectconstants.h" #include "cmakeprojectnodes.h" -#if 0 -#include "cmakebuildstep.h" -#include "cmakekitinformation.h" -#include "cmakeprojectmanager.h" -#include "cmakeprojectnodes.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#endif - #include #include #include @@ -79,85 +47,12 @@ using namespace ProjectExplorer; using namespace Utils; -namespace { - -CMakeProjectManager::Internal::CMakeBuildConfiguration *activeBc(Project *p) -{ - if (!p) - return nullptr; - - return qobject_cast( - p->activeTarget() ? p->activeTarget()->activeBuildConfiguration() : nullptr); -} - -} // namespace - namespace CMakeProjectManager { using namespace Internal; Q_LOGGING_CATEGORY(cmakeBuildSystemLog, "qtc.cmake.buildsystem", QtWarningMsg); -// -------------------------------------------------------------------- -// BuildSystem: -// -------------------------------------------------------------------- - -BuildSystem::BuildSystem(Project *project) - : m_project(project) -{ - QTC_CHECK(project); - - // Timer: - m_delayedParsingTimer.setSingleShot(true); - - connect(&m_delayedParsingTimer, &QTimer::timeout, this, &BuildSystem::triggerParsing); -} - -BuildSystem::~BuildSystem() = default; - -Project *BuildSystem::project() const -{ - return m_project; -} - -bool BuildSystem::isWaitingForParse() const -{ - return m_delayedParsingTimer.isActive(); -} - -void BuildSystem::requestParse(int reparseParameters) -{ - QTC_ASSERT(!(reparseParameters & PARAM_ERROR), return ); - if (reparseParameters & PARAM_IGNORE) - return; - - m_delayedParsingTimer.setInterval((reparseParameters & PARAM_URGENT) ? 0 : 1000); - m_delayedParsingTimer.start(); - m_delayedParsingParameters = m_delayedParsingParameters | reparseParameters; -} - -void BuildSystem::triggerParsing() -{ - int parameters = m_delayedParsingParameters; - m_delayedParsingParameters = BuildSystem::PARAM_DEFAULT; - - QTC_CHECK(!m_project->isParsing()); - QTC_ASSERT((parameters & BuildSystem::PARAM_ERROR) == 0, return ); - if (parameters & BuildSystem::PARAM_IGNORE) - return; - - // Clear buildsystem specific parameters before passing them on! - parameters = parameters - & ~(BuildSystem::PARAM_ERROR | BuildSystem::PARAM_IGNORE - | BuildSystem::PARAM_URGENT); - - { - ParsingContext ctx(m_project->guardParsingRun(), parameters, m_project, activeBc(m_project)); - if (validateParsingContext(ctx)) - parseProject(std::move(ctx)); - } -} - // -------------------------------------------------------------------- // CMakeBuildSystem: // -------------------------------------------------------------------- @@ -227,13 +122,12 @@ void CMakeBuildSystem::parseProject(ParsingContext &&ctx) m_currentContext = std::move(ctx); auto bc = qobject_cast(m_currentContext.buildConfiguration); - - int parameters = m_currentContext.parameters; + QTC_ASSERT(bc, return ); if (m_allFiles.isEmpty()) - parameters |= BuildDirManager::REPARSE_SCAN; + bc->m_buildDirManager.requestFilesystemScan(); - m_waitingForScan = parameters & BuildDirManager::REPARSE_SCAN; + m_waitingForScan = bc->m_buildDirManager.isFilesystemScanRequested(); m_waitingForParse = true; m_combinedScanAndParseResult = true; @@ -246,7 +140,7 @@ void CMakeBuildSystem::parseProject(ParsingContext &&ctx) "CMake.Scan.Tree"); } - bc->m_buildDirManager.parse(parameters); + bc->m_buildDirManager.parse(); } void CMakeBuildSystem::handleTreeScanningFinished() diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.h b/src/plugins/cmakeprojectmanager/cmakebuildsystem.h index c30a29d5a78..1170a38e120 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.h @@ -25,20 +25,12 @@ #pragma once -#include -#include - -#include +#include namespace CppTools { class CppProjectUpdater; } // namespace CppTools -namespace ProjectExplorer { -class BuildConfiguration; -class ExtraCompiler; -} // namespace ProjectExplorer - namespace CMakeProjectManager { class CMakeProject; @@ -47,88 +39,11 @@ namespace Internal { class CMakeBuildConfiguration; } // namespace Internal -// -------------------------------------------------------------------- -// BuildSystem: -// -------------------------------------------------------------------- - -class BuildSystem : public QObject -{ - Q_OBJECT - -public: - const static int PARAM_CUSTOM_OFFSET = 3; - enum Parameters : int { - PARAM_DEFAULT = 0, // use defaults - - PARAM_IGNORE = (1 << (PARAM_CUSTOM_OFFSET - 3)), // Ignore this request without raising a fuss - PARAM_ERROR = (1 << (PARAM_CUSTOM_OFFSET - 2)), // Ignore this request and warn - - PARAM_URGENT = (1 << (PARAM_CUSTOM_OFFSET - 1)), // Do not wait for more requests, start ASAP - }; - - explicit BuildSystem(ProjectExplorer::Project *project); - ~BuildSystem() override; - - BuildSystem(const BuildSystem &other) = delete; - - ProjectExplorer::Project *project() const; - - bool isWaitingForParse() const; - void requestParse(int reparseParameters); // request a (delayed!) parser run. - -protected: - class ParsingContext - { - public: - ParsingContext() = default; - - ParsingContext(const ParsingContext &other) = delete; - ParsingContext &operator=(const ParsingContext &other) = delete; - ParsingContext(ParsingContext &&other) = default; - ParsingContext &operator=(ParsingContext &&other) = default; - - ProjectExplorer::Project::ParseGuard guard; - - int parameters = PARAM_DEFAULT; - ProjectExplorer::Project *project = nullptr; - ProjectExplorer::BuildConfiguration *buildConfiguration = nullptr; - - private: - ParsingContext(ProjectExplorer::Project::ParseGuard &&g, - int params, - ProjectExplorer::Project *p, - ProjectExplorer::BuildConfiguration *bc) - : guard(std::move(g)) - , parameters(params) - , project(p) - , buildConfiguration(bc) - {} - - friend class BuildSystem; - }; - - virtual bool validateParsingContext(const ParsingContext &ctx) - { - Q_UNUSED(ctx) - return true; - } - - virtual void parseProject(ParsingContext &&ctx) = 0; // actual code to parse project - -private: - void triggerParsing(); - - ProjectExplorer::Project *m_project; - - QTimer m_delayedParsingTimer; - int m_delayedParsingParameters = PARAM_DEFAULT; -}; - // -------------------------------------------------------------------- // CMakeBuildSystem: // -------------------------------------------------------------------- -class CMakeBuildSystem : public BuildSystem +class CMakeBuildSystem : public ProjectExplorer::BuildSystem { Q_OBJECT diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index caa8e0eb130..13dae9c4406 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -85,14 +85,14 @@ static CMakeBuildConfiguration *activeBc(const CMakeProject *p) CMakeProject::CMakeProject(const FilePath &fileName) : Project(Constants::CMAKEMIMETYPE, fileName) { - m_buildsystem = std::make_unique(this); - setId(CMakeProjectManager::Constants::CMAKEPROJECT_ID); setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID)); setDisplayName(projectDirectory().fileName()); setCanBuildProducts(); setKnowsAllBuildExecutables(false); setHasMakeInstallEquivalent(true); + + setBuildSystem(std::make_unique(this)); } CMakeProject::~CMakeProject() = default; diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h index 75a8ed81c41..cf7a1f058ee 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.h +++ b/src/plugins/cmakeprojectmanager/cmakeproject.h @@ -32,10 +32,8 @@ #include "cmakebuildtarget.h" #include "cmakeprojectimporter.h" -#include +#include #include -#include -#include #include @@ -50,8 +48,6 @@ namespace ProjectExplorer { class FileNode; } namespace CMakeProjectManager { -class BuildSystem; - namespace Internal { class CMakeBuildConfiguration; class CMakeBuildSettingsWidget; @@ -66,8 +62,6 @@ public: explicit CMakeProject(const Utils::FilePath &filename); ~CMakeProject() final; - BuildSystem *buildSystem() const { return m_buildsystem.get(); } - ProjectExplorer::Tasks projectIssues(const ProjectExplorer::Kit *k) const final; void runCMake(); @@ -94,11 +88,6 @@ private: mutable std::unique_ptr m_projectImporter; - std::unique_ptr m_buildsystem; - - // friend class Internal::CMakeBuildConfiguration; - // friend class Internal::CMakeBuildSettingsWidget; - friend class CMakeBuildSystem; }; diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp index 21be7d1995d..10f8202ad5d 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp @@ -32,12 +32,13 @@ #include "cmaketoolmanager.h" #include "cmakeprojectnodes.h" -#include -#include +#include #include #include -#include #include +#include +#include +#include #include #include #include diff --git a/src/plugins/projectexplorer/CMakeLists.txt b/src/plugins/projectexplorer/CMakeLists.txt index 2e065ea3bf4..0476aea722f 100644 --- a/src/plugins/projectexplorer/CMakeLists.txt +++ b/src/plugins/projectexplorer/CMakeLists.txt @@ -21,6 +21,7 @@ add_qtc_plugin(ProjectExplorer buildstep.cpp buildstep.h buildsteplist.cpp buildsteplist.h buildstepspage.cpp buildstepspage.h + buildsystem.cpp buildsystem.h buildtargetinfo.h clangparser.cpp clangparser.h codestylesettingspropertiespage.cpp codestylesettingspropertiespage.h codestylesettingspropertiespage.ui diff --git a/src/plugins/projectexplorer/buildsystem.cpp b/src/plugins/projectexplorer/buildsystem.cpp new file mode 100644 index 00000000000..84c9b123811 --- /dev/null +++ b/src/plugins/projectexplorer/buildsystem.cpp @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "buildsystem.h" + +#include "buildconfiguration.h" +#include "target.h" + +#include + +using namespace Utils; + +namespace ProjectExplorer { + +// -------------------------------------------------------------------- +// BuildSystem: +// -------------------------------------------------------------------- + +BuildSystem::BuildSystem(Project *project) + : m_project(project) +{ + QTC_CHECK(project); + + // Timer: + m_delayedParsingTimer.setSingleShot(true); + + connect(&m_delayedParsingTimer, &QTimer::timeout, this, &BuildSystem::triggerParsing); +} + +Project *BuildSystem::project() const +{ + return m_project; +} + +bool BuildSystem::isWaitingForParse() const +{ + return m_delayedParsingTimer.isActive(); +} + +void BuildSystem::requestParse() +{ + requestParse(0); +} + +void BuildSystem::requestDelayedParse() +{ + requestParse(1000); +} + +void BuildSystem::requestParse(int delay) +{ + m_delayedParsingTimer.setInterval(delay); + m_delayedParsingTimer.start(); +} + +void BuildSystem::triggerParsing() +{ + QTC_CHECK(!project()->isParsing()); + + Project *p = project(); + Target *t = p->activeTarget(); + BuildConfiguration *bc = t ? t->activeBuildConfiguration() : nullptr; + + MacroExpander *e = nullptr; + if (bc) + e = bc->macroExpander(); + else if (t) + e = t->macroExpander(); + else + e = p->macroExpander(); + + Utils::Environment env = p->activeParseEnvironment(); + + ParsingContext ctx(p->guardParsingRun(), p, bc, e, env); + + if (validateParsingContext(ctx)) + parseProject(std::move(ctx)); +} + +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/buildsystem.h b/src/plugins/projectexplorer/buildsystem.h new file mode 100644 index 00000000000..dd8456074c8 --- /dev/null +++ b/src/plugins/projectexplorer/buildsystem.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "projectexplorer_export.h" + +#include "project.h" +#include "treescanner.h" + +#include + +namespace ProjectExplorer { + +class BuildConfiguration; +class ExtraCompiler; + +// -------------------------------------------------------------------- +// BuildSystem: +// -------------------------------------------------------------------- + +class PROJECTEXPLORER_EXPORT BuildSystem : public QObject +{ + Q_OBJECT + +public: + explicit BuildSystem(Project *project); + + BuildSystem(const BuildSystem &other) = delete; + + Project *project() const; + + bool isWaitingForParse() const; + + void requestParse(); + void requestDelayedParse(); + +protected: + class ParsingContext + { + public: + ParsingContext() = default; + + ParsingContext(const ParsingContext &other) = delete; + ParsingContext &operator=(const ParsingContext &other) = delete; + ParsingContext(ParsingContext &&other) = default; + ParsingContext &operator=(ParsingContext &&other) = default; + + Project::ParseGuard guard; + + Project *project = nullptr; + BuildConfiguration *buildConfiguration = nullptr; + Utils::MacroExpander *expander = nullptr; + Utils::Environment environment; + + private: + ParsingContext(Project::ParseGuard &&g, + Project *p, + BuildConfiguration *bc, + Utils::MacroExpander *e, + Utils::Environment &env) + : guard(std::move(g)) + , project(p) + , buildConfiguration(bc) + , expander(e) + , environment(env) + {} + + friend class BuildSystem; + }; + + virtual bool validateParsingContext(const ParsingContext &ctx) + { + Q_UNUSED(ctx) + return true; + } + + virtual void parseProject(ParsingContext &&ctx) = 0; // actual code to parse project + +private: + void requestParse(int delay); // request a (delayed!) parser run. + void triggerParsing(); + + QTimer m_delayedParsingTimer; + + Project *m_project; +}; + +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index d881c80ce06..1d7cd11d9cc 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -27,6 +27,7 @@ #include "buildconfiguration.h" #include "buildinfo.h" +#include "buildsystem.h" #include "deployconfiguration.h" #include "editorconfiguration.h" #include "kit.h" @@ -182,6 +183,7 @@ public: bool m_knowsAllBuildExecutables = true; bool m_hasMakeInstallEquivalent = false; bool m_needsBuildConfigurations = true; + std::unique_ptr m_buildSystem; std::unique_ptr m_document; std::vector> m_extraProjectDocuments; std::unique_ptr m_rootProjectNode; @@ -253,6 +255,11 @@ bool Project::canBuildProducts() const return d->m_canBuildProducts; } +BuildSystem *Project::buildSystem() const +{ + return d->m_buildSystem.get(); +} + Utils::FilePath Project::projectFilePath() const { QTC_ASSERT(d->m_document, return Utils::FilePath()); @@ -879,6 +886,12 @@ Utils::Environment Project::activeParseEnvironment() const return result; } +void Project::setBuildSystem(std::unique_ptr &&bs) +{ + QTC_ASSERT(!bs->parent(), bs->setParent(nullptr)); + d->m_buildSystem = std::move(bs); +} + Core::Context Project::projectContext() const { return Core::Context(d->m_id); diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h index 082010d6c3e..c4f29f0d1a8 100644 --- a/src/plugins/projectexplorer/project.h +++ b/src/plugins/projectexplorer/project.h @@ -50,6 +50,7 @@ class MacroExpander; namespace ProjectExplorer { class BuildInfo; +class BuildSystem; class ContainerNode; class EditorConfiguration; class FolderNode; @@ -85,6 +86,8 @@ public: QString mimeType() const; bool canBuildProducts() const; + BuildSystem *buildSystem() const; + Utils::FilePath projectFilePath() const; Utils::FilePath projectDirectory() const; static Utils::FilePath projectDirectory(const Utils::FilePath &top); @@ -234,6 +237,8 @@ public: // as the main project file. void setExtraProjectFiles(const QVector &projectDocumentPaths); + Utils::Environment activeParseEnvironment() const; + signals: void projectFileIsDirty(const Utils::FilePath &path); @@ -294,7 +299,7 @@ protected: static ProjectExplorer::Task createProjectTask(ProjectExplorer::Task::TaskType type, const QString &description); - Utils::Environment activeParseEnvironment() const; + void setBuildSystem(std::unique_ptr &&bs); // takes ownership! private: // Helper methods to manage parsing state and signalling diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro index 90e9ed264c9..f8d9045712f 100644 --- a/src/plugins/projectexplorer/projectexplorer.pro +++ b/src/plugins/projectexplorer/projectexplorer.pro @@ -13,6 +13,7 @@ HEADERS += projectexplorer.h \ addrunconfigdialog.h \ ansifilterparser.h \ buildinfo.h \ + buildsystem.h \ clangparser.h \ configtaskhandler.h \ desktoprunconfiguration.h \ @@ -170,6 +171,7 @@ SOURCES += projectexplorer.cpp \ addrunconfigdialog.cpp \ ansifilterparser.cpp \ buildinfo.cpp \ + buildsystem.cpp \ clangparser.cpp \ configtaskhandler.cpp \ desktoprunconfiguration.cpp \ diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs index 926e6fc0815..1708495ca25 100644 --- a/src/plugins/projectexplorer/projectexplorer.qbs +++ b/src/plugins/projectexplorer/projectexplorer.qbs @@ -40,6 +40,7 @@ Project { "buildstep.cpp", "buildstep.h", "buildsteplist.cpp", "buildsteplist.h", "buildstepspage.cpp", "buildstepspage.h", + "buildsystem.cpp", "buildsystem.h", "buildtargetinfo.h", "clangparser.cpp", "clangparser.h", "codestylesettingspropertiespage.cpp", "codestylesettingspropertiespage.h", "codestylesettingspropertiespage.ui",