From 01cc0e74991fd32c20847f8c02d4fc673d6bb115 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 26 Nov 2024 16:35:21 +0100 Subject: [PATCH] Autotools: Make the BuildSystem per BuildConfiguration The per-target variant is intended for project managers without build configurations. Fixes: QTCREATORBUG-32064 Change-Id: I908627dbe11a68ee7ac4cca3a10f956630008f08 Reviewed-by: hjk --- .../autotoolsprojectmanager/CMakeLists.txt | 1 - .../autotoolsbuildconfiguration.cpp | 171 +++++++++++++++- .../autotoolsbuildsystem.cpp | 187 ------------------ .../autotoolsbuildsystem.h | 12 -- .../autotoolsprojectmanager.qbs | 2 - .../autotoolsprojectplugin.cpp | 2 - 6 files changed, 170 insertions(+), 205 deletions(-) delete mode 100644 src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp delete mode 100644 src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.h diff --git a/src/plugins/autotoolsprojectmanager/CMakeLists.txt b/src/plugins/autotoolsprojectmanager/CMakeLists.txt index f78daac7e07..09ec0b2646b 100644 --- a/src/plugins/autotoolsprojectmanager/CMakeLists.txt +++ b/src/plugins/autotoolsprojectmanager/CMakeLists.txt @@ -5,7 +5,6 @@ add_qtc_plugin(AutotoolsProjectManager autogenstep.cpp autogenstep.h autoreconfstep.cpp autoreconfstep.h autotoolsbuildconfiguration.cpp autotoolsbuildconfiguration.h - autotoolsbuildsystem.cpp autotoolsbuildsystem.h autotoolsprojectconstants.h autotoolsprojectmanagertr.h autotoolsprojectplugin.cpp diff --git a/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.cpp b/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.cpp index 142794f9cee..dcce460621e 100644 --- a/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.cpp +++ b/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.cpp @@ -5,29 +5,191 @@ #include "autotoolsprojectconstants.h" #include "autotoolsprojectmanagertr.h" +#include "makefileparser.h" #include #include #include +#include #include #include #include +#include #include +#include + +#include + +#include #include using namespace ProjectExplorer; +using namespace Tasking; using namespace Utils; namespace AutotoolsProjectManager::Internal { -// AutotoolsBuildConfiguration +// AutotoolsBuildSystem +class AutotoolsBuildSystem final : public BuildSystem +{ +public: + explicit AutotoolsBuildSystem(BuildConfiguration *bc); +private: + void triggerParsing() final; + QString name() const final { return QLatin1String("autotools"); } + + /** + * Is invoked when the makefile parsing by m_makefileParserThread has + * been finished. Adds all sources and files into the project tree and + * takes care listen to file changes for Makefile.am and configure.ac + * files. + */ + void makefileParsingFinished(const MakefileParserOutputData &outputData); + + /// Return value for AutotoolsProject::files() + QStringList m_files; + + /// Responsible for parsing the makefiles asynchronously in a thread + Tasking::TaskTreeRunner m_parserRunner; + + std::unique_ptr m_cppCodeModelUpdater; +}; + +AutotoolsBuildSystem::AutotoolsBuildSystem(BuildConfiguration *bc) + : BuildSystem(bc) + , m_cppCodeModelUpdater(ProjectUpdaterFactory::createCppProjectUpdater()) +{ + connect(project(), &Project::projectFileIsDirty, this, [this] { requestParse(); }); +} + +static void parseMakefileImpl(QPromise &promise, const QString &makefile) +{ + const auto result = parseMakefile(makefile, QFuture(promise.future())); + if (result) + promise.addResult(*result); + else + promise.future().cancel(); +} + +void AutotoolsBuildSystem::triggerParsing() +{ + const Storage> storage; + + const auto onSetup = [this, storage](Async &async) { + *storage = guardParsingRun(); + async.setConcurrentCallData(parseMakefileImpl, projectFilePath().path()); + }; + const auto onDone = [this, storage](const Async &async) { + (*storage)->markAsSuccess(); + makefileParsingFinished(async.result()); + }; + + const Group recipe { + storage, + AsyncTask(onSetup, onDone, CallDoneIf::Success) + }; + m_parserRunner.start(recipe); +} + +static QStringList filterIncludes(const QString &absSrc, const QString &absBuild, + const QStringList &in) +{ + QStringList result; + for (const QString &i : in) { + QString out = i; + out.replace(QLatin1String("$(top_srcdir)"), absSrc); + out.replace(QLatin1String("$(abs_top_srcdir)"), absSrc); + + out.replace(QLatin1String("$(top_builddir)"), absBuild); + out.replace(QLatin1String("$(abs_top_builddir)"), absBuild); + + result << out; + } + return result; +} + +void AutotoolsBuildSystem::makefileParsingFinished(const MakefileParserOutputData &outputData) +{ + m_files.clear(); + + QSet filesToWatch; + + // Apply sources to m_files, which are returned at AutotoolsBuildSystem::files() + const QFileInfo fileInfo = projectFilePath().toFileInfo(); + const QDir dir = fileInfo.absoluteDir(); + const QStringList files = outputData.m_sources; + for (const QString& file : files) + m_files.append(dir.absoluteFilePath(file)); + + // Watch for changes of Makefile.am files. If a Makefile.am file + // has been changed, the project tree must be reparsed. + const QStringList makefiles = outputData.m_makefiles; + for (const QString &makefile : makefiles) { + const QString absMakefile = dir.absoluteFilePath(makefile); + + m_files.append(absMakefile); + + filesToWatch.insert(FilePath::fromString(absMakefile)); + } + + // Add configure.ac file to project and watch for changes. + const QLatin1String configureAc(QLatin1String("configure.ac")); + const QFile configureAcFile(fileInfo.absolutePath() + QLatin1Char('/') + configureAc); + if (configureAcFile.exists()) { + const QString absConfigureAc = dir.absoluteFilePath(configureAc); + m_files.append(absConfigureAc); + + filesToWatch.insert(FilePath::fromString(absConfigureAc)); + } + + auto newRoot = std::make_unique(project()->projectDirectory()); + for (const QString &f : std::as_const(m_files)) { + const FilePath path = FilePath::fromString(f); + newRoot->addNestedNode(std::make_unique(path, + FileNode::fileTypeForFileName(path))); + } + setRootProjectNode(std::move(newRoot)); + project()->setExtraProjectFiles(filesToWatch); + + QtSupport::CppKitInfo kitInfo(kit()); + QTC_ASSERT(kitInfo.isValid(), return ); + + RawProjectPart rpp; + rpp.setDisplayName(project()->displayName()); + rpp.setProjectFileLocation(projectFilePath()); + rpp.setQtVersion(kitInfo.projectPartQtVersion); + const QStringList cflags = outputData.m_cflags; + QStringList cxxflags = outputData.m_cxxflags; + if (cxxflags.isEmpty()) + cxxflags = cflags; + + const FilePath includeFileBaseDir = projectDirectory(); + rpp.setFlagsForC({kitInfo.cToolchain, cflags, includeFileBaseDir}); + rpp.setFlagsForCxx({kitInfo.cxxToolchain, cxxflags, includeFileBaseDir}); + + const QString absSrc = project()->projectDirectory().path(); + BuildConfiguration *bc = target()->activeBuildConfiguration(); + + const QString absBuild = bc ? bc->buildDirectory().path() : QString(); + + rpp.setIncludePaths(filterIncludes(absSrc, absBuild, outputData.m_includePaths)); + rpp.setMacros(outputData.m_macros); + rpp.setFiles(m_files); + + m_cppCodeModelUpdater->update({project(), kitInfo, activeParseEnvironment(), {rpp}}); + + emitBuildSystemUpdated(); +} + +// AutotoolsBuildConfiguration class AutotoolsBuildConfiguration final : public BuildConfiguration { public: AutotoolsBuildConfiguration(Target *target, Id id) : BuildConfiguration(target, id) + , m_buildSystem(new AutotoolsBuildSystem(this)) { // / is used so the un-changed check in setBuildDirectory() works correctly. // The leading / is to avoid the relative the path expansion in BuildConfiguration::buildDirectory. @@ -48,6 +210,13 @@ public: // ### Build Steps Clean ### appendInitialCleanStep(Constants::MAKE_STEP_ID); // make clean } + + ~AutotoolsBuildConfiguration() override { delete m_buildSystem; } + +private: + BuildSystem *buildSystem() const override { return m_buildSystem; } + + AutotoolsBuildSystem * const m_buildSystem; }; class AutotoolsBuildConfigurationFactory final : public BuildConfigurationFactory diff --git a/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp b/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp deleted file mode 100644 index 0c79660e377..00000000000 --- a/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright (C) 2016 Openismus GmbH. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "autotoolsbuildsystem.h" - -#include "makefileparser.h" - -#include -#include -#include -#include - -#include - -#include - -#include -#include - -using namespace ProjectExplorer; -using namespace Tasking; -using namespace Utils; - -namespace AutotoolsProjectManager::Internal { - -class AutotoolsBuildSystem final : public BuildSystem -{ -public: - explicit AutotoolsBuildSystem(Target *target); - ~AutotoolsBuildSystem() final; - -private: - void triggerParsing() final; - QString name() const final { return QLatin1String("autotools"); } - - /** - * Is invoked when the makefile parsing by m_makefileParserThread has - * been finished. Adds all sources and files into the project tree and - * takes care listen to file changes for Makefile.am and configure.ac - * files. - */ - void makefileParsingFinished(const MakefileParserOutputData &outputData); - - /// Return value for AutotoolsProject::files() - QStringList m_files; - - /// Responsible for parsing the makefiles asynchronously in a thread - Tasking::TaskTreeRunner m_parserRunner; - - std::unique_ptr m_cppCodeModelUpdater; -}; - -AutotoolsBuildSystem::AutotoolsBuildSystem(Target *target) - : BuildSystem(target) - , m_cppCodeModelUpdater(ProjectUpdaterFactory::createCppProjectUpdater()) -{ - connect(target, &Target::activeBuildConfigurationChanged, this, [this] { requestParse(); }); - connect(target->project(), &Project::projectFileIsDirty, this, [this] { requestParse(); }); -} - -AutotoolsBuildSystem::~AutotoolsBuildSystem() = default; - -static void parseMakefileImpl(QPromise &promise, const QString &makefile) -{ - const auto result = parseMakefile(makefile, QFuture(promise.future())); - if (result) - promise.addResult(*result); - else - promise.future().cancel(); -} - -void AutotoolsBuildSystem::triggerParsing() -{ - const Storage> storage; - - const auto onSetup = [this, storage](Async &async) { - *storage = guardParsingRun(); - async.setConcurrentCallData(parseMakefileImpl, projectFilePath().path()); - }; - const auto onDone = [this, storage](const Async &async) { - (*storage)->markAsSuccess(); - makefileParsingFinished(async.result()); - }; - - const Group recipe { - storage, - AsyncTask(onSetup, onDone, CallDoneIf::Success) - }; - m_parserRunner.start(recipe); -} - -static QStringList filterIncludes(const QString &absSrc, const QString &absBuild, - const QStringList &in) -{ - QStringList result; - for (const QString &i : in) { - QString out = i; - out.replace(QLatin1String("$(top_srcdir)"), absSrc); - out.replace(QLatin1String("$(abs_top_srcdir)"), absSrc); - - out.replace(QLatin1String("$(top_builddir)"), absBuild); - out.replace(QLatin1String("$(abs_top_builddir)"), absBuild); - - result << out; - } - return result; -} - -void AutotoolsBuildSystem::makefileParsingFinished(const MakefileParserOutputData &outputData) -{ - m_files.clear(); - - QSet filesToWatch; - - // Apply sources to m_files, which are returned at AutotoolsBuildSystem::files() - const QFileInfo fileInfo = projectFilePath().toFileInfo(); - const QDir dir = fileInfo.absoluteDir(); - const QStringList files = outputData.m_sources; - for (const QString& file : files) - m_files.append(dir.absoluteFilePath(file)); - - // Watch for changes of Makefile.am files. If a Makefile.am file - // has been changed, the project tree must be reparsed. - const QStringList makefiles = outputData.m_makefiles; - for (const QString &makefile : makefiles) { - const QString absMakefile = dir.absoluteFilePath(makefile); - - m_files.append(absMakefile); - - filesToWatch.insert(FilePath::fromString(absMakefile)); - } - - // Add configure.ac file to project and watch for changes. - const QLatin1String configureAc(QLatin1String("configure.ac")); - const QFile configureAcFile(fileInfo.absolutePath() + QLatin1Char('/') + configureAc); - if (configureAcFile.exists()) { - const QString absConfigureAc = dir.absoluteFilePath(configureAc); - m_files.append(absConfigureAc); - - filesToWatch.insert(FilePath::fromString(absConfigureAc)); - } - - auto newRoot = std::make_unique(project()->projectDirectory()); - for (const QString &f : std::as_const(m_files)) { - const FilePath path = FilePath::fromString(f); - newRoot->addNestedNode(std::make_unique(path, - FileNode::fileTypeForFileName(path))); - } - setRootProjectNode(std::move(newRoot)); - project()->setExtraProjectFiles(filesToWatch); - - QtSupport::CppKitInfo kitInfo(kit()); - QTC_ASSERT(kitInfo.isValid(), return ); - - RawProjectPart rpp; - rpp.setDisplayName(project()->displayName()); - rpp.setProjectFileLocation(projectFilePath()); - rpp.setQtVersion(kitInfo.projectPartQtVersion); - const QStringList cflags = outputData.m_cflags; - QStringList cxxflags = outputData.m_cxxflags; - if (cxxflags.isEmpty()) - cxxflags = cflags; - - const FilePath includeFileBaseDir = projectDirectory(); - rpp.setFlagsForC({kitInfo.cToolchain, cflags, includeFileBaseDir}); - rpp.setFlagsForCxx({kitInfo.cxxToolchain, cxxflags, includeFileBaseDir}); - - const QString absSrc = project()->projectDirectory().path(); - BuildConfiguration *bc = target()->activeBuildConfiguration(); - - const QString absBuild = bc ? bc->buildDirectory().path() : QString(); - - rpp.setIncludePaths(filterIncludes(absSrc, absBuild, outputData.m_includePaths)); - rpp.setMacros(outputData.m_macros); - rpp.setFiles(m_files); - - m_cppCodeModelUpdater->update({project(), kitInfo, activeParseEnvironment(), {rpp}}); - - emitBuildSystemUpdated(); -} - -BuildSystem *createAutotoolsBuildSystem(Target *target) -{ - return new AutotoolsBuildSystem(target); -} - -} // AutotoolsProjectManager::Internal diff --git a/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.h b/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.h deleted file mode 100644 index 25cd6e829e3..00000000000 --- a/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.h +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (C) 2016 Openismus GmbH. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include - -namespace AutotoolsProjectManager::Internal { - -ProjectExplorer::BuildSystem *createAutotoolsBuildSystem(ProjectExplorer::Target *target); - -} // AutotoolsProjectManager::Internal diff --git a/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.qbs b/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.qbs index cefd8722c21..ae276372430 100644 --- a/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.qbs +++ b/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.qbs @@ -17,8 +17,6 @@ QtcPlugin { "autoreconfstep.h", "autotoolsbuildconfiguration.cpp", "autotoolsbuildconfiguration.h", - "autotoolsbuildsystem.cpp", - "autotoolsbuildsystem.h", "autotoolsprojectconstants.h", "autotoolsprojectmanagertr.h", "autotoolsprojectplugin.cpp", diff --git a/src/plugins/autotoolsprojectmanager/autotoolsprojectplugin.cpp b/src/plugins/autotoolsprojectmanager/autotoolsprojectplugin.cpp index 212f0cdb666..8bf0ecfe171 100644 --- a/src/plugins/autotoolsprojectmanager/autotoolsprojectplugin.cpp +++ b/src/plugins/autotoolsprojectmanager/autotoolsprojectplugin.cpp @@ -4,7 +4,6 @@ #include "autogenstep.h" #include "autoreconfstep.h" #include "autotoolsbuildconfiguration.h" -#include "autotoolsbuildsystem.h" #include "autotoolsprojectconstants.h" #include "configurestep.h" #include "makestep.h" @@ -41,7 +40,6 @@ public: setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID)); setDisplayName(projectDirectory().fileName()); setHasMakeInstallEquivalent(true); - setBuildSystemCreator(&createAutotoolsBuildSystem); } };