2016-01-15 14:57:40 +01:00
|
|
|
/****************************************************************************
|
2011-11-29 14:19:28 +01:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** Copyright (C) 2016 Openismus GmbH.
|
|
|
|
** Author: Peter Penz (ppenz@openismus.com)
|
|
|
|
** Author: Patricia Santana Cruz (patriciasantanacruz@gmail.com)
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2011-11-29 14:19:28 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2011-11-29 14:19:28 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** 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
|
2016-01-15 14:57:40 +01:00
|
|
|
** 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.
|
2011-11-29 14:19:28 +01:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** 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.
|
2011-11-29 14:19:28 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2011-11-29 14:19:28 +01:00
|
|
|
|
|
|
|
#include "autotoolsproject.h"
|
2012-04-24 15:49:09 +02:00
|
|
|
#include "autotoolsbuildconfiguration.h"
|
2011-11-29 14:19:28 +01:00
|
|
|
#include "autotoolsprojectconstants.h"
|
|
|
|
#include "autotoolsprojectnode.h"
|
|
|
|
#include "autotoolsopenprojectwizard.h"
|
|
|
|
#include "makestep.h"
|
|
|
|
#include "makefileparserthread.h"
|
|
|
|
|
|
|
|
#include <projectexplorer/abi.h>
|
2013-03-25 17:13:18 +01:00
|
|
|
#include <projectexplorer/toolchain.h>
|
2012-09-03 18:31:44 +02:00
|
|
|
#include <projectexplorer/kitmanager.h>
|
|
|
|
#include <projectexplorer/kitinformation.h>
|
2011-11-29 14:19:28 +01:00
|
|
|
#include <projectexplorer/buildconfiguration.h>
|
|
|
|
#include <projectexplorer/buildsteplist.h>
|
|
|
|
#include <projectexplorer/projectexplorerconstants.h>
|
2012-04-24 15:49:09 +02:00
|
|
|
#include <projectexplorer/target.h>
|
2013-03-25 17:13:18 +01:00
|
|
|
#include <projectexplorer/headerpath.h>
|
2011-11-29 14:19:28 +01:00
|
|
|
#include <extensionsystem/pluginmanager.h>
|
2014-09-15 00:12:27 +02:00
|
|
|
#include <cpptools/cppmodelmanager.h>
|
2016-01-12 12:51:33 +01:00
|
|
|
#include <cpptools/projectinfo.h>
|
2017-02-06 16:59:53 +01:00
|
|
|
#include <cpptools/cppprojectupdater.h>
|
2011-11-29 14:19:28 +01:00
|
|
|
#include <coreplugin/icore.h>
|
2013-03-26 11:32:14 +01:00
|
|
|
#include <coreplugin/icontext.h>
|
2015-04-21 09:08:07 +03:00
|
|
|
#include <qtsupport/baseqtversion.h>
|
|
|
|
#include <qtsupport/qtkitinformation.h>
|
2016-09-30 21:10:32 +02:00
|
|
|
#include <utils/algorithm.h>
|
2011-11-29 14:19:28 +01:00
|
|
|
#include <utils/qtcassert.h>
|
2012-07-25 09:48:48 +02:00
|
|
|
#include <utils/filesystemwatcher.h>
|
2011-11-29 14:19:28 +01:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QFileInfo>
|
|
|
|
#include <QTimer>
|
|
|
|
#include <QPointer>
|
|
|
|
#include <QApplication>
|
|
|
|
#include <QCursor>
|
|
|
|
#include <QLabel>
|
|
|
|
#include <QPushButton>
|
|
|
|
#include <QVBoxLayout>
|
2011-11-29 14:19:28 +01:00
|
|
|
|
|
|
|
using namespace AutotoolsProjectManager;
|
|
|
|
using namespace AutotoolsProjectManager::Internal;
|
|
|
|
using namespace ProjectExplorer;
|
|
|
|
|
2017-03-03 18:16:34 +01:00
|
|
|
AutotoolsProject::AutotoolsProject(const Utils::FileName &fileName) :
|
2017-03-29 11:25:01 +02:00
|
|
|
Project(Constants::MAKEFILE_MIMETYPE, fileName),
|
2017-02-06 16:59:53 +01:00
|
|
|
m_fileWatcher(new Utils::FileSystemWatcher(this)),
|
|
|
|
m_cppCodeModelUpdater(new CppTools::CppProjectUpdater(this))
|
2011-11-29 14:19:28 +01:00
|
|
|
{
|
2013-09-27 16:30:20 +02:00
|
|
|
setId(Constants::AUTOTOOLS_PROJECT_ID);
|
2017-01-30 14:59:10 +01:00
|
|
|
setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
|
2017-04-07 14:35:49 +02:00
|
|
|
setDisplayName(projectDirectory().fileName());
|
2011-11-29 14:19:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
AutotoolsProject::~AutotoolsProject()
|
|
|
|
{
|
2017-02-06 16:59:53 +01:00
|
|
|
delete m_cppCodeModelUpdater;
|
|
|
|
|
2017-03-03 17:10:00 +01:00
|
|
|
setRootProjectNode(nullptr);
|
2011-11-29 14:19:28 +01:00
|
|
|
|
2017-03-03 17:10:00 +01:00
|
|
|
if (m_makefileParserThread) {
|
2011-11-29 14:19:28 +01:00
|
|
|
m_makefileParserThread->wait();
|
|
|
|
delete m_makefileParserThread;
|
2017-03-03 17:10:00 +01:00
|
|
|
m_makefileParserThread = nullptr;
|
2011-11-29 14:19:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-13 10:35:03 +02:00
|
|
|
QString AutotoolsProject::defaultBuildDirectory(const QString &projectPath)
|
|
|
|
{
|
|
|
|
return QFileInfo(projectPath).absolutePath();
|
2011-11-29 14:19:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// This function, is called at the very beginning, to
|
|
|
|
// restore the settings if there are some stored.
|
2015-05-18 16:57:29 +02:00
|
|
|
Project::RestoreResult AutotoolsProject::fromMap(const QVariantMap &map, QString *errorMessage)
|
2011-11-29 14:19:28 +01:00
|
|
|
{
|
2015-05-18 16:57:29 +02:00
|
|
|
RestoreResult result = Project::fromMap(map, errorMessage);
|
|
|
|
if (result != RestoreResult::Ok)
|
|
|
|
return result;
|
2011-11-29 14:19:28 +01:00
|
|
|
|
2015-01-30 10:19:13 +01:00
|
|
|
connect(m_fileWatcher, &Utils::FileSystemWatcher::fileChanged,
|
|
|
|
this, &AutotoolsProject::onFileChanged);
|
2011-11-29 14:19:28 +01:00
|
|
|
|
|
|
|
// Load the project tree structure.
|
2012-07-17 15:56:43 +02:00
|
|
|
loadProjectTree();
|
2012-04-24 15:49:09 +02:00
|
|
|
|
2013-08-21 12:48:46 +02:00
|
|
|
Kit *defaultKit = KitManager::defaultKit();
|
2012-09-03 18:31:44 +02:00
|
|
|
if (!activeTarget() && defaultKit)
|
|
|
|
addTarget(createTarget(defaultKit));
|
2011-11-29 14:19:28 +01:00
|
|
|
|
2015-05-18 16:57:29 +02:00
|
|
|
return RestoreResult::Ok;
|
2011-11-29 14:19:28 +01:00
|
|
|
}
|
|
|
|
|
2012-07-17 15:56:43 +02:00
|
|
|
void AutotoolsProject::loadProjectTree()
|
2011-11-29 14:19:28 +01:00
|
|
|
{
|
2017-07-13 10:51:15 +02:00
|
|
|
emitParsingStarted();
|
2017-06-13 14:41:14 +02:00
|
|
|
if (m_makefileParserThread) {
|
2011-11-29 14:19:28 +01:00
|
|
|
// The thread is still busy parsing a previus configuration.
|
|
|
|
// Wait until the thread has been finished and delete it.
|
|
|
|
// TODO: Discuss whether blocking is acceptable.
|
2015-07-09 13:30:40 +02:00
|
|
|
disconnect(m_makefileParserThread, &QThread::finished,
|
|
|
|
this, &AutotoolsProject::makefileParsingFinished);
|
2011-11-29 14:19:28 +01:00
|
|
|
m_makefileParserThread->wait();
|
|
|
|
delete m_makefileParserThread;
|
|
|
|
m_makefileParserThread = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse the makefile asynchronously in a thread
|
2016-01-08 12:12:27 +01:00
|
|
|
m_makefileParserThread = new MakefileParserThread(projectFilePath().toString());
|
2011-11-29 14:19:28 +01:00
|
|
|
|
2015-01-30 10:19:13 +01:00
|
|
|
connect(m_makefileParserThread, &MakefileParserThread::started,
|
|
|
|
this, &AutotoolsProject::makefileParsingStarted);
|
2011-11-29 14:19:28 +01:00
|
|
|
|
2015-01-30 10:19:13 +01:00
|
|
|
connect(m_makefileParserThread, &MakefileParserThread::finished,
|
|
|
|
this, &AutotoolsProject::makefileParsingFinished);
|
2011-11-29 14:19:28 +01:00
|
|
|
m_makefileParserThread->start();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AutotoolsProject::makefileParsingStarted()
|
|
|
|
{
|
|
|
|
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
|
|
|
}
|
|
|
|
|
|
|
|
void AutotoolsProject::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 AutotoolsProject::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;
|
|
|
|
|
|
|
|
QApplication::restoreOverrideCursor();
|
|
|
|
|
|
|
|
if (m_makefileParserThread->isCanceled()) {
|
|
|
|
// The parsing has been cancelled by the user. Don't show any
|
|
|
|
// project data at all.
|
|
|
|
m_makefileParserThread->deleteLater();
|
2017-06-13 14:41:14 +02:00
|
|
|
m_makefileParserThread = nullptr;
|
2011-11-29 14:19:28 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_makefileParserThread->hasError())
|
|
|
|
qWarning("Parsing of makefile contained errors.");
|
|
|
|
|
|
|
|
// Remove file watches for the current project state.
|
|
|
|
// The file watches will be added again after the parsing.
|
|
|
|
foreach (const QString& watchedFile, m_watchedFiles)
|
|
|
|
m_fileWatcher->removeFile(watchedFile);
|
|
|
|
|
|
|
|
m_watchedFiles.clear();
|
|
|
|
|
|
|
|
// Apply sources to m_files, which are returned at AutotoolsProject::files()
|
2016-01-08 12:12:27 +01:00
|
|
|
const QFileInfo fileInfo = projectFilePath().toFileInfo();
|
2011-11-29 14:19:28 +01:00
|
|
|
const QDir dir = fileInfo.absoluteDir();
|
2017-06-13 14:41:14 +02:00
|
|
|
const QStringList files = m_makefileParserThread->sources();
|
2011-11-29 14:19:28 +01:00
|
|
|
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();
|
2011-11-30 15:08:34 +01:00
|
|
|
foreach (const QString &makefile, makefiles) {
|
2017-06-13 14:41:14 +02:00
|
|
|
const QString absMakefile = dir.absoluteFilePath(makefile);
|
2011-11-29 14:19:28 +01:00
|
|
|
|
2017-06-13 14:41:14 +02:00
|
|
|
m_files.append(absMakefile);
|
|
|
|
|
|
|
|
m_fileWatcher->addFile(absMakefile, Utils::FileSystemWatcher::WatchAllChanges);
|
|
|
|
m_watchedFiles.append(absMakefile);
|
2011-11-29 14:19:28 +01:00
|
|
|
}
|
|
|
|
|
2011-11-30 15:08:34 +01:00
|
|
|
// Add configure.ac file to project and watch for changes.
|
2011-11-29 14:19:28 +01:00
|
|
|
const QLatin1String configureAc(QLatin1String("configure.ac"));
|
2012-04-03 11:53:55 +02:00
|
|
|
const QFile configureAcFile(fileInfo.absolutePath() + QLatin1Char('/') + configureAc);
|
2011-11-29 14:19:28 +01:00
|
|
|
if (configureAcFile.exists()) {
|
2017-06-13 14:41:14 +02:00
|
|
|
const QString absConfigureAc = dir.absoluteFilePath(configureAc);
|
|
|
|
m_files.append(absConfigureAc);
|
|
|
|
|
|
|
|
m_fileWatcher->addFile(absConfigureAc, Utils::FileSystemWatcher::WatchAllChanges);
|
|
|
|
m_watchedFiles.append(absConfigureAc);
|
2011-11-29 14:19:28 +01:00
|
|
|
}
|
|
|
|
|
2017-03-03 15:13:06 +01:00
|
|
|
auto newRoot = new AutotoolsProjectNode(projectDirectory());
|
2017-06-13 14:41:14 +02:00
|
|
|
for (const QString &f : m_files) {
|
|
|
|
const Utils::FileName path = Utils::FileName::fromString(f);
|
|
|
|
newRoot->addNestedNode(new FileNode(path, FileNode::fileTypeForFileName(path), false));
|
2017-03-10 17:30:40 +01:00
|
|
|
}
|
2017-03-03 15:13:06 +01:00
|
|
|
setRootProjectNode(newRoot);
|
2016-09-30 21:10:32 +02:00
|
|
|
|
2011-11-29 14:19:28 +01:00
|
|
|
updateCppCodeModel();
|
|
|
|
|
|
|
|
m_makefileParserThread->deleteLater();
|
2017-06-13 14:41:14 +02:00
|
|
|
m_makefileParserThread = nullptr;
|
2016-10-20 13:18:54 +02:00
|
|
|
|
2017-07-13 10:51:15 +02:00
|
|
|
emitParsingFinished(true);
|
2011-11-29 14:19:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void AutotoolsProject::onFileChanged(const QString &file)
|
|
|
|
{
|
|
|
|
Q_UNUSED(file);
|
2012-07-17 15:56:43 +02:00
|
|
|
loadProjectTree();
|
2011-11-29 14:19:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
QStringList AutotoolsProject::buildTargets() const
|
|
|
|
{
|
|
|
|
QStringList targets;
|
|
|
|
targets.append(QLatin1String("all"));
|
|
|
|
targets.append(QLatin1String("clean"));
|
|
|
|
return targets;
|
|
|
|
}
|
|
|
|
|
2015-07-09 01:28:04 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2011-11-29 14:19:28 +01:00
|
|
|
void AutotoolsProject::updateCppCodeModel()
|
|
|
|
{
|
2017-02-06 16:59:53 +01:00
|
|
|
const Kit *k = nullptr;
|
|
|
|
if (Target *target = activeTarget())
|
|
|
|
k = target->kit();
|
|
|
|
else
|
|
|
|
k = KitManager::defaultKit();
|
|
|
|
QTC_ASSERT(k, return);
|
|
|
|
|
|
|
|
ToolChain *cToolChain
|
|
|
|
= ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::C_LANGUAGE_ID);
|
|
|
|
ToolChain *cxxToolChain
|
|
|
|
= ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
|
2011-11-29 14:19:28 +01:00
|
|
|
|
2017-02-06 16:59:53 +01:00
|
|
|
m_cppCodeModelUpdater->cancel();
|
2014-08-19 12:00:31 +02:00
|
|
|
|
2017-02-06 16:59:53 +01:00
|
|
|
CppTools::RawProjectPart rpp;
|
2017-02-21 14:40:31 +01:00
|
|
|
rpp.setDisplayName(displayName());
|
2017-03-09 14:13:22 +01:00
|
|
|
rpp.setProjectFileLocation(projectFilePath().toString());
|
2017-01-27 12:03:33 +01:00
|
|
|
|
2015-04-21 09:08:07 +03:00
|
|
|
CppTools::ProjectPart::QtVersion activeQtVersion = CppTools::ProjectPart::NoQt;
|
2017-02-06 16:59:53 +01:00
|
|
|
if (QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(k)) {
|
2017-08-17 09:31:16 +02:00
|
|
|
if (qtVersion->qtVersion() <= QtSupport::QtVersionNumber(4,8,6))
|
|
|
|
activeQtVersion = CppTools::ProjectPart::Qt4_8_6AndOlder;
|
|
|
|
else if (qtVersion->qtVersion() < QtSupport::QtVersionNumber(5,0,0))
|
|
|
|
activeQtVersion = CppTools::ProjectPart::Qt4Latest;
|
2015-04-21 09:08:07 +03:00
|
|
|
else
|
|
|
|
activeQtVersion = CppTools::ProjectPart::Qt5;
|
|
|
|
}
|
|
|
|
|
2017-02-06 16:59:53 +01:00
|
|
|
rpp.setQtVersion(activeQtVersion);
|
2013-04-29 02:31:43 +04:00
|
|
|
const QStringList cflags = m_makefileParserThread->cflags();
|
|
|
|
QStringList cxxflags = m_makefileParserThread->cxxflags();
|
|
|
|
if (cxxflags.isEmpty())
|
|
|
|
cxxflags = cflags;
|
2017-02-06 16:59:53 +01:00
|
|
|
rpp.setFlagsForC({cToolChain, cflags});
|
|
|
|
rpp.setFlagsForCxx({cxxToolChain, cxxflags});
|
2012-04-24 15:49:09 +02:00
|
|
|
|
2015-07-09 01:28:04 +02:00
|
|
|
const QString absSrc = projectDirectory().toString();
|
|
|
|
const Target *target = activeTarget();
|
|
|
|
const QString absBuild = (target && target->activeBuildConfiguration())
|
|
|
|
? target->activeBuildConfiguration()->buildDirectory().toString() : QString();
|
|
|
|
|
2017-02-06 16:59:53 +01:00
|
|
|
rpp.setIncludePaths(filterIncludes(absSrc, absBuild, m_makefileParserThread->includePaths()));
|
2017-02-07 15:00:38 +01:00
|
|
|
rpp.setMacros(m_makefileParserThread->macros());
|
2017-02-06 16:59:53 +01:00
|
|
|
rpp.setFiles(m_files);
|
2013-04-28 19:24:49 +04:00
|
|
|
|
2017-02-06 16:59:53 +01:00
|
|
|
m_cppCodeModelUpdater->update({this, cToolChain, cxxToolChain, k, {rpp}});
|
2011-11-29 14:19:28 +01:00
|
|
|
}
|