Autotools: Introduce AutotoolsBuildSystem

Introduce AutotoolsBuildSystem and slim down AutotoolsProject.

Change-Id: I68296152f9ecd5d14198c8d0b36a06c2d1b162ec
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
Tobias Hunger
2019-08-13 12:47:11 +02:00
parent b7e4046a17
commit fb21b78444
15 changed files with 113 additions and 173 deletions

View File

@@ -0,0 +1,209 @@
/****************************************************************************
**
** Copyright (C) 2016 Openismus GmbH.
** Author: Peter Penz (ppenz@openismus.com)
** Author: Patricia Santana Cruz (patriciasantanacruz@gmail.com)
** 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 "autotoolsbuildsystem.h"
#include "makefileparserthread.h"
#include "makestep.h"
#include <cpptools/cppprojectupdater.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtcppkitinfo.h>
#include <utils/filesystemwatcher.h>
using namespace ProjectExplorer;
namespace AutotoolsProjectManager {
namespace Internal {
AutotoolsBuildSystem::AutotoolsBuildSystem(Project *project)
: BuildSystem(project)
, m_cppCodeModelUpdater(new CppTools::CppProjectUpdater)
{
connect(project, &Project::activeBuildConfigurationChanged, this, [this]() { requestParse(); });
connect(project, &Project::projectFileIsDirty, this, [this]() { requestParse(); });
}
AutotoolsBuildSystem::~AutotoolsBuildSystem()
{
delete m_cppCodeModelUpdater;
if (m_makefileParserThread) {
m_makefileParserThread->wait();
delete m_makefileParserThread;
m_makefileParserThread = nullptr;
}
}
void AutotoolsBuildSystem::parseProject(BuildSystem::ParsingContext &&ctx)
{
if (m_makefileParserThread) {
// The thread is still busy parsing a previous configuration.
// Wait until the thread has been finished and delete it.
// TODO: Discuss whether blocking is acceptable.
disconnect(m_makefileParserThread,
&QThread::finished,
this,
&AutotoolsBuildSystem::makefileParsingFinished);
m_makefileParserThread->wait();
delete m_makefileParserThread;
m_makefileParserThread = nullptr;
}
// Parse the makefile asynchronously in a thread
m_makefileParserThread = new MakefileParserThread(project()->projectFilePath().toString(),
std::move(ctx.guard));
connect(m_makefileParserThread,
&MakefileParserThread::finished,
this,
&AutotoolsBuildSystem::makefileParsingFinished);
m_makefileParserThread->start();
}
void AutotoolsBuildSystem::makefileParsingFinished()
{
// The finished() signal is from a previous makefile-parser-thread
// and can be skipped. This can happen, if the thread has emitted the
// finished() signal during the execution of AutotoolsBuildSystem::loadProjectTree().
// In this case the signal is in the message queue already and deleting
// the thread of course does not remove the signal again.
if (sender() != m_makefileParserThread)
return;
if (m_makefileParserThread->isCanceled()) {
// The parsing has been cancelled by the user. Don't show any
// project data at all.
m_makefileParserThread->deleteLater();
m_makefileParserThread = nullptr;
return;
}
if (m_makefileParserThread->hasError())
qWarning("Parsing of makefile contained errors.");
m_files.clear();
QVector<Utils::FilePath> filesToWatch;
// Apply sources to m_files, which are returned at AutotoolsBuildSystem::files()
const QFileInfo fileInfo = project()->projectFilePath().toFileInfo();
const QDir dir = fileInfo.absoluteDir();
const QStringList files = m_makefileParserThread->sources();
foreach (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 = m_makefileParserThread->makefiles();
foreach (const QString &makefile, makefiles) {
const QString absMakefile = dir.absoluteFilePath(makefile);
m_files.append(absMakefile);
filesToWatch.append(Utils::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.append(Utils::FilePath::fromString(absConfigureAc));
}
auto newRoot = std::make_unique<ProjectNode>(project()->projectDirectory());
for (const QString &f : m_files) {
const Utils::FilePath path = Utils::FilePath::fromString(f);
newRoot->addNestedNode(std::make_unique<FileNode>(path,
FileNode::fileTypeForFileName(path)));
}
project()->setRootProjectNode(std::move(newRoot));
project()->setExtraProjectFiles(filesToWatch);
updateCppCodeModel();
m_makefileParserThread->deleteLater();
m_makefileParserThread = nullptr;
}
static QStringList filterIncludes(const QString &absSrc, const QString &absBuild,
const QStringList &in)
{
QStringList result;
foreach (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::updateCppCodeModel()
{
QtSupport::CppKitInfo kitInfo(project());
QTC_ASSERT(kitInfo.isValid(), return );
const Utils::FilePath projectFilePath = project()->projectFilePath();
CppTools::RawProjectPart rpp;
rpp.setDisplayName(project()->displayName());
rpp.setProjectFileLocation(projectFilePath.toString());
rpp.setQtVersion(kitInfo.projectPartQtVersion);
const QStringList cflags = m_makefileParserThread->cflags();
QStringList cxxflags = m_makefileParserThread->cxxflags();
if (cxxflags.isEmpty())
cxxflags = cflags;
rpp.setFlagsForC({kitInfo.cToolChain, cflags});
rpp.setFlagsForCxx({kitInfo.cxxToolChain, cxxflags});
const QString absSrc = project()->projectDirectory().toString();
const Target *target = project()->activeTarget();
BuildConfiguration *bc = target ? target->activeBuildConfiguration() : nullptr;
const QString absBuild = bc ? bc->buildDirectory().toString() : QString();
rpp.setIncludePaths(filterIncludes(absSrc, absBuild, m_makefileParserThread->includePaths()));
rpp.setMacros(m_makefileParserThread->macros());
rpp.setFiles(m_files);
m_cppCodeModelUpdater->update({project(), kitInfo, project()->activeParseEnvironment(), {rpp}});
}
} // namespace Internal
} // namespace AutotoolsProjectManager