forked from qt-creator/qt-creator
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:
209
src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp
Normal file
209
src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp
Normal 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
|
Reference in New Issue
Block a user